mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-04-26 19:40:51 +08:00
fix(ui): improve edit rule dialog layout and button consistency
- Increase dialog width from 380px to 460px to fit all content - Unify button heights across ab-button and ab-button-multi components - small: 32px, normal: 36px, big: 44px - Restructure ab-rule form layout with consistent gap spacing - Fix Episode Offset row to keep input and button on same line (mobile) - Add proper z-index layering for ab-bottom-sheet (backdrop: 100, container: 101, panel: 102) - Add scoped styles for ab-setting dynamic-tags wrapper - Add action button separator line in edit dialog Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
- 规则编辑弹窗新增归档/取消归档按钮
|
||||
- 规则编辑器新增剧集偏移字段和「自动检测」按钮
|
||||
- 新增 i18n 翻译(中文/英文)
|
||||
- 优化规则编辑弹窗布局:统一表单字段对齐、统一按钮高度、修复移动端底部弹窗 z-index 层级问题
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ const boxSize = computed(() => {
|
||||
if (rule.value.deleted) {
|
||||
return 'w-300';
|
||||
} else {
|
||||
return 'w-380';
|
||||
return 'w-460';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -105,10 +105,10 @@ const boxSize = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else space-y-12>
|
||||
<div v-else class="edit-rule-content">
|
||||
<ab-rule v-model:rule="rule"></ab-rule>
|
||||
|
||||
<div fx-cer justify-end gap-x-10>
|
||||
<div class="edit-rule-actions">
|
||||
<ab-button
|
||||
v-if="rule.archived"
|
||||
size="small"
|
||||
@@ -153,3 +153,22 @@ const boxSize = computed(() => {
|
||||
</ab-popup>
|
||||
</ab-popup>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.edit-rule-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.edit-rule-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding-top: 4px;
|
||||
border-top: 1px solid var(--color-border);
|
||||
padding-top: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -52,19 +52,17 @@ const items: SettingItem<BangumiRule>[] = [
|
||||
prop: {
|
||||
type: 'number',
|
||||
},
|
||||
bottomLine: true,
|
||||
},
|
||||
{
|
||||
configKey: 'filter',
|
||||
label: () => t('homepage.rule.exclude'),
|
||||
type: 'dynamic-tags',
|
||||
bottomLine: true,
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div space-y-12>
|
||||
<div class="rule-form">
|
||||
<ab-setting
|
||||
v-for="i in items"
|
||||
:key="i.configKey"
|
||||
@@ -73,12 +71,12 @@ const items: SettingItem<BangumiRule>[] = [
|
||||
></ab-setting>
|
||||
|
||||
<!-- Offset field with auto-detect button -->
|
||||
<div class="offset-row">
|
||||
<div class="offset-label">{{ $t('homepage.rule.offset') }}</div>
|
||||
<ab-label :label="() => $t('homepage.rule.offset')">
|
||||
<div class="offset-controls">
|
||||
<input
|
||||
v-model.number="rule.offset"
|
||||
type="number"
|
||||
ab-input
|
||||
class="offset-input"
|
||||
/>
|
||||
<ab-button
|
||||
@@ -89,47 +87,50 @@ const items: SettingItem<BangumiRule>[] = [
|
||||
{{ $t('homepage.rule.auto_detect') }}
|
||||
</ab-button>
|
||||
</div>
|
||||
<div v-if="offsetReason" class="offset-reason">{{ offsetReason }}</div>
|
||||
</div>
|
||||
</ab-label>
|
||||
|
||||
<div v-if="offsetReason" class="offset-reason">{{ offsetReason }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.offset-row {
|
||||
.rule-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.offset-label {
|
||||
font-size: 14px;
|
||||
color: var(--color-text);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.offset-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
|
||||
@include forTablet {
|
||||
width: auto;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
:deep(.ab-button) {
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.offset-input {
|
||||
width: 72px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast);
|
||||
width: 80px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--color-primary);
|
||||
@include forMobile {
|
||||
flex: 1;
|
||||
min-width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.offset-reason {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-secondary);
|
||||
padding-left: 2px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,12 +7,12 @@ withDefaults(defineProps<AbSettingProps>(), {
|
||||
bottomLine: false,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
const data = defineModel<any>('data');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="setting-item">
|
||||
<ab-label :label="label">
|
||||
<AbSwitch
|
||||
v-if="type === 'switch'"
|
||||
@@ -36,11 +36,33 @@ const data = defineModel<any>('data');
|
||||
v-bind="prop"
|
||||
/>
|
||||
|
||||
<div v-else-if="type === 'dynamic-tags'" w-full sm:max-w-200 overflow-auto pb-1>
|
||||
<div v-else-if="type === 'dynamic-tags'" class="dynamic-tags-wrapper">
|
||||
<NDynamicTags v-model:value="data" size="small"></NDynamicTags>
|
||||
</div>
|
||||
</ab-label>
|
||||
|
||||
<div v-if="bottomLine" line my-6></div>
|
||||
<div v-if="bottomLine" class="setting-divider"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.setting-divider {
|
||||
height: 1px;
|
||||
background: var(--color-border);
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.dynamic-tags-wrapper {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 2px;
|
||||
|
||||
@include forTablet {
|
||||
max-width: 220px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, computed } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { usePointerSwipe } from '@vueuse/core';
|
||||
import {
|
||||
TransitionRoot,
|
||||
TransitionChild,
|
||||
Dialog,
|
||||
DialogPanel,
|
||||
TransitionChild,
|
||||
TransitionRoot,
|
||||
} from '@headlessui/vue';
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -69,7 +69,7 @@ function close() {
|
||||
|
||||
<template>
|
||||
<TransitionRoot :show="show" as="template">
|
||||
<Dialog @close="close" class="ab-bottom-sheet">
|
||||
<Dialog class="ab-bottom-sheet" @close="close">
|
||||
<!-- Backdrop -->
|
||||
<TransitionChild
|
||||
enter="overlay-enter-active"
|
||||
@@ -125,6 +125,7 @@ function close() {
|
||||
&__backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 100;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
@@ -132,6 +133,7 @@ function close() {
|
||||
&__container {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 101;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
@@ -140,6 +142,7 @@ function close() {
|
||||
|
||||
&__panel {
|
||||
position: relative;
|
||||
z-index: 102;
|
||||
width: 100%;
|
||||
max-width: 640px;
|
||||
background: var(--color-surface);
|
||||
|
||||
@@ -70,22 +70,22 @@ const showSelections = ref<boolean>(false);
|
||||
&--big {
|
||||
border-radius: var(--radius-md);
|
||||
width: 276px;
|
||||
height: 55px;
|
||||
font-size: 24px;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&--normal {
|
||||
border-radius: var(--radius-sm);
|
||||
width: 170px;
|
||||
min-width: 100px;
|
||||
height: 36px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&--small {
|
||||
border-radius: var(--radius-sm);
|
||||
width: 86px;
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
min-width: 80px;
|
||||
height: 32px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
|
||||
@@ -80,13 +80,13 @@ const buttonSize = computed(() => {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
// Sizes - all meet 44px minimum touch target
|
||||
// Sizes
|
||||
&--big {
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
max-width: 276px;
|
||||
height: 55px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
&--normal {
|
||||
@@ -94,17 +94,15 @@ const buttonSize = computed(() => {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
max-width: 170px;
|
||||
min-height: var(--touch-target);
|
||||
height: 44px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
&--small {
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 13px;
|
||||
min-width: 86px;
|
||||
min-height: var(--touch-target);
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
min-width: 80px;
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user