feat: 同步质量校验修复并精简工作台操作

This commit is contained in:
GouJ
2026-09-03 19:38:57 +08:00
parent 771b66cafc
commit 13bb6dc83b
47 changed files with 2244 additions and 260 deletions
+90
View File
@@ -0,0 +1,90 @@
import { flushPromises, mount, type VueWrapper } from '@vue/test-utils'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { NInput, NDropdown } from 'naive-ui'
import ActionMenu from './ActionMenu.vue'
import DetailDisclosure from './DetailDisclosure.vue'
import StyleEditor from '../../features/visual-style/components/StyleEditor.vue'
import SubjectList from '../../features/breakdown/components/SubjectList.vue'
import { selectMenu } from '../../testing/naive'
import type { SubjectCandidate } from '../../features/breakdown/types'
let wrapper: VueWrapper | undefined
afterEach(() => {
wrapper?.unmount()
wrapper = undefined
document.body.innerHTML = ''
vi.unstubAllGlobals()
})
describe('精简入口保留功能', () => {
it('菜单按点击展开,禁用项不能绕过,触发器有可访问名称', async () => {
wrapper = mount(ActionMenu, {
attachTo: document.body,
props: {
label: '测试更多操作',
items: [
{ key: 'history', label: '执行记录' },
{ key: 'export', label: '导出', disabled: true }
]
}
})
expect(wrapper.get('button').attributes('aria-haspopup')).toBe('menu')
expect(wrapper.get('button').attributes('aria-expanded')).toBe('false')
expect(document.querySelector('.n-dropdown-option-body')).toBeNull()
await selectMenu('测试更多操作', '执行记录')
expect(wrapper.emitted('select')).toEqual([['history']])
wrapper.getComponent(NDropdown).vm.$emit('select', 'export')
expect(wrapper.emitted('select')).toHaveLength(1)
})
it('补充说明默认不展开,键盘可聚焦的标题可查看原文', async () => {
wrapper = mount(DetailDisclosure, { props: { title: '规则说明' }, slots: { default: '完整规则仍然保留' } })
expect(wrapper.text()).not.toContain('完整规则仍然保留')
await wrapper.get('.n-collapse-item__header-main').trigger('click')
await flushPromises()
expect(wrapper.text()).toContain('完整规则仍然保留')
})
it('风格高级字段收起不丢失保存值,展开后仍可修改', async () => {
wrapper = mount(StyleEditor, { props: { visualStyle: null, disabled: false } })
expect(wrapper.find('#style-constraints').exists()).toBe(false)
await wrapper.get('.n-collapse-item__header-main').trigger('click')
await flushPromises()
await wrapper.get('#style-constraints').setValue('["保留硬约束"]')
const fields = wrapper.findAllComponents(NInput)
fields.find(item => item.props('placeholder')?.includes('人物质感'))!.vm.$emit('update:value', '人物风格')
await flushPromises()
await wrapper.get('.n-collapse-item__header-main').trigger('click')
await wrapper.get('form').trigger('submit')
expect(wrapper.emitted('save')).toMatchObject([
[{ characterPrompt: '人物风格', hardConstraints: ['保留硬约束'] }]
])
})
it('主体长文收起仅影响显示,完整内容与图片入口不丢失', async () => {
const description = '主体完整经历。'.repeat(30)
wrapper = mount(SubjectList, {
props: {
projectId: 'p',
subjects: [
{
profileId: 'p1',
ref: '@CH0001',
name: '人物',
module: 'character',
description,
appearance_prompt: '外观',
aliases: []
} as SubjectCandidate
],
forms: []
},
global: { stubs: { RouterLink: true } }
})
const text = wrapper.get('.line-clamp-3')
expect(text.text()).toBe(description)
await wrapper.get('button').trigger('click')
expect(wrapper.find('.line-clamp-3').exists()).toBe(false)
expect(wrapper.findAll('router-link-stub')).toHaveLength(2)
})
})
+32
View File
@@ -0,0 +1,32 @@
<script setup lang="ts">
import { ref } from 'vue'
import { NButton, NDropdown } from 'naive-ui'
import { Ellipsis } from '@lucide/vue'
/** 低频操作集中到键盘可访问的菜单;选中禁用项也不会向外触发动作。 */
const props = withDefaults(
defineProps<{ label?: string; items: { key: string; label: string; disabled?: boolean }[] }>(),
{ label: '更多操作' }
)
const emit = defineEmits<{ select: [key: string] }>()
const open = ref(false)
function select(key: string) {
const item = props.items.find(option => option.key === key)
if (!item || item.disabled) return
emit('select', key)
open.value = false
}
</script>
<template>
<NDropdown trigger="click" placement="bottom-end" :options="items" v-model:show="open" @select="select">
<NButton
quaternary
class="icon-button"
:aria-label="label"
:title="label"
aria-haspopup="menu"
:aria-expanded="open"
><template #icon><Ellipsis :size="18" /></template
></NButton>
</NDropdown>
</template>
+23
View File
@@ -0,0 +1,23 @@
<script setup lang="ts">
import { ref } from 'vue'
import { NButton, NCollapse, NCollapseItem } from 'naive-ui'
/** 保留说明与诊断的可发现入口,默认不占据主内容区域;阻塞错误不应放入此组件。 */
withDefaults(defineProps<{ title?: string }>(), { title: '使用说明' })
const expanded = ref<string[]>([])
/** 原生按钮保留 Enter/Space 键盘激活;文字点击不再向外重复触发折叠。 */
function toggle() {
expanded.value = expanded.value.length ? [] : ['details']
}
</script>
<template>
<NCollapse v-model:expanded-names="expanded" class="detail-disclosure"
><NCollapseItem name="details"
><template #header
><NButton text size="small" :aria-expanded="expanded.length > 0" @click.stop="toggle">{{
title
}}</NButton></template
>
<div class="detail-disclosure-content"><slot /></div></NCollapseItem
></NCollapse>
</template>