+
+ {t('chat.topics.export.obsidian_show_md_files')}
+
+
+
+
+ setExpandedKeys(keys as string[])}
+ treeData={treeData}
+ loadData={loadData}
+ onSelect={(selectedKeys, info) => {
+ if (selectedKeys.length > 0) {
+ const path = selectedKeys[0] as string
+ const isMdFile = !!(info.node as any).isMdFile
+
+ setCurrentSelection({
+ path,
+ isMdFile
+ })
+
+ onPathChange?.(path, isMdFile)
+ }
+ }}
+ showLine
+ showIcon
+ icon={renderIcon}
+ />
+
+
+
+ {currentSelection.path !== defaultPath && (
+
+ {t('chat.topics.export.obsidian_selected_path')}: {currentSelection.path}
+
+ )}
+
+
+ )
+}
+
+const Container = styled.div`
+ display: flex;
+ flex-direction: column;
+ height: 400px;
+`
+
+const TreeContainer = styled.div`
+ flex: 1;
+ overflow-y: auto;
+ border: 1px solid var(--color-border);
+ border-radius: 4px;
+ padding: 10px;
+ margin-bottom: 10px;
+ height: 320px;
+`
+
+const SwitchContainer = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+ padding: 0 10px;
+`
+
+const SelectedPath = styled.div`
+ font-size: 12px;
+ color: var(--color-text-2);
+ margin-top: 5px;
+ padding: 0 10px;
+ word-break: break-all;
+`
+
+export default ObsidianFolderSelector
diff --git a/src/renderer/src/components/Popups/ObsidianExportPopup.tsx b/src/renderer/src/components/Popups/ObsidianExportPopup.tsx
new file mode 100644
index 00000000..b258e9cd
--- /dev/null
+++ b/src/renderer/src/components/Popups/ObsidianExportPopup.tsx
@@ -0,0 +1,72 @@
+import ObsidianFolderSelector from '@renderer/components/ObsidianFolderSelector'
+import i18n from '@renderer/i18n'
+import store from '@renderer/store'
+import { exportMarkdownToObsidian } from '@renderer/utils/export'
+
+interface ObsidianExportOptions {
+ title: string
+ markdown: string
+}
+
+// 用于显示 Obsidian 导出对话框
+const showObsidianExportDialog = async (options: ObsidianExportOptions): Promise