mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-12 00:54:42 +08:00
fix: optimize mobile input layout
This commit is contained in:
@@ -797,13 +797,15 @@ onUnmounted(() => {
|
||||
<VCol cols="12" class="py-0">
|
||||
<!-- remember me checkbox -->
|
||||
<div class="d-flex align-center justify-space-between flex-wrap">
|
||||
<VCheckbox
|
||||
v-model="form.remember"
|
||||
:label="t('login.stayLoggedIn')"
|
||||
hide-details
|
||||
density="compact"
|
||||
class="login-checkbox"
|
||||
/>
|
||||
<label class="native-login-checkbox login-checkbox">
|
||||
<input
|
||||
v-model="form.remember"
|
||||
class="native-login-checkbox__input"
|
||||
type="checkbox"
|
||||
name="remember"
|
||||
/>
|
||||
<span class="native-login-checkbox__label">{{ t('login.stayLoggedIn') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
@@ -1068,6 +1070,7 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: logo-enter 700ms cubic-bezier(0.16, 1, 0.3, 1) 100ms both;
|
||||
margin-block-end: 8px;
|
||||
|
||||
/* Logo 背后的柔光环 */
|
||||
@@ -1114,6 +1117,7 @@ onUnmounted(() => {
|
||||
|
||||
.login-title {
|
||||
margin: 0;
|
||||
animation: text-enter 600ms cubic-bezier(0.16, 1, 0.3, 1) 200ms both;
|
||||
background: linear-gradient(135deg, rgb(var(--v-theme-on-surface)) 30%, rgba(var(--v-theme-primary), 1) 100%);
|
||||
background-clip: text;
|
||||
font-size: 1.85rem;
|
||||
@@ -1125,6 +1129,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
animation: text-enter 600ms cubic-bezier(0.16, 1, 0.3, 1) 300ms both;
|
||||
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
@@ -1227,6 +1232,66 @@ onUnmounted(() => {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 原生保持登录复选框,避免使用全局 VCheckbox 小屏适配布局。 */
|
||||
.native-login-checkbox {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||
cursor: pointer;
|
||||
gap: 10px;
|
||||
min-block-size: 40px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.native-login-checkbox__input {
|
||||
position: relative;
|
||||
display: inline-grid;
|
||||
flex: 0 0 18px;
|
||||
border: 2px solid rgba(var(--v-theme-on-surface), 0.54);
|
||||
border-radius: 4px;
|
||||
margin: 0;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
block-size: 18px;
|
||||
cursor: pointer;
|
||||
inline-size: 18px;
|
||||
place-content: center;
|
||||
transition:
|
||||
background-color 150ms ease,
|
||||
border-color 150ms ease,
|
||||
box-shadow 150ms ease;
|
||||
}
|
||||
|
||||
.native-login-checkbox__input::before {
|
||||
block-size: 5px;
|
||||
border-block-end: 2px solid rgb(var(--v-theme-on-primary));
|
||||
border-inline-start: 2px solid rgb(var(--v-theme-on-primary));
|
||||
content: '';
|
||||
inline-size: 9px;
|
||||
transform: translateY(-1px) rotate(-45deg) scale(0);
|
||||
transform-origin: center;
|
||||
transition: transform 120ms ease;
|
||||
}
|
||||
|
||||
.native-login-checkbox__input:checked {
|
||||
border-color: rgb(var(--v-theme-primary));
|
||||
background-color: rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
.native-login-checkbox__input:checked::before {
|
||||
transform: translateY(-1px) rotate(-45deg) scale(1);
|
||||
}
|
||||
|
||||
.native-login-checkbox__input:focus-visible {
|
||||
box-shadow: 0 0 0 3px rgba(var(--v-theme-primary), 0.18);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.native-login-checkbox__label {
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Remember me 复选框样式优化 */
|
||||
.login-checkbox {
|
||||
opacity: 0.85;
|
||||
@@ -1383,11 +1448,6 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Logo 入场 */
|
||||
.login-logo-wrapper {
|
||||
animation: logo-enter 700ms cubic-bezier(0.16, 1, 0.3, 1) 100ms both;
|
||||
}
|
||||
|
||||
@keyframes logo-enter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
@@ -1400,15 +1460,6 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
/* 标题入场 */
|
||||
.login-title {
|
||||
animation: text-enter 600ms cubic-bezier(0.16, 1, 0.3, 1) 200ms both;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
animation: text-enter 600ms cubic-bezier(0.16, 1, 0.3, 1) 300ms both;
|
||||
}
|
||||
|
||||
@keyframes text-enter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
|
||||
@@ -4,6 +4,8 @@ import { useDisplay } from 'vuetify'
|
||||
|
||||
type ResponsiveInputKind = 'choice' | 'field' | 'group' | 'multiline' | 'range'
|
||||
|
||||
const MOBILE_EMPTY_PLACEHOLDER = '-'
|
||||
|
||||
interface ResponsiveInputOptions {
|
||||
kind: ResponsiveInputKind
|
||||
name: string
|
||||
@@ -123,6 +125,9 @@ export function createResponsiveInputAdapter(component: Component, options: Resp
|
||||
if (options.kind === 'field' || options.kind === 'multiline') {
|
||||
controlAttrs.variant = 'plain'
|
||||
controlAttrs.singleLine = true
|
||||
if (!hasDisplayText(controlAttrs.placeholder)) {
|
||||
controlAttrs.placeholder = MOBILE_EMPTY_PLACEHOLDER
|
||||
}
|
||||
}
|
||||
|
||||
if (showHint) {
|
||||
|
||||
@@ -567,8 +567,12 @@ html[data-theme-radius='extra'] {
|
||||
}
|
||||
|
||||
.app-responsive-input--empty:not(:has(.v-field--dirty)) .v-field {
|
||||
background-color: rgba(var(--v-theme-on-surface), 0.035);
|
||||
box-shadow: inset 0 0 0 1px rgba(var(--v-theme-on-surface), 0.14);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.app-responsive-input--empty:not(:has(.v-field--dirty)) .v-field__input::placeholder {
|
||||
color: rgba(var(--v-theme-on-surface), 0.5);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.app-responsive-input--field .v-field__outline,
|
||||
@@ -644,6 +648,25 @@ html[data-theme-radius='extra'] {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
// 桌面也占满 12 格的字段在移动端改为上下两行,避免长输入只挤在右侧。
|
||||
.v-row > :is(
|
||||
.v-col-12:not([class*='v-col-sm-']):not([class*='v-col-md-']):not([class*='v-col-lg-']):not([class*='v-col-xl-']):not([class*='v-col-xxl-']),
|
||||
.v-col-sm-12:not([class*='v-col-md-']):not([class*='v-col-lg-']):not([class*='v-col-xl-']):not([class*='v-col-xxl-']),
|
||||
.v-col-md-12:not([class*='v-col-lg-']):not([class*='v-col-xl-']):not([class*='v-col-xxl-'])
|
||||
) > :is(.app-responsive-input--field, .app-responsive-input--range) {
|
||||
row-gap: 0.5rem;
|
||||
align-items: start;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.v-row > :is(
|
||||
.v-col-12:not([class*='v-col-sm-']):not([class*='v-col-md-']):not([class*='v-col-lg-']):not([class*='v-col-xl-']):not([class*='v-col-xxl-']),
|
||||
.v-col-sm-12:not([class*='v-col-md-']):not([class*='v-col-lg-']):not([class*='v-col-xl-']):not([class*='v-col-xxl-']),
|
||||
.v-col-md-12:not([class*='v-col-lg-']):not([class*='v-col-xl-']):not([class*='v-col-xxl-'])
|
||||
) > :is(.app-responsive-input--field, .app-responsive-input--range) .app-responsive-input__control {
|
||||
inline-size: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
|
||||
Reference in New Issue
Block a user