fix: 完善移动端表单响应式布局

This commit is contained in:
jxxghp
2026-07-14 13:51:50 +08:00
parent cec9563963
commit d625d1ad46
3 changed files with 34 additions and 3 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "moviepilot", "name": "moviepilot",
"version": "2.14.4", "version": "2.14.5",
"private": true, "private": true,
"type": "module", "type": "module",
"bin": "dist/service.js", "bin": "dist/service.js",
+17 -1
View File
@@ -24,6 +24,15 @@ function hasDisplayText(value: unknown): value is string | number {
return (typeof value === 'string' && value.trim().length > 0) || typeof value === 'number' return (typeof value === 'string' && value.trim().length > 0) || typeof value === 'number'
} }
/**
* 判断录入控件模型中是否已有可展示的值。
*/
function hasInputValue(value: unknown) {
if (Array.isArray(value)) return value.length > 0
return value !== undefined && value !== null && value !== ''
}
/** /**
* 解析包装组件尚未声明的 Vue 布尔属性值。 * 解析包装组件尚未声明的 Vue 布尔属性值。
*/ */
@@ -127,12 +136,19 @@ export function createResponsiveInputAdapter(component: Component, options: Resp
const { label: labelSlot, ...controlSlots } = slots const { label: labelSlot, ...controlSlots } = slots
const labelContent = labelSlot?.({ label, props: { for: controlId } }) ?? String(label) const labelContent = labelSlot?.({ label, props: { for: controlId } }) ?? String(label)
const disabled = isBooleanAttributeEnabled(attrs.disabled) const disabled = isBooleanAttributeEnabled(attrs.disabled)
const isField = options.kind === 'field' || options.kind === 'multiline'
const isEmptyWithoutPlaceholder = isField
&& !hasInputValue(attrs.modelValue ?? attrs['model-value'])
&& !hasDisplayText(attrs.placeholder)
return h('div', { return h('div', {
class: [ class: [
'app-responsive-input', 'app-responsive-input',
`app-responsive-input--${options.kind}`, `app-responsive-input--${options.kind}`,
{ 'app-responsive-input--disabled': disabled }, {
'app-responsive-input--disabled': disabled,
'app-responsive-input--empty': isEmptyWithoutPlaceholder,
},
rootClass, rootClass,
], ],
style: rootStyle, style: rootStyle,
+16 -1
View File
@@ -566,6 +566,11 @@ html[data-theme-radius='extra'] {
transition: background-color 0.18s ease, box-shadow 0.18s ease; transition: background-color 0.18s ease, box-shadow 0.18s ease;
} }
.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);
}
.app-responsive-input--field .v-field__outline, .app-responsive-input--field .v-field__outline,
.app-responsive-input--field .v-field__overlay, .app-responsive-input--field .v-field__overlay,
.app-responsive-input--multiline .v-field__outline, .app-responsive-input--multiline .v-field__outline,
@@ -588,11 +593,13 @@ html[data-theme-radius='extra'] {
} }
.app-responsive-input--multiline { .app-responsive-input--multiline {
row-gap: 0.5rem;
align-items: start; align-items: start;
grid-template-columns: minmax(0, 1fr);
} }
.app-responsive-input--multiline .app-responsive-input__control { .app-responsive-input--multiline .app-responsive-input__control {
padding-block-start: 0.125rem; inline-size: 100%;
} }
.app-responsive-input--multiline .v-field__input { .app-responsive-input--multiline .v-field__input {
@@ -631,6 +638,14 @@ html[data-theme-radius='extra'] {
opacity: var(--v-disabled-opacity); opacity: var(--v-disabled-opacity);
} }
// 进入移动录入模式的控件强制独占一行,避免原 VCol 小于 12 列时两栏布局被再次压缩。
@media (width < 960px) {
.v-row > :is(.v-col, [class*='v-col-']):has(.app-responsive-input) {
flex: 0 0 100%;
max-width: 100%;
}
}
@media (hover: hover) { @media (hover: hover) {
.app-responsive-input--field .v-field:hover, .app-responsive-input--field .v-field:hover,
.app-responsive-input--multiline .v-field:hover { .app-responsive-input--multiline .v-field:hover {