fix(frontend): 修复纸页刷新宽度并完善侧栏和图表主题
This commit is contained in:
@@ -62,6 +62,22 @@ const fontSizeInput = ref(16)
|
||||
let crepe: Crepe | null = null
|
||||
let disposeLanguagePicker: (() => void) | undefined
|
||||
let disposeCodeLabels: (() => void) | undefined
|
||||
const diagramPreviews = new Map<string, { source: string; apply: (value: HTMLElement) => void }>()
|
||||
function renderDiagram(source: string, apply: (value: HTMLElement) => void) {
|
||||
for (const [id, entry] of diagramPreviews) {
|
||||
if (entry.apply === apply) diagramPreviews.delete(id)
|
||||
}
|
||||
const element = createMermaidPreview(source, themeStore.isDark, apply)
|
||||
diagramPreviews.set(element.id, { source, apply })
|
||||
return element
|
||||
}
|
||||
watch(() => themeStore.currentThemeId, () => {
|
||||
const current = [...diagramPreviews.entries()]
|
||||
diagramPreviews.clear()
|
||||
for (const [id, entry] of current) {
|
||||
if (editorRoot.value?.querySelector(`[id="${id}"]`)) entry.apply(renderDiagram(entry.source, entry.apply))
|
||||
}
|
||||
}, { flush: 'post' })
|
||||
|
||||
function applyProofingPreferences() {
|
||||
const editable = editorRoot.value?.querySelector<HTMLElement>('.ProseMirror')
|
||||
@@ -206,7 +222,7 @@ onMounted(async () => {
|
||||
languages: shikiLanguages(themeStore.resolvedCodeBlockTheme),
|
||||
renderLanguage: renderCodeLanguage,
|
||||
renderPreview: (language, content, applyPreview) => language.trim().toLowerCase() === 'mermaid'
|
||||
? createMermaidPreview(content, themeStore.isDark, applyPreview)
|
||||
? renderDiagram(content, applyPreview)
|
||||
: config.renderPreview(language, content, applyPreview),
|
||||
extensions: [basicSetup, keymap.of([indentWithTab]), shikiEditorTheme(themeStore.resolvedCodeBlockTheme)],
|
||||
})))
|
||||
@@ -242,7 +258,7 @@ watch(() => editorStore.headingRequest, request => {
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => { disposeCodeLabels?.(); disposeLanguagePicker?.(); void crepe?.destroy() })
|
||||
onBeforeUnmount(() => { diagramPreviews.clear(); disposeCodeLabels?.(); disposeLanguagePicker?.(); void crepe?.destroy() })
|
||||
|
||||
defineExpose({ getEditor: () => crepe?.editor })
|
||||
</script>
|
||||
|
||||
@@ -48,6 +48,16 @@ afterEach(() => {
|
||||
})
|
||||
|
||||
describe('FileTreePanel file switching', () => {
|
||||
it('expands every nested folder from the toolbar', async () => {
|
||||
const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/workspace', component: { template: '<div />' } }] })
|
||||
await router.push('/workspace')
|
||||
const store = useWorkspaceStore()
|
||||
store.fileTree = [{ id: 'a', name: 'A', path: '/a', type: 'folder', is_open: false, children: [{ id: 'b', name: 'B', path: '/a/b', type: 'folder', is_open: false }] }]
|
||||
wrapper = mount(FileTreePanel, { global: { plugins: [router] } })
|
||||
await wrapper.get('[aria-label="全部展开文件夹"]').trigger('click')
|
||||
expect(store.fileTree[0]!.is_open).toBe(true)
|
||||
expect(store.fileTree[0]!.children![0]!.is_open).toBe(true)
|
||||
})
|
||||
it('switches full-height panels using tabs and preserves the file search', async () => {
|
||||
const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/workspace', component: { template: '<div />' } }] })
|
||||
await router.push('/workspace')
|
||||
|
||||
@@ -68,6 +68,12 @@ const filteredTree = computed(() => {
|
||||
})
|
||||
return filter(workspaceStore.fileTree)
|
||||
})
|
||||
function expandAllFiles() {
|
||||
const expand = (nodes: FileNode[]) => nodes.forEach(node => {
|
||||
if (node.type === 'folder') { node.is_open = true; expand(node.children ?? []) }
|
||||
})
|
||||
expand(workspaceStore.fileTree)
|
||||
}
|
||||
let lastScrollTop = 0
|
||||
function revealSearch(event: WheelEvent) {
|
||||
if (activeTab.value !== 'files') return
|
||||
@@ -216,6 +222,7 @@ function containingFolder(path: string): string {
|
||||
<button type="button" :title="t('新建笔记', 'New note')" :aria-label="t('新建笔记', 'New note')" @click.stop="beginCreate('file', selectedFolderPath)"><AppIcon :icon="DocumentAdd" /></button>
|
||||
<button type="button" :title="t('新建文件夹', 'New folder')" :aria-label="t('新建文件夹', 'New folder')" @click.stop="beginCreate('folder', selectedFolderPath)"><AppIcon :icon="FolderAdd" /></button>
|
||||
<button type="button" :aria-label="t('搜索文件', 'Search files')" :aria-expanded="searchVisible" @click="searchVisible = !searchVisible">{{ t('搜索', 'Search') }}</button>
|
||||
<button type="button" :aria-label="t('全部展开文件夹', 'Expand all folders')" @click="expandAllFiles">{{ t('全部展开', 'Expand all') }}</button>
|
||||
</div>
|
||||
<div v-if="searchVisible || searchQuery || searchFocused" class="file-search">
|
||||
<input v-model="searchQuery" type="search" :placeholder="t('搜索文件或文件夹…', 'Search files or folders…')" :aria-label="t('搜索文件或文件夹', 'Search files or folders')" @focus="searchFocused = true" @blur="searchFocused = false" />
|
||||
|
||||
Reference in New Issue
Block a user