style: 对齐拆解设置控件并修复单位换行
This commit is contained in:
@@ -343,6 +343,86 @@ body {
|
||||
.control-row-checkbox .n-checkbox-box-wrapper {
|
||||
align-self: center;
|
||||
}
|
||||
/* 拆解配置跟随抽屉实际宽度;标题 20px + 间距 8px,下方统一使用 34px 控件行。 */
|
||||
.breakdown-settings-panel {
|
||||
container: breakdown-settings / inline-size;
|
||||
}
|
||||
.breakdown-config {
|
||||
--breakdown-label-offset: 28px;
|
||||
display: grid;
|
||||
grid-template-columns: 180px minmax(0, 1fr) auto;
|
||||
align-items: start;
|
||||
gap: 16px 24px;
|
||||
}
|
||||
.breakdown-config .field-label {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
line-height: 20px;
|
||||
}
|
||||
.breakdown-group-field,
|
||||
.breakdown-modules-field,
|
||||
.breakdown-module-option {
|
||||
min-width: 0;
|
||||
}
|
||||
.breakdown-group-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.breakdown-group-number.n-input-number {
|
||||
flex: 0 0 120px;
|
||||
width: 120px;
|
||||
}
|
||||
.breakdown-group-unit {
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
color: var(--app-muted);
|
||||
font-size: 14px;
|
||||
}
|
||||
.breakdown-modules-field {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
.breakdown-module-options {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 12px 16px;
|
||||
}
|
||||
.breakdown-module-description {
|
||||
margin: 4px 0 0;
|
||||
padding-left: 24px;
|
||||
color: var(--app-muted);
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.breakdown-preview-button.n-button {
|
||||
align-self: start;
|
||||
margin-top: var(--breakdown-label-offset);
|
||||
white-space: nowrap;
|
||||
}
|
||||
@container breakdown-settings (max-width: 780px) {
|
||||
.breakdown-config {
|
||||
grid-template-columns: 180px minmax(0, 1fr);
|
||||
}
|
||||
.breakdown-preview-button.n-button {
|
||||
grid-column: 2;
|
||||
justify-self: end;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
@container breakdown-settings (max-width: 560px) {
|
||||
.breakdown-config {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
.breakdown-module-options {
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
|
||||
}
|
||||
.breakdown-preview-button.n-button {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
.workspace-tools-body .storyboard-coverage {
|
||||
margin-block: 20px;
|
||||
}
|
||||
|
||||
@@ -140,6 +140,58 @@ async function selectTab(label: string) {
|
||||
}
|
||||
|
||||
describe('拆解页内容滚动', () => {
|
||||
it('拆解设置保留输入标签、单行单位与模块说明,改版后仍校验模块和剧本状态', async () => {
|
||||
const fetcher = vi.fn<typeof fetch>()
|
||||
vi.stubGlobal('fetch', fetcher)
|
||||
const provided = mountPage()
|
||||
await wrapper!.get('[data-workspace-tools]').trigger('click')
|
||||
await flushPromises()
|
||||
const config = wrapper!.get('.breakdown-config')
|
||||
expect(config.get('label[for="group-size"]').text()).toBe('每组集数')
|
||||
expect(config.get<HTMLInputElement>('#group-size').element.value).toBe('3')
|
||||
expect(config.get('.breakdown-group-unit').text()).toBe('集 / 组')
|
||||
expect(config.get('fieldset > legend').text()).toBe('抽取模块')
|
||||
const options = config.findAll('.breakdown-module-option')
|
||||
expect(options).toHaveLength(3)
|
||||
const preview = config.get<HTMLButtonElement>('.breakdown-preview-button')
|
||||
expect(preview.element.disabled).toBe(false)
|
||||
for (const option of options) {
|
||||
const checkbox = option.get('[role="checkbox"]')
|
||||
const description = option.get('.breakdown-module-description')
|
||||
expect(checkbox.attributes('aria-describedby')).toBe(description.attributes('id'))
|
||||
expect(checkbox.find('.breakdown-module-description').exists()).toBe(false)
|
||||
expect(description.text()).not.toBe('')
|
||||
await checkbox.trigger('click')
|
||||
}
|
||||
expect(preview.element.disabled).toBe(true)
|
||||
expect(wrapper!.text()).toContain('至少选择一个抽取模块')
|
||||
await options[1]!.get('[role="checkbox"]').trigger('click')
|
||||
expect(preview.element.disabled).toBe(false)
|
||||
provided.data.value!.project.status = 'generating'
|
||||
await flushPromises()
|
||||
expect(preview.element.disabled).toBe(true)
|
||||
expect(fetcher).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('拆解配置按抽屉宽度换行,单位不收缩,三类控件对齐且说明位于控件下方', () => {
|
||||
// DOM 环境不计算坐标,检查统一标题偏移、34px 控件行和容器断点契约。
|
||||
const css = readFileSync('src/admin.css', 'utf8')
|
||||
expect(css).toMatch(/\.breakdown-settings-panel\s*\{\s*container:\s*breakdown-settings \/ inline-size;/)
|
||||
expect(css).toMatch(/\.breakdown-config\s*\{[^}]*--breakdown-label-offset:\s*28px;/)
|
||||
expect(css).toMatch(/\.breakdown-config \.field-label\s*\{[^}]*margin:\s*0 0 8px;[^}]*line-height:\s*20px;/)
|
||||
expect(css).toMatch(/\.breakdown-group-unit\s*\{[^}]*flex-shrink:\s*0;[^}]*white-space:\s*nowrap;/)
|
||||
expect(css).toMatch(
|
||||
/\.n-checkbox\.control-row-checkbox\s*\{[^}]*align-items:\s*center;[^}]*min-height:\s*34px;/
|
||||
)
|
||||
expect(css).toMatch(
|
||||
/\.breakdown-preview-button\.n-button\s*\{[^}]*align-self:\s*start;[^}]*margin-top:\s*var\(--breakdown-label-offset\);/
|
||||
)
|
||||
expect(css).toContain('@container breakdown-settings (max-width: 780px)')
|
||||
expect(css).toContain('@container breakdown-settings (max-width: 560px)')
|
||||
expect(css).toContain('repeat(auto-fit, minmax(min(100%, 160px), 1fr))')
|
||||
expect(readFileSync('src/styles.css', 'utf8')).not.toContain('.breakdown-config')
|
||||
})
|
||||
|
||||
it.each(['人物', '场景', '道具'])('%s 使用共用固定斑马纹样式,搜索后保持列表条目结构', async label => {
|
||||
mountPage()
|
||||
await selectTab(label)
|
||||
|
||||
@@ -155,7 +155,7 @@ function exportResult() {
|
||||
</div>
|
||||
<div v-if="project?.episodes.length" class="toolbar-actions">
|
||||
<WorkspaceTools v-model:open="toolsOpen" title="拆解设置与恢复" label="拆解设置与恢复">
|
||||
<section class="panel p-5 lg:p-6">
|
||||
<section class="panel breakdown-settings-panel p-5 lg:p-6">
|
||||
<div class="mb-5 flex flex-wrap items-start justify-between gap-3">
|
||||
<div>
|
||||
<h2 class="flex items-center gap-2 font-semibold"><Layers :size="17" />拆解设置</h2>
|
||||
@@ -168,38 +168,46 @@ function exportResult() {
|
||||
<NTag size="small" :bordered="false">来源:正式剧集</NTag>
|
||||
</div>
|
||||
<div class="breakdown-config">
|
||||
<div>
|
||||
<div class="breakdown-group-field">
|
||||
<label class="field-label" for="group-size">每组集数</label>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="breakdown-group-input">
|
||||
<NInputNumber
|
||||
:disabled="operation.pending"
|
||||
:input-props="{ id: 'group-size' }"
|
||||
class="w-24"
|
||||
class="breakdown-group-number"
|
||||
:value="typeof groupSize === 'number' ? groupSize : null"
|
||||
@update:value="groupSize = $event ?? 0"
|
||||
:min="1"
|
||||
:step="1"
|
||||
></NInputNumber
|
||||
><span class="text-sm text-muted">集 / 组</span>
|
||||
><span class="breakdown-group-unit">集 / 组</span>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="flex flex-wrap gap-5 border-0 p-0">
|
||||
<legend class="field-label mb-3">抽取模块</legend>
|
||||
<NCheckbox
|
||||
:checked="modules.includes(option.value)"
|
||||
:disabled="operation.pending"
|
||||
:aria-label="option.label"
|
||||
@update:checked="toggleModule(option.value, $event)"
|
||||
v-for="option in moduleOptions"
|
||||
:key="option.value"
|
||||
class="flex cursor-pointer items-start gap-2.5"
|
||||
><span
|
||||
><span class="block text-sm font-medium">{{ option.label }}</span
|
||||
><span class="mt-1 block text-[11px] text-muted">{{
|
||||
option.description
|
||||
}}</span></span
|
||||
></NCheckbox
|
||||
>
|
||||
<fieldset class="breakdown-modules-field">
|
||||
<legend class="field-label">抽取模块</legend>
|
||||
<div class="breakdown-module-options">
|
||||
<div
|
||||
v-for="option in moduleOptions"
|
||||
:key="option.value"
|
||||
class="breakdown-module-option"
|
||||
>
|
||||
<NCheckbox
|
||||
:checked="modules.includes(option.value)"
|
||||
:disabled="operation.pending"
|
||||
:aria-label="option.label"
|
||||
:aria-describedby="`breakdown-module-${option.value}-help`"
|
||||
@update:checked="toggleModule(option.value, $event)"
|
||||
class="control-row-checkbox"
|
||||
><span class="text-sm font-medium">{{ option.label }}</span></NCheckbox
|
||||
>
|
||||
<p
|
||||
:id="`breakdown-module-${option.value}-help`"
|
||||
class="breakdown-module-description"
|
||||
>
|
||||
{{ option.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<NButton
|
||||
:disabled="
|
||||
@@ -210,7 +218,7 @@ function exportResult() {
|
||||
!!error
|
||||
"
|
||||
@click="loadPreview"
|
||||
class="self-end"
|
||||
class="breakdown-preview-button"
|
||||
><LoaderCircle v-if="previewBusy" :size="14" class="animate-spin" />预览分组
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
@@ -621,13 +621,6 @@
|
||||
monospace;
|
||||
}
|
||||
|
||||
.breakdown-config {
|
||||
display: grid;
|
||||
grid-template-columns: 145px minmax(0, 1fr) auto;
|
||||
align-items: start;
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.group-preview {
|
||||
margin-top: 24px;
|
||||
padding-top: 20px;
|
||||
@@ -735,15 +728,6 @@
|
||||
.history-panel {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.breakdown-config {
|
||||
grid-template-columns: 120px minmax(0, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
.breakdown-config > button {
|
||||
grid-column: 1 / -1;
|
||||
justify-self: start;
|
||||
}
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.storyboard-controls {
|
||||
@@ -771,10 +755,6 @@
|
||||
font-size: 23px;
|
||||
}
|
||||
|
||||
.breakdown-config {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.stage-strip {
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user