style: 统一页面表单操作左对齐

This commit is contained in:
GouJ
2026-09-22 19:03:29 +08:00
parent 869ebf2f2c
commit 7763170830
5 changed files with 30 additions and 7 deletions
@@ -220,7 +220,7 @@ onScopeDispose(() => controller?.abort())
/> />
</section> </section>
</div> </div>
<div class="mt-3 flex items-center gap-3"> <div class="page-form-actions mt-4">
<NButton <NButton
type="primary" type="primary"
:loading="saving" :loading="saving"
@@ -6,7 +6,7 @@ import { NButton, NCheckbox, NInput } from 'naive-ui'
import { computed, reactive, ref, watch } from 'vue' import { computed, reactive, ref, watch } from 'vue'
import type { SaveIdentityInput, SubjectIdentity } from '../types' import type { SaveIdentityInput, SubjectIdentity } from '../types'
/** 身份文本草稿不随询覆盖;父页面切换主体或保存成功后重建编辑器。 */ /** 身份文本草稿不随询覆盖;父页面切换主体或保存成功后重建编辑器。 */
const props = defineProps<{ identity: SubjectIdentity | null; disabled: boolean; module: string }>() const props = defineProps<{ identity: SubjectIdentity | null; disabled: boolean; module: string }>()
const emit = defineEmits<{ save: [input: SaveIdentityInput]; dirty: [value: boolean] }>() const emit = defineEmits<{ save: [input: SaveIdentityInput]; dirty: [value: boolean] }>()
const form = reactive({ description: '', generationPrompt: '', isLocked: false }) const form = reactive({ description: '', generationPrompt: '', isLocked: false })
@@ -88,11 +88,11 @@ function save() {
class="flex items-start gap-2 text-xs leading-6" class="flex items-start gap-2 text-xs leading-6"
>{{ module === 'character' ? '确认并锁定演员身份' : '确认并锁定身份文本' }}</NCheckbox >{{ module === 'character' ? '确认并锁定演员身份' : '确认并锁定身份文本' }}</NCheckbox
> >
<div class="flex flex-wrap items-center justify-between gap-3"> <div class="page-form-actions">
<NButton :disabled="disabled" type="primary" attr-type="submit">保存主体身份</NButton>
<span class="text-xs text-muted">{{ <span class="text-xs text-muted">{{
dirty ? '有未保存修改,刷新不会覆盖草稿。' : '图片以已保存的身份提示词为准。' dirty ? '有未保存修改,刷新不会覆盖草稿。' : '图片以已保存的身份提示词为准。'
}}</span }}</span>
><NButton :disabled="disabled" type="primary" attr-type="submit">保存主体身份</NButton>
</div> </div>
</fieldset> </fieldset>
</AppForm> </AppForm>
@@ -7,7 +7,7 @@ import { NButton, NCheckbox, NInput, NTag } from 'naive-ui'
import { computed, reactive, ref, watch } from 'vue' import { computed, reactive, ref, watch } from 'vue'
import type { SaveVisualStyleInput, VisualStyle } from '../types' import type { SaveVisualStyleInput, VisualStyle } from '../types'
/** 编辑草稿独立于询结果,刷新不会覆盖尚未保存的输入。 */ /** 编辑草稿独立于询结果,刷新不会覆盖尚未保存的输入。 */
const props = defineProps<{ visualStyle: VisualStyle | null; disabled: boolean }>() const props = defineProps<{ visualStyle: VisualStyle | null; disabled: boolean }>()
const emit = defineEmits<{ save: [input: SaveVisualStyleInput]; dirty: [value: boolean] }>() const emit = defineEmits<{ save: [input: SaveVisualStyleInput]; dirty: [value: boolean] }>()
const form = reactive({ const form = reactive({
@@ -145,7 +145,7 @@ const constraintsDetails = ref<InstanceType<typeof DetailDisclosure> | null>(nul
<p class="text-xs leading-6 text-muted"> <p class="text-xs leading-6 text-muted">
锁定后仍可人工编辑并保存取消勾选并保存后才能再次使用 AI 重生成 锁定后仍可人工编辑并保存取消勾选并保存后才能再次使用 AI 重生成
</p> </p>
<div class="flex justify-end"> <div class="page-form-actions">
<NButton :disabled="disabled" type="primary" attr-type="submit"> 保存视觉风格 </NButton> <NButton :disabled="disabled" type="primary" attr-type="submit"> 保存视觉风格 </NButton>
</div> </div>
</fieldset> </fieldset>
+8
View File
@@ -182,6 +182,14 @@
gap: 10px; gap: 10px;
padding-top: 20px; padding-top: 20px;
} }
/* 页面级表单的保存/执行操作从左侧开始,说明文字紧随其后;弹窗底部仍保持右对齐。 */
.page-form-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-start;
gap: 8px 16px;
}
.field-label { .field-label {
display: block; display: block;
margin-bottom: 9px; margin-bottom: 9px;
+15
View File
@@ -29,6 +29,21 @@ afterEach(() => {
}) })
describe('全站平面主题', () => { describe('全站平面主题', () => {
it('页面级表单操作统一左对齐,弹窗操作仍保持右对齐', () => {
const css = readAllStyles()
expect(css).toMatch(
/\.page-form-actions\s*\{[^}]*display:\s*flex;[^}]*flex-wrap:\s*wrap;[^}]*align-items:\s*center;[^}]*justify-content:\s*flex-start;[^}]*gap:\s*8px 16px;/
)
expect(css).toMatch(/\.dialog-footer\s*\{[^}]*justify-content:\s*flex-end;/)
for (const file of [
'src/features/subject-identity/components/IdentityEditor.vue',
'src/features/visual-style/components/StyleEditor.vue',
'src/features/generation-config/components/CreativeProfileSettings.vue'
]) {
expect(readFileSync(file, 'utf8')).toContain('page-form-actions')
}
})
it.each([false, true])('模式 %s 的绿色按钮使用白字,禁用后灰底灰字且不可提交', dark => { it.each([false, true])('模式 %s 的绿色按钮使用白字,禁用后灰底灰字且不可提交', dark => {
localStorage.setItem('drama-studio-theme', dark ? 'dark' : 'light') localStorage.setItem('drama-studio-theme', dark ? 'dark' : 'light')
vi.stubGlobal('matchMedia', () => ({ matches: dark, addEventListener() {}, removeEventListener() {} })) vi.stubGlobal('matchMedia', () => ({ matches: dark, addEventListener() {}, removeEventListener() {} }))