fix(ui): unify dialogs and complete theme component coverage

This commit is contained in:
2026-09-05 23:56:02 +08:00
parent 6107b7ff1b
commit af2556d29e
22 changed files with 254 additions and 35 deletions
+9
View File
@@ -0,0 +1,9 @@
# 浏览器回归入口
先在 frontend 运行 `pnpm dev`。这些页面直接挂载真实组件,使用空的编辑器状态,不加载或保存用户笔记,也不调用模型 API;不在生产构建的入口中。
- `/tests/visual/index.html?theme=light`:将 theme 依次替换为 dark、sepia、paper-moments、ocean-blue、midnight-purple。检查输入、禁用、焦点、悬停、展开/折叠、Markdown、图表及长标识;在宽屏和窄窗口重复。
- `/tests/visual/index.html?case=dialog`:检查满视口遮罩、背景无法滚动、内部长内容可滚动、Tab 焦点限定、Escape 关闭与再次打开。
- `/tests/visual/index.html?case=editor`:逐字输入行内代码;先输入两个反引号、向左移再填字;连续普通/软换行;输入法提交;选区替换;撤销/重做。编辑器单元测试另覆盖 Markdown 序列化往返。
运行自动回归:`pnpm test`。AppDialog 测试覆盖滚动锁引用计数、恢复焦点、禁止隐式关闭;主题预览矩阵覆盖六主题的实际共享 CSS、控件状态和 CSP/无脚本隔离。自动结构检查不代替浏览器截图、布局和对比度检查。
+23
View File
@@ -0,0 +1,23 @@
<!doctype html>
<html><head><meta charset="utf-8"><title>隔离视觉回归</title></head><body><div id="app"></div>
<script type="module">
import { createApp, h, ref } from 'vue';
import { createPinia } from 'pinia';
import Preview from '/src/features/themes/CommunityThemePreview.vue';
import Editor from '/src/features/editor/VisualMarkdownEditor.vue';
import AppDialog from '/src/components/common/AppDialog.vue';
import '/src/styles/tokens.css';
import '/src/styles/features.css';
const params = new URLSearchParams(location.search);
const theme = params.get('theme') || 'light';
const builtin = ['light','dark','sepia'].includes(theme);
const mode = params.get('case') || 'theme';
createApp({setup(){
const open = ref(true);
return () => mode === 'editor' ? h(Editor,{initialContent:''}) : mode === 'dialog' ? h('main', {class:'feature-page',style:'height:100vh;'},[
h('div',{style:'height:120vh;'},'背景长页面'),
h('button',{class:'button-primary',onClick:()=>open.value=true},'打开测试弹窗'),
open.value && h(AppDialog,{label:'隔离弹窗',onClose:()=>open.value=false},{default:()=>h('section',{class:'modal'},[h('h2','弹窗滚动与焦点'),h('input',{class:'input',autofocus:true}),h('div',{style:'height:110vh;'},'内部长内容'),h('button',{class:'button-secondary',onClick:()=>open.value=false},'关闭')])})
]) : h('main',{},[h('button',{onClick:()=>open.value=true},'打开主题样例'),open.value&&h(Preview,{themeId:theme,name:theme,...(builtin?{css:''}:{}),onClose:()=>open.value=false})]);
}}).use(createPinia()).mount('#app');
</script></body></html>