mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-17 21:50:35 +08:00
fix: 调整主题定制器和对话框样式,优化用户体验
This commit is contained in:
@@ -47,7 +47,7 @@ export default defineComponent({
|
||||
|
||||
// 当弹窗刚打开时,记录当前的滚动状态
|
||||
if (!wasDialogOpen && isDialogOpen.value) {
|
||||
wasScrolledBeforeDialog.value = scrollDistance.value > 0
|
||||
wasScrolledBeforeDialog.value = scrollDistance.value > 10
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +160,8 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* stylelint-disable no-descending-specificity */
|
||||
|
||||
@use '@configured-variables' as variables;
|
||||
@use '@layouts/styles/placeholders';
|
||||
@use '@layouts/styles/mixins';
|
||||
@@ -257,8 +259,8 @@ export default defineComponent({
|
||||
&.layout-vertical-nav-collapsed .layout-vertical-nav:not(.overlay-nav) {
|
||||
.nav-header {
|
||||
justify-content: center;
|
||||
padding-inline: 0;
|
||||
margin-inline: 0;
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
@@ -312,8 +314,8 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.layout-navbar {
|
||||
border-block-end: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
||||
background: rgb(var(--v-theme-background));
|
||||
border-block-end: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
||||
inline-size: 100%;
|
||||
max-inline-size: none;
|
||||
padding-inline: 0;
|
||||
@@ -324,15 +326,15 @@ export default defineComponent({
|
||||
border-radius: 0 !important;
|
||||
background: transparent !important;
|
||||
inline-size: 100%;
|
||||
max-inline-size: variables.$layout-boxed-content-width;
|
||||
margin-inline: auto;
|
||||
max-inline-size: variables.$layout-boxed-content-width;
|
||||
padding-inline: 1.5rem;
|
||||
}
|
||||
|
||||
.layout-page-content {
|
||||
inline-size: 100%;
|
||||
max-inline-size: variables.$layout-boxed-content-width;
|
||||
margin-inline: auto;
|
||||
max-inline-size: variables.$layout-boxed-content-width;
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
|
||||
@@ -371,8 +373,8 @@ export default defineComponent({
|
||||
.v-theme--transparent .layout-wrapper.layout-horizontal-nav-active .layout-navbar {
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border-block-end-color: rgba(var(--v-theme-on-surface), 0.04);
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
html[data-theme='transparent'] .layout-wrapper.layout-horizontal-nav-active .navbar-content-container,
|
||||
@@ -431,11 +433,11 @@ export default defineComponent({
|
||||
.nav-section-title,
|
||||
.nav-link > a,
|
||||
.nav-item-icon {
|
||||
color: rgba(231, 227, 252, 0.78) !important;
|
||||
color: rgba(231, 227, 252, 78%) !important;
|
||||
}
|
||||
|
||||
.nav-link > a:hover {
|
||||
background-color: rgba(231, 227, 252, 0.06);
|
||||
background-color: rgba(231, 227, 252, 6%);
|
||||
}
|
||||
|
||||
.nav-link > .router-link-exact-active {
|
||||
@@ -458,8 +460,7 @@ export default defineComponent({
|
||||
.layout-page-content {
|
||||
// display: flex;
|
||||
// 使用 clip 替代 hidden,避免 Chrome 144+ 滚动锁定问题
|
||||
overflow-x: clip;
|
||||
overflow-y: auto;
|
||||
overflow: clip auto;
|
||||
|
||||
.page-content-container {
|
||||
inline-size: 100%;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { usePWA } from '@/composables/usePWA'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useTheme } from 'vuetify'
|
||||
import { VDialog, VNavigationDrawer } from 'vuetify/components'
|
||||
import { useDisplay } from 'vuetify'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -31,6 +32,7 @@ const { isCustomized, resetSettings, setLayout, setPrimaryColor, setSemiDarkMenu
|
||||
const { appMode } = usePWA()
|
||||
const { t } = useI18n()
|
||||
const { global: globalTheme } = useTheme()
|
||||
const display = useDisplay()
|
||||
const defaultPrimaryColor = themeCustomizerPrimaryColors[0].value
|
||||
|
||||
const drawer = computed({
|
||||
@@ -41,11 +43,12 @@ const drawer = computed({
|
||||
const customizerContainer = computed(() => (appMode.value ? VDialog : VNavigationDrawer))
|
||||
|
||||
const customizerContainerProps = computed(() => {
|
||||
if (appMode.value) {
|
||||
if (appMode.value && display.mdAndDown.value) {
|
||||
return {
|
||||
class: 'theme-customizer-dialog-overlay',
|
||||
maxWidth: 420,
|
||||
scrim: true,
|
||||
fullscreen: !display.mdAndUp.value,
|
||||
scrollable: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +58,7 @@ const customizerContainerProps = computed(() => {
|
||||
scrim: false,
|
||||
temporary: true,
|
||||
width: 420,
|
||||
persistent: false,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -129,16 +133,11 @@ async function handleResetSettings() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="customizerContainer"
|
||||
v-model="drawer"
|
||||
v-bind="customizerContainerProps"
|
||||
>
|
||||
<component :is="customizerContainer" v-model="drawer" v-bind="customizerContainerProps">
|
||||
<div class="theme-customizer-panel" :class="{ 'theme-customizer-panel--dialog': appMode }">
|
||||
<div class="theme-customizer-header">
|
||||
<div class="theme-customizer-header py-5 px-4">
|
||||
<div>
|
||||
<h2 class="theme-customizer-title">{{ t('theme.customizer.title') }}</h2>
|
||||
<p class="theme-customizer-subtitle">{{ t('theme.customizer.subtitle') }}</p>
|
||||
</div>
|
||||
<div class="theme-customizer-header-actions">
|
||||
<VBadge color="error" dot :model-value="showResetBadge" location="top end" offset-x="2" offset-y="2">
|
||||
@@ -167,7 +166,6 @@ async function handleResetSettings() {
|
||||
<div
|
||||
v-for="color in themeCustomizerPrimaryColors"
|
||||
:key="color.value"
|
||||
type="button"
|
||||
class="theme-customizer-color-option"
|
||||
:class="{ 'is-active': settings.primaryColor === color.value }"
|
||||
:aria-label="t('theme.customizer.usePrimaryColor', { color: color.name })"
|
||||
@@ -177,7 +175,7 @@ async function handleResetSettings() {
|
||||
</div>
|
||||
|
||||
<div
|
||||
type="button"
|
||||
v-if="!appMode"
|
||||
class="theme-customizer-color-option theme-customizer-color-option--picker"
|
||||
:class="{
|
||||
'is-active': !themeCustomizerPrimaryColors.some(color => color.value === settings.primaryColor),
|
||||
@@ -201,7 +199,6 @@ async function handleResetSettings() {
|
||||
<div
|
||||
v-for="theme in themeOptions"
|
||||
:key="theme.value"
|
||||
type="button"
|
||||
class="theme-customizer-card-option"
|
||||
:class="{ 'is-active': settings.theme === theme.value }"
|
||||
@click="setTheme(theme.value)"
|
||||
@@ -216,7 +213,6 @@ async function handleResetSettings() {
|
||||
<div
|
||||
v-for="skin in skinOptions"
|
||||
:key="skin.value"
|
||||
type="button"
|
||||
class="theme-customizer-preview-option"
|
||||
:class="{ 'is-active': settings.skin === skin.value }"
|
||||
@click="setSkin(skin.value)"
|
||||
@@ -260,7 +256,6 @@ async function handleResetSettings() {
|
||||
<div
|
||||
v-for="layout in layoutOptions"
|
||||
:key="layout.value"
|
||||
type="button"
|
||||
class="theme-customizer-preview-option"
|
||||
:class="{ 'is-active': settings.layout === layout.value, 'is-disabled': appMode }"
|
||||
@click="handleLayoutChange(layout.value)"
|
||||
@@ -287,11 +282,13 @@ async function handleResetSettings() {
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
/* stylelint-disable no-descending-specificity */
|
||||
|
||||
.theme-customizer-drawer {
|
||||
position: fixed !important;
|
||||
z-index: 12000 !important;
|
||||
border-inline-start: 1px solid rgba(var(--v-theme-on-surface), 0.08) !important;
|
||||
block-size: 100dvh !important;
|
||||
border-inline-start: 1px solid rgba(var(--v-theme-on-surface), 0.08) !important;
|
||||
box-shadow: -2px 0 6px rgba(0, 0, 0, 10%) !important;
|
||||
inset-block: 0 !important;
|
||||
inset-inline-end: 0 !important;
|
||||
@@ -321,16 +318,11 @@ async function handleResetSettings() {
|
||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
||||
border-radius: 16px;
|
||||
background: rgb(var(--v-theme-surface));
|
||||
block-size: auto;
|
||||
box-shadow: 0 8px 22px rgba(0, 0, 0, 12%);
|
||||
inline-size: min(420px, calc(100vw - 32px));
|
||||
max-block-size: 85vh;
|
||||
max-block-size: 85dvh;
|
||||
block-size: 100dvh;
|
||||
}
|
||||
|
||||
.theme-customizer-panel--dialog .theme-customizer-body {
|
||||
max-block-size: calc(85vh - 104px);
|
||||
max-block-size: calc(85dvh - 104px);
|
||||
block-size: calc(100dvh - 80px - env(safe-area-inset-bottom) - env(safe-area-inset-top));
|
||||
}
|
||||
|
||||
.theme-customizer-drawer.v-theme--transparent,
|
||||
@@ -363,11 +355,9 @@ html[data-theme='transparent'] .v-overlay__content:has(.theme-customizer-panel--
|
||||
|
||||
.theme-customizer-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding-block: 28px 26px;
|
||||
padding-inline: 32px 24px;
|
||||
}
|
||||
|
||||
.theme-customizer-title {
|
||||
@@ -378,14 +368,6 @@ html[data-theme='transparent'] .v-overlay__content:has(.theme-customizer-panel--
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.theme-customizer-subtitle {
|
||||
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||
font-size: 1rem;
|
||||
line-height: 1.35;
|
||||
margin-block: 8px 0;
|
||||
margin-inline: 0;
|
||||
}
|
||||
|
||||
.theme-customizer-header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -61,19 +61,21 @@ const visible = computed({
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* stylelint-disable selector-pseudo-class-no-unknown */
|
||||
|
||||
.system-health-dialog-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.system-health-dialog-body {
|
||||
/* 弹窗正文本身不滚动,滚动只交给健康检查结果列表。 */
|
||||
display: flex;
|
||||
overflow: hidden !important;
|
||||
flex: 1 1 auto;
|
||||
block-size: min(42rem, calc(100dvh - 8rem - env(safe-area-inset-top) - env(safe-area-inset-bottom)));
|
||||
min-block-size: 0;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
:global(.v-dialog--fullscreen) .system-health-dialog-body {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* stylelint-disable scss/at-rule-no-unknown */
|
||||
/* stylelint-disable no-descending-specificity */
|
||||
// 公共样式 - 所有主题都需要
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@@ -80,21 +82,18 @@ html[data-theme-skin='bordered'] {
|
||||
}
|
||||
|
||||
.layout-vertical-nav,
|
||||
.navbar-content-container,
|
||||
.footer-nav-card {
|
||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.1) !important;
|
||||
}
|
||||
|
||||
.navbar-content-container {
|
||||
border-block-end: 1px solid rgba(var(--v-theme-on-surface), 0.1) !important;
|
||||
}
|
||||
|
||||
.layout-vertical-nav {
|
||||
border-block: 0 !important;
|
||||
border-inline-start: 0 !important;
|
||||
}
|
||||
|
||||
.navbar-content-container {
|
||||
border-block-start: 0 !important;
|
||||
border-radius: 0 0 10px 10px;
|
||||
background-color: rgba(var(--v-theme-surface), 0.82);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用类信息卡片:固定右侧媒体槽位,避免图片被左侧文字挤压变形。
|
||||
@@ -118,6 +117,7 @@ html[data-theme-skin='bordered'] {
|
||||
rgba(var(--v-theme-surface), var(--app-card-surface-opacity)) !important;
|
||||
box-shadow: var(--app-card-rest-shadow) !important;
|
||||
color: rgb(var(--v-theme-on-surface));
|
||||
|
||||
--app-card-accent-rgb: var(--v-theme-primary);
|
||||
--app-card-accent-end-rgb: var(--app-card-accent-rgb);
|
||||
--app-card-accent-start-opacity: 0.025;
|
||||
@@ -126,6 +126,7 @@ html[data-theme-skin='bordered'] {
|
||||
--app-card-hover-border-opacity: 0.16;
|
||||
--app-card-stripe-opacity: 0.22;
|
||||
--app-card-surface-opacity: 0.92;
|
||||
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -163,8 +164,9 @@ html[data-theme-skin='bordered'] {
|
||||
|
||||
html[data-theme="transparent"] .app-card-colorful,
|
||||
.v-theme--transparent .app-card-colorful {
|
||||
backdrop-filter: blur(var(--transparent-blur, 10px));
|
||||
border: 0 !important;
|
||||
backdrop-filter: blur(var(--transparent-blur, 10px));
|
||||
|
||||
--app-card-accent-start-opacity: 0.018;
|
||||
--app-card-accent-end-opacity: 0.01;
|
||||
--app-card-border-opacity: 0;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* stylelint-disable scss/at-rule-no-unknown */
|
||||
|
||||
// 透明主题专用样式
|
||||
html[data-theme="transparent"] {
|
||||
// 定义透明度变量
|
||||
@@ -39,6 +41,7 @@ html[data-theme="transparent"] {
|
||||
|
||||
// 设置页彩色卡片保留透明主题的玻璃质感,只叠加极轻的图标主色。
|
||||
.app-card-colorful {
|
||||
border: 0 !important;
|
||||
background:
|
||||
linear-gradient(
|
||||
135deg,
|
||||
@@ -47,7 +50,6 @@ html[data-theme="transparent"] {
|
||||
rgba(var(--v-theme-surface), 0) 76%
|
||||
),
|
||||
rgba(var(--v-theme-surface), var(--transparent-opacity-light)) !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
// 工具栏
|
||||
|
||||
Reference in New Issue
Block a user