feat: enable one-click export for simple markdown exporting (#3137)
* feat: enable one-click export for simple markdown exporting * feat: optimize ui for simple markdown export
This commit is contained in:
parent
b9d97e8a35
commit
9b79051ea5
@ -411,6 +411,8 @@
|
||||
"error.invalid.enter.model": "Please select a model",
|
||||
"error.invalid.proxy.url": "Invalid proxy URL",
|
||||
"error.invalid.webdav": "Invalid WebDAV settings",
|
||||
"error.markdown.export.preconf": "Failed to export the Markdown file to the preconfigured path",
|
||||
"error.markdown.export.specified": "Failed to export the Markdown file",
|
||||
"error.notion.export": "Failed to export to Notion. Please check connection status and configuration according to documentation",
|
||||
"error.notion.no_api_key": "Notion ApiKey or Notion DatabaseID is not configured",
|
||||
"error.yuque.export": "Failed to export to Yuque. Please check connection status and configuration according to documentation",
|
||||
@ -441,6 +443,8 @@
|
||||
"restore.success": "Restored successfully",
|
||||
"save.success.title": "Saved successfully",
|
||||
"searching": "Searching the internet...",
|
||||
"success.markdown.export.preconf": "Successfully exported the Markdown file to the preconfigured path",
|
||||
"success.markdown.export.specified": "Successfully exported the Markdown file",
|
||||
"success.notion.export": "Successfully exported to Notion",
|
||||
"success.yuque.export": "Successfully exported to Yuque",
|
||||
"switch.disabled": "Please wait for the current reply to complete",
|
||||
@ -666,6 +670,11 @@
|
||||
"hour_interval_other": "{{count}} hours",
|
||||
"minute_interval_one": "{{count}} minute",
|
||||
"minute_interval_other": "{{count}} minutes",
|
||||
"markdown_export.title": "Markdown Export",
|
||||
"markdown_export.path": "Default Export Path",
|
||||
"markdown_export.path_placeholder": "Export Path",
|
||||
"markdown_export.select": "Select",
|
||||
"markdown_export.help": "If provided, exports will be automatically saved to this path; otherwise, a save dialog will appear.",
|
||||
"notion.api_key": "Notion API Key",
|
||||
"notion.api_key_placeholder": "Enter Notion API Key",
|
||||
"notion.auto_split": "Auto split when exporting",
|
||||
|
||||
@ -411,6 +411,8 @@
|
||||
"error.invalid.enter.model": "モデルを選択してください",
|
||||
"error.invalid.proxy.url": "無効なプロキシURL",
|
||||
"error.invalid.webdav": "無効なWebDAV設定",
|
||||
"error.markdown.export.preconf": "Markdown ファイルを事前設定されたパスにエクスポートできませんでした",
|
||||
"error.markdown.export.specified": "Markdown ファイルのエクスポートに失敗しました",
|
||||
"error.notion.export": "Notionへのエクスポートに失敗しました。接続状態と設定を確認してください",
|
||||
"error.notion.no_api_key": "Notion ApiKey または Notion DatabaseID が設定されていません",
|
||||
"error.yuque.export": "語雀へのエクスポートに失敗しました。接続状態と設定を確認してください",
|
||||
@ -441,6 +443,8 @@
|
||||
"restore.success": "復元に成功しました",
|
||||
"save.success.title": "保存に成功しました",
|
||||
"searching": "インターネットで検索中...",
|
||||
"success.markdown.export.preconf": "Markdown ファイルを事前設定されたパスに正常にエクスポートしました",
|
||||
"success.markdown.export.specified": "Markdown ファイルを正常にエクスポートしました",
|
||||
"success.notion.export": "Notionへのエクスポートに成功しました",
|
||||
"success.yuque.export": "語雀へのエクスポートに成功しました",
|
||||
"switch.disabled": "現在の応答が完了するまで切り替えを無効にします",
|
||||
@ -666,6 +670,11 @@
|
||||
"hour_interval_other": "{{count}} 時間",
|
||||
"minute_interval_one": "{{count}} 分",
|
||||
"minute_interval_other": "{{count}} 分",
|
||||
"markdown_export.title": "Markdown エクスポート",
|
||||
"markdown_export.path": "デフォルトのエクスポートパス",
|
||||
"markdown_export.path_placeholder": "エクスポートパス",
|
||||
"markdown_export.select": "選択",
|
||||
"markdown_export.help": "入力された場合、エクスポート時に自動的にこのパスに保存されます。未入力の場合、保存ダイアログが表示されます。",
|
||||
"notion.api_key": "Notion APIキー",
|
||||
"notion.api_key_placeholder": "Notion APIキーを入力してください",
|
||||
"notion.auto_split": "내보내기 시 자동 분할",
|
||||
|
||||
@ -411,6 +411,8 @@
|
||||
"error.invalid.enter.model": "Пожалуйста, выберите модель",
|
||||
"error.invalid.proxy.url": "Неверный URL прокси",
|
||||
"error.invalid.webdav": "Неверные настройки WebDAV",
|
||||
"error.markdown.export.preconf": "Не удалось экспортировать файл Markdown в предуказанный путь",
|
||||
"error.markdown.export.specified": "Не удалось экспортировать файл Markdown",
|
||||
"error.notion.export": "Ошибка экспорта в Notion, пожалуйста, проверьте состояние подключения и настройки в документации",
|
||||
"error.notion.no_api_key": "Notion ApiKey или Notion DatabaseID не настроен",
|
||||
"error.yuque.export": "Ошибка экспорта в Yuque, пожалуйста, проверьте состояние подключения и настройки в документации",
|
||||
@ -441,6 +443,8 @@
|
||||
"restore.success": "Успешно восстановлено",
|
||||
"save.success.title": "Успешно сохранено",
|
||||
"searching": "Поиск в Интернете...",
|
||||
"success.markdown.export.preconf": "Файл Markdown успешно экспортирован в предуказанный путь",
|
||||
"success.markdown.export.specified": "Файл Markdown успешно экспортирован",
|
||||
"success.notion.export": "Успешный экспорт в Notion",
|
||||
"success.yuque.export": "Успешный экспорт в Yuque",
|
||||
"switch.disabled": "Пожалуйста, дождитесь завершения текущего ответа",
|
||||
@ -666,6 +670,11 @@
|
||||
"hour_interval_other": "{{count}} часов",
|
||||
"minute_interval_one": "{{count}} минута",
|
||||
"minute_interval_other": "{{count}} минут",
|
||||
"markdown_export.title": "Экспорт в Markdown",
|
||||
"markdown_export.path": "Путь экспорта по умолчанию",
|
||||
"markdown_export.path_placeholder": "Путь экспорта",
|
||||
"markdown_export.select": "Выбрать",
|
||||
"markdown_export.help": "Если указано, файлы будут автоматически сохраняться в этот путь; в противном случае появится диалоговое окно сохранения.",
|
||||
"notion.api_key": "Ключ API Notion",
|
||||
"notion.api_key_placeholder": "Введите ключ API Notion",
|
||||
"notion.auto_split": "Автоматическое разбиение на страницы при экспорте диалога",
|
||||
|
||||
@ -411,6 +411,8 @@
|
||||
"error.invalid.enter.model": "请选择一个模型",
|
||||
"error.invalid.proxy.url": "无效的代理地址",
|
||||
"error.invalid.webdav": "无效的 WebDAV 设置",
|
||||
"error.markdown.export.preconf": "导出Markdown文件到预先设定的路径失败",
|
||||
"error.markdown.export.specified": "导出Markdown文件失败",
|
||||
"error.notion.export": "导出 Notion 错误,请检查连接状态并对照文档检查配置",
|
||||
"error.notion.no_api_key": "未配置 Notion API Key 或 Notion Database ID",
|
||||
"error.yuque.export": "导出语雀错误,请检查连接状态并对照文档检查配置",
|
||||
@ -441,6 +443,8 @@
|
||||
"restore.success": "恢复成功",
|
||||
"save.success.title": "保存成功",
|
||||
"searching": "正在联网搜索...",
|
||||
"success.markdown.export.preconf": "成功导出Markdown文件到预先设定的路径",
|
||||
"success.markdown.export.specified": "成功导出Markdown文件",
|
||||
"success.notion.export": "成功导出到Notion",
|
||||
"success.yuque.export": "成功导出到语雀",
|
||||
"switch.disabled": "请等待当前回复完成后操作",
|
||||
@ -666,6 +670,11 @@
|
||||
"hour_interval_other": "{{count}} 小时",
|
||||
"minute_interval_one": "{{count}} 分钟",
|
||||
"minute_interval_other": "{{count}} 分钟",
|
||||
"markdown_export.title": "Markdown 导出",
|
||||
"markdown_export.path": "默认导出路径",
|
||||
"markdown_export.path_placeholder": "导出路径",
|
||||
"markdown_export.select": "选择",
|
||||
"markdown_export.help": "若填入,则每次导出时将自动保存到该路径;否则,将弹出保存对话框",
|
||||
"notion.api_key": "Notion 密钥",
|
||||
"notion.api_key_placeholder": "请输入Notion 密钥",
|
||||
"notion.auto_split": "导出对话时自动分页",
|
||||
|
||||
@ -411,6 +411,8 @@
|
||||
"error.invalid.enter.model": "請選擇一個模型",
|
||||
"error.invalid.proxy.url": "無效的代理伺服器 URL",
|
||||
"error.invalid.webdav": "無效的 WebDAV 設定",
|
||||
"error.markdown.export.preconf": "導出 Markdown 文件到預先設定的路徑失敗",
|
||||
"error.markdown.export.specified": "導出 Markdown 文件失敗",
|
||||
"error.notion.export": "匯出 Notion 錯誤,請檢查連接狀態並對照文件檢查設定",
|
||||
"error.notion.no_api_key": "未設定 Notion API Key 或 Notion Database ID",
|
||||
"error.yuque.export": "匯出語雀錯誤,請檢查連接狀態並對照文件檢查設定",
|
||||
@ -441,6 +443,8 @@
|
||||
"restore.success": "恢復成功",
|
||||
"save.success.title": "儲存成功",
|
||||
"searching": "正在網路上搜尋...",
|
||||
"success.markdown.export.preconf": "成功導出 Markdown 文件到預先設定的路徑",
|
||||
"success.markdown.export.specified": "成功導出 Markdown 文件",
|
||||
"success.notion.export": "成功匯出到 Notion",
|
||||
"success.yuque.export": "成功匯出到語雀",
|
||||
"switch.disabled": "請等待當前回覆完成",
|
||||
@ -666,6 +670,11 @@
|
||||
"hour_interval_other": "{{count}} 小時",
|
||||
"minute_interval_one": "{{count}} 分鐘",
|
||||
"minute_interval_other": "{{count}} 分鐘",
|
||||
"markdown_export.title": "Markdown 匯出",
|
||||
"markdown_export.path": "預設匯出路徑",
|
||||
"markdown_export.path_placeholder": "匯出路徑",
|
||||
"markdown_export.select": "選擇",
|
||||
"markdown_export.help": "若填入,每次匯出時將自動儲存至該路徑;否則,將彈出儲存對話框。",
|
||||
"notion.api_key": "Notion 金鑰",
|
||||
"notion.api_key_placeholder": "請輸入 Notion 金鑰",
|
||||
"notion.auto_split": "匯出對話時自動分頁",
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
import { FileSearchOutlined, FolderOpenOutlined, InfoCircleOutlined, SaveOutlined } from '@ant-design/icons'
|
||||
import {
|
||||
DeleteOutlined,
|
||||
FileSearchOutlined,
|
||||
FolderOpenOutlined,
|
||||
InfoCircleOutlined,
|
||||
SaveOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { Client } from '@notionhq/client'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import MinApp from '@renderer/components/MinApp'
|
||||
@ -9,6 +15,7 @@ import { useKnowledgeFiles } from '@renderer/hooks/useKnowledgeFiles'
|
||||
import { reset } from '@renderer/services/BackupService'
|
||||
import { RootState, useAppDispatch } from '@renderer/store'
|
||||
import {
|
||||
setmarkdownExportPath,
|
||||
setNotionApiKey,
|
||||
setNotionAutoSplit,
|
||||
setNotionDatabaseID,
|
||||
@ -38,6 +45,56 @@ import {
|
||||
} from '..'
|
||||
import WebDavSettings from './WebDavSettings'
|
||||
|
||||
// 新增的 MarkdownExportSettings 组件
|
||||
const MarkdownExportSettings: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const markdownExportPath = useSelector((state: RootState) => state.settings.markdownExportPath)
|
||||
|
||||
const handleSelectFolder = async () => {
|
||||
const path = await window.api.file.selectFolder()
|
||||
if (path) {
|
||||
dispatch(setmarkdownExportPath(path))
|
||||
}
|
||||
}
|
||||
|
||||
const handleClearPath = () => {
|
||||
dispatch(setmarkdownExportPath(null))
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle>{t('settings.data.markdown_export.title')}</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.data.markdown_export.path')}</SettingRowTitle>
|
||||
<HStack alignItems="center" gap="5px" style={{ width: 315 }}>
|
||||
<Input
|
||||
type="text"
|
||||
value={markdownExportPath || ''}
|
||||
readOnly
|
||||
style={{ width: 250 }}
|
||||
placeholder={t('settings.data.markdown_export.path_placeholder')}
|
||||
suffix={
|
||||
markdownExportPath ? (
|
||||
<DeleteOutlined onClick={handleClearPath} style={{ color: 'var(--color-error)', cursor: 'pointer' }} />
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
<Button onClick={handleSelectFolder} icon={<FolderOpenOutlined />}>
|
||||
{t('settings.data.markdown_export.select')}
|
||||
</Button>
|
||||
</HStack>
|
||||
</SettingRow>
|
||||
<SettingRow>
|
||||
<SettingHelpText>{t('settings.data.markdown_export.help')}</SettingHelpText>
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
)
|
||||
}
|
||||
|
||||
// 新增的 NotionSettings 组件
|
||||
const NotionSettings: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
@ -382,6 +439,7 @@ const DataSettings: FC = () => {
|
||||
<SettingGroup theme={theme}>
|
||||
<WebDavSettings />
|
||||
</SettingGroup>
|
||||
<MarkdownExportSettings />
|
||||
<NotionSettings />
|
||||
<YuqueSettings />
|
||||
<SettingGroup theme={theme}>
|
||||
|
||||
@ -72,6 +72,7 @@ export interface SettingsState {
|
||||
notionDatabaseID: string | null
|
||||
notionApiKey: string | null
|
||||
notionPageNameKey: string | null
|
||||
markdownExportPath: string | null
|
||||
thoughtAutoCollapse: boolean
|
||||
notionAutoSplit: boolean
|
||||
notionSplitSize: number
|
||||
@ -136,6 +137,7 @@ const initialState: SettingsState = {
|
||||
notionDatabaseID: '',
|
||||
notionApiKey: '',
|
||||
notionPageNameKey: 'Name',
|
||||
markdownExportPath: null,
|
||||
thoughtAutoCollapse: true,
|
||||
notionAutoSplit: false,
|
||||
notionSplitSize: 90,
|
||||
@ -310,6 +312,9 @@ const settingsSlice = createSlice({
|
||||
setNotionPageNameKey: (state, action: PayloadAction<string>) => {
|
||||
state.notionPageNameKey = action.payload
|
||||
},
|
||||
setmarkdownExportPath: (state, action: PayloadAction<string | null>) => {
|
||||
state.markdownExportPath = action.payload
|
||||
},
|
||||
setThoughtAutoCollapse: (state, action: PayloadAction<boolean>) => {
|
||||
state.thoughtAutoCollapse = action.payload
|
||||
},
|
||||
@ -384,6 +389,7 @@ export const {
|
||||
setNotionDatabaseID,
|
||||
setNotionApiKey,
|
||||
setNotionPageNameKey,
|
||||
setmarkdownExportPath,
|
||||
setThoughtAutoCollapse,
|
||||
setNotionAutoSplit,
|
||||
setNotionSplitSize,
|
||||
|
||||
@ -6,6 +6,7 @@ import store from '@renderer/store'
|
||||
import { setExportState } from '@renderer/store/runtime'
|
||||
import { Message, Topic } from '@renderer/types'
|
||||
import { removeSpecialCharactersForFileName } from '@renderer/utils/index'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export const messageToMarkdown = (message: Message) => {
|
||||
const roleText = message.role === 'user' ? '🧑💻 User' : '🤖 Assistant'
|
||||
@ -31,15 +32,51 @@ export const topicToMarkdown = async (topic: Topic) => {
|
||||
}
|
||||
|
||||
export const exportTopicAsMarkdown = async (topic: Topic) => {
|
||||
const { markdownExportPath } = store.getState().settings
|
||||
if (!markdownExportPath) {
|
||||
try {
|
||||
const fileName = removeSpecialCharactersForFileName(topic.name) + '.md'
|
||||
const markdown = await topicToMarkdown(topic)
|
||||
window.api.file.save(fileName, markdown)
|
||||
await window.api.file.save(fileName, markdown)
|
||||
window.message.success({ content: i18n.t('message.success.markdown.export.specified'), key: 'markdown-success' })
|
||||
} catch (error: any) {
|
||||
window.message.error({ content: i18n.t('message.error.markdown.export.specified'), key: 'markdown-error' })
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const timestamp = dayjs().format('YYYY-MM-DD-HH-mm-ss')
|
||||
const fileName = removeSpecialCharactersForFileName(topic.name) + ` ${timestamp}.md`
|
||||
const markdown = await topicToMarkdown(topic)
|
||||
await window.api.file.write(markdownExportPath + '/' + fileName, markdown)
|
||||
window.message.success({ content: i18n.t('message.success.markdown.export.preconf'), key: 'markdown-success' })
|
||||
} catch (error: any) {
|
||||
window.message.error({ content: i18n.t('message.error.markdown.export.preconf'), key: 'markdown error' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const exportMessageAsMarkdown = async (message: Message) => {
|
||||
const fileName = getMessageTitle(message) + '.md'
|
||||
const { markdownExportPath } = store.getState().settings
|
||||
if (!markdownExportPath) {
|
||||
try {
|
||||
const fileName = removeSpecialCharactersForFileName(getMessageTitle(message)) + '.md'
|
||||
const markdown = messageToMarkdown(message)
|
||||
window.api.file.save(fileName, markdown)
|
||||
await window.api.file.save(fileName, markdown)
|
||||
window.message.success({ content: i18n.t('message.success.markdown.export.specified'), key: 'markdown-success' })
|
||||
} catch (error: any) {
|
||||
window.message.error({ content: i18n.t('message.error.markdown.export.specified'), key: 'markdown error' })
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const timestamp = dayjs().format('YYYY-MM-DD-HH-mm-ss')
|
||||
const fileName = removeSpecialCharactersForFileName(getMessageTitle(message)) + ` ${timestamp}.md`
|
||||
const markdown = messageToMarkdown(message)
|
||||
await window.api.file.write(markdownExportPath + '/' + fileName, markdown)
|
||||
window.message.success({ content: i18n.t('message.success.markdown.export.preconf'), key: 'markdown-success' })
|
||||
} catch (error: any) {
|
||||
window.message.error({ content: i18n.t('message.error.markdown.export.preconf'), key: 'markdown-error' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修改 splitNotionBlocks 函数
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user