diff --git a/src/App.vue b/src/App.vue index 8cd0452..4dfc36f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,19 +1,10 @@ + + + + + + diff --git a/src/components/MilkdownEditor.vue b/src/components/MilkdownEditor.vue index 6a15b69..af6cf37 100644 --- a/src/components/MilkdownEditor.vue +++ b/src/components/MilkdownEditor.vue @@ -164,16 +164,20 @@ import { Selection } from '@milkdown/prose/state' import { undo, redo, undoDepth, redoDepth } from '@milkdown/prose/history' import { copilotPlugin, copilotConfigCtx, copilotGhostMark, setCopilotEnabled, interruptCopilot, COPILOT_PLUGIN_KEY, SIZE_LIMIT, checkSizeLimit, clearGhostSuggestion } from '../plugins/copilotPlugin' import { docBlockNode, docBlockRemark, docBlockView } from '../plugins/docBlockPlugin' -import { mermaidRenderPreview, codeBlockConfig } from '../plugins/mermaidPlugin' -import { fetchSuggestion } from '../utils/api.js' +import { mermaidRenderPreview, refreshMermaidPreviews, codeBlockConfig } from '../plugins/mermaidPlugin' +import { fetchSuggestion, fetchTTS } from '../utils/api.js' import { useSettingsStore } from '../stores/settings' +import { useTheme } from '../composables/useTheme.js' import { OCR_URL, EXPORT_PDF_URL } from '../utils/config.js' +import TTSMenu from './TTSMenu.vue' +import TTSPlayer from './TTSPlayer.vue' import { convertFileToMarkdown } from '../utils/convert.js' import { setOcrCache, clearOcrCache, clearAllOcrCache, IMAGE_SIZE_LIMIT, calculateImageHash, getOcrByHash, setOcrByHash } from '../utils/ocrCache.js' import { DOC_BLOCK_NODE_TYPE, getDocTypeFromFilename, isSupportedDocFile, transformDocBlockMarkdownForClipboard, transformLegacyDocBlocksForExport, transformSpecialDocBlocksToLegacy } from '../utils/docBlock.js' const emit = defineEmits(['update:markdown']) const settings = useSettingsStore() +const { isDark } = useTheme() const t = (key) => settings.t[key] const initialMarkdown = computed(() => settings.initialMarkdown) @@ -325,6 +329,13 @@ watch( } ) +watch( + () => isDark.value, + () => { + refreshMermaidPreviews() + } +) + const revokeObjectUrl = (url) => { if (!objectUrls.has(url)) return URL.revokeObjectURL(url) @@ -841,37 +852,36 @@ const handleUpload = async (event) => { const results = [] const errors = [] - for (let index = 0; index < docFiles.length; index++) { - const file = docFiles[index] - uploadProgress.value = { current: index + 1, total: docFiles.length, filename: file.name } + const parsePromises = docFiles.map(async (file, index) => { + const docType = getDocTypeFromFilename(file.name) + let content = '' - try { - const docType = getDocTypeFromFilename(file.name) - let content = '' - - if (isTextFile(file)) { - content = await file.text() - } else if (isConvertibleFile(file)) { - content = await convertFileToMarkdown(file) - } else { - throw new Error('不支持的文件类型') - } - - if (!content) { - throw new Error('文档解析结果为空') - } - - results.push({ - docType, - docName: file.name || `document.${docType}`, - content, - index, - }) - } catch (e) { - const message = e instanceof Error ? e.message : '' - errors.push({ filename: file.name, message }) + if (isTextFile(file)) { + content = await file.text() + } else if (isConvertibleFile(file)) { + content = await convertFileToMarkdown(file) + } else { + throw new Error('不支持的文件类型') } - } + + if (!content) { + throw new Error('文档解析结果为空') + } + + return { docType, docName: file.name || `document.${docType}`, content, index } + }) + + const settled = await Promise.allSettled(parsePromises) + + settled.forEach((result, idx) => { + uploadProgress.value = { current: idx + 1, total: docFiles.length, filename: docFiles[idx].name } + if (result.status === 'fulfilled') { + results.push(result.value) + } else { + const message = result.reason instanceof Error ? result.reason.message : String(result.reason) + errors.push({ filename: docFiles[idx].name, message }) + } + }) uploadProgress.value = null diff --git a/src/components/SettingsPanel.vue b/src/components/SettingsPanel.vue index 6c715b0..42b8fb3 100644 --- a/src/components/SettingsPanel.vue +++ b/src/components/SettingsPanel.vue @@ -1,11 +1,14 @@