diff --git a/README.md b/README.md index 6db0b61..dfd02c2 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ Oxfmt 不负责代码质量,Oxlint 不负责 Vue 的完整类型推导;Vue S - 拆解页固定精简状态栏与结果标签,设置、预览及恢复操作收进“拆解设置与恢复”面板;人物、场景、道具、分镜和任务明细共用独立结果滚动区,执行记录单独滚动。结果区占满剩余高度,切换标签回到顶部,轮询刷新或开关设置不重置阅读位置;失败与校验提示在面板关闭时仍然可见。 - 剧集正文按编号连续展示全部已写入剧集;点击目录定位正文,滚动正文同步高亮并保持当前目录项可见。目录分行显示集数和完整标题,执行记录可按需展开。切换角色/世界观等标签不会销毁阅读器或重置位置。 - 主体身份、分镜设计和镜头生产共用 `DirectoryItem`:编号、完整标题和状态分层展示,桌面目录为 240–280px,窄屏改为可横向滚动的条目。目录标题与筛选固定,只有列表滚动。拆解结果的导出按钮与标签同排右对齐;形态图片筛选按内容区宽度自动排成一行或两列网格。 +- 侧栏导航与主体/剧集/镜头目录采用直角满行背景,移除列表两侧的内缩,悬停和选中态都铺满所在列。条目内部保留文字间距;窄屏横向目录仍保持独立滚动,不影响表单与弹窗的圆角。 - 身份、分镜、生产与图库的批量配置、说明和诊断统一放入 `WorkspaceTools`(Naive UI Drawer),按需覆盖当前工作区,不挤压列表。面板支持 Esc 或关闭按钮;关闭不会取消任务或清除配置。历史回执可从入口查看,新回执主动打开诊断;查询错误始终在外层可见。 - 生产步骤的操作按钮保留上下间距;`ConfirmAction` 用稳定根元素承接外部间距,避免多根弹窗组件吞掉 `class`。 - 右上角提供浅色、暗黑、跟随系统三种模式,默认跟随系统,选择保存在本机浏览器。存储被禁用时仍可在当前会话切换。 diff --git a/src/admin.css b/src/admin.css index 93b2a34..461e381 100644 --- a/src/admin.css +++ b/src/admin.css @@ -61,6 +61,12 @@ body { .admin-sider { height: 100%; } +/* Naive 菜单背景默认左右内缩 8px;只铺满导航行,不改图标与文字缩进。 */ +.admin-sider .n-menu .n-menu-item-content::before { + left: 0; + right: 0; + border-radius: 0; +} .admin-brand { display: flex; align-items: center; @@ -452,11 +458,11 @@ body { display: flex; flex-direction: column; gap: 8px; - padding: 8px 10px 16px; + padding: 8px 0 16px; } .directory-group-heading { flex-shrink: 0; - padding: 14px 6px 2px; + padding: 14px 14px 2px; font: 11px/1.6 ui-monospace, monospace; @@ -472,7 +478,7 @@ body { height: auto; min-height: 88px; padding: 12px 14px; - border-radius: 5px; + border-radius: 0; white-space: normal; text-align: left; } @@ -673,14 +679,15 @@ body { display: flex; flex-direction: column; gap: 6px; - padding: 4px 10px 18px; + padding: 4px 0 18px; } .n-button.reader-episode-link { flex-shrink: 0; + width: 100%; height: auto; min-height: 64px; padding: 12px 14px; - border-radius: 5px; + border-radius: 0; color: var(--app-muted); white-space: normal; text-align: left; @@ -762,9 +769,6 @@ body { padding: 16px 12px 12px; flex-wrap: wrap; } - .reader-directory-content { - padding-inline: 6px; - } .n-button.reader-episode-link { padding: 12px 10px; } diff --git a/src/components/ui/DirectoryItem.test.ts b/src/components/ui/DirectoryItem.test.ts index 4dabb28..3da6e56 100644 --- a/src/components/ui/DirectoryItem.test.ts +++ b/src/components/ui/DirectoryItem.test.ts @@ -50,6 +50,26 @@ describe('统一目录条目', () => { expect(css).toContain('grid-template-columns: clamp(240px, 22%, 280px) minmax(0, 1fr)') }) + it('侧栏与主体、镜头、剧集目录统一直角满行,保留文字内边距和移动端滚动', () => { + // happy-dom 无法计算伪元素几何,保护实际控制选中背景宽度的 CSS 规则。 + const css = readFileSync('src/admin.css', 'utf8') + expect(css).toMatch( + /\.admin-sider \.n-menu \.n-menu-item-content::before\s*\{[^}]*left:\s*0;[^}]*right:\s*0;[^}]*border-radius:\s*0/ + ) + expect(css).toMatch(/\.directory-list-content\s*\{[^}]*padding:\s*8px 0 16px/) + expect(css).toMatch(/\.reader-directory-content\s*\{[^}]*padding:\s*4px 0 18px/) + expect(css).not.toMatch(/\.reader-directory-content\s*\{[^}]*padding-inline:\s*[1-9]/) + for (const selector of ['directory-item', 'reader-episode-link']) { + expect(css).toMatch( + new RegExp( + `\\.n-button\\.${selector}\\s*\\{[^}]*width:\\s*100%;[^}]*padding:\\s*12px 14px;[^}]*border-radius:\\s*0` + ) + ) + } + expect(css).toMatch(/\.directory-group-heading\s*\{[^}]*padding:\s*14px 14px 2px/) + expect(css).toMatch(/\.directory-list-content\s*\{[^}]*flex-direction:\s*row;[^}]*width:\s*max-content/) + }) + it('导出工具栏与筛选器使用受约束的网格,不让 Tabs 和 Select 默认宽度强制换行', () => { const css = readFileSync('src/admin.css', 'utf8') expect(css).toMatch(/\.result-toolbar\s*\{[^}]*grid-template-columns:\s*minmax\(0, 1fr\) auto/) diff --git a/src/components/ui/DirectoryItem.vue b/src/components/ui/DirectoryItem.vue index ee0ca02..28c332e 100644 --- a/src/components/ui/DirectoryItem.vue +++ b/src/components/ui/DirectoryItem.vue @@ -1,7 +1,7 @@ diff --git a/src/composables/useTheme.test.ts b/src/composables/useTheme.test.ts index 8458909..f59cd6b 100644 --- a/src/composables/useTheme.test.ts +++ b/src/composables/useTheme.test.ts @@ -113,7 +113,14 @@ describe('微信风格明暗主题', () => { errorColor: tokens.danger }) expect(Layout).toMatchObject({ color: tokens.body, headerColor: tokens.surface, siderColor: tokens.subtle }) - expect(Menu).toMatchObject({ itemColorActive: tokens.selected, itemTextColorActive: tokens['accent-text'] }) + expect(Menu).toMatchObject({ + borderRadius: '0px', + itemColorActive: tokens.selected, + itemColorActiveCollapsed: tokens.selected, + itemTextColorActive: tokens['accent-text'] + }) + // 圆角调整只用于导航,表单、普通按钮和弹窗仍保留原有主题。 + expect(common?.borderRadius).toBe('6px') expect(Button?.textColorPrimary).toBe(tokens['on-accent']) for (const background of [common!.primaryColor!, common!.primaryColorHover!, common!.primaryColorPressed!]) { expect(contrast(String(Button!.textColorPrimary), background)).toBeGreaterThanOrEqual(4.5) diff --git a/src/composables/useTheme.ts b/src/composables/useTheme.ts index 17f16fa..844e993 100644 --- a/src/composables/useTheme.ts +++ b/src/composables/useTheme.ts @@ -94,8 +94,10 @@ export function useTheme() { siderColor: subtle }, Menu: { + borderRadius: '0px', itemColorActive: selected, itemColorActiveHover: selected, + itemColorActiveCollapsed: selected, itemColorHover: dark ? '#2c2c2c' : '#e8e8e8', itemTextColorActive: accentText, itemTextColorActiveHover: accentText,