增加导出二级菜单,备份方式

This commit is contained in:
jasminexz 2023-09-06 20:17:12 +08:00
parent 791546c727
commit bdae6fadfd
5 changed files with 123 additions and 26 deletions

View File

@ -304,7 +304,7 @@ export const articleBackupApi = (params?: object): Promise<R<any>> => {
* @param params
* @returns
*/
export interface BackupFile { date: string, time: string, filename: string, fileLength: number }
export interface BackupFile { date: string, time: string, filename: string, fileLength: number, desc?: string }
export const articleBackupListApi = (): Promise<R<BackupFile[]>> => {
return rq.get<BackupFile[]>("/article/backup/list");
}

View File

@ -11,17 +11,48 @@
<el-button @click="getBackupList">
<span class="iconbl bl-refresh-line" style="margin-right: 7px;"></span>刷新
</el-button>
<el-button @click="backupNow">
<span class="iconbl bl-archive-line" style="margin-right: 7px;"></span>立即备份
</el-button>
<div class="backup-tip">当前仅支持下载最大 10MB 的文件, 如果备份文件超过 10MB, 请您自行从服务器中下载若您的服务器带宽较小也建议您自行从服务器下载</div>
<el-tooltip content="将文章以 Markdown 格式进行备份" :hide-after="0">
<el-button @click="backupNow('MARKDOWN', 'NO')">
<span class="iconbl bl-file-markdown" style="margin-right: 7px;"></span>备份 Markdown
</el-button>
</el-tooltip>
<el-tooltip content="将文章以 Markdown 格式进行备份,同时备份所有图片" :hide-after="0">
<el-button @click="backupNow('MARKDOWN', 'YES')">
<span class="iconbl bl-file-markdown" style="margin-right: 7px;"></span>备份本地 Markdown
</el-button>
</el-tooltip>
<el-tooltip content="将文章以 Html 格式进行备份" :hide-after="0">
<el-button @click="backupNow('HTML', 'NO')">
<span class="iconbl bl-HTML" style="margin-right: 7px;"></span>备份 Html
</el-button>
</el-tooltip>
<el-tooltip content="将文章以 Html 格式进行备份,同时备份所有图片" :hide-after="0">
<el-button @click="backupNow('HTML', 'YES')">
<span class="iconbl bl-HTML" style="margin-right: 7px;"></span>备份本地 Html
</el-button>
</el-tooltip>
<div class="backup-tip">
服务器将于每日早上 7 点备份 Markdown 数据
</div>
<div class="backup-tip">
当前仅支持下载最大 10MB 的文件, 过大时请您自行从服务器中下载若您的服务器带宽较小也建议您自行从服务器下载
</div>
</div>
<div class="bak-container">
<div v-for="bak in backupList" :key="bak.filename" class="bak-item">
<span class="iconbl bl-file-zip-line"></span>
<span class="name">{{ bak.filename }}</span>
<span class="size">{{ formatFileSize(bak.fileLength) }}</span>
<el-button class="visible" text bg style="margin-left: 5px;" @click="download(bak)"><span
<bl-row>
<span class="iconbl bl-file-zip-line"></span>
<span class="name">{{ bak.filename }}</span>
<span class="size">{{ formatFileSize(bak.fileLength) }}</span>
</bl-row>
<div>
<span class="desc">{{ bak.desc }}</span>
</div>
<el-button class="download-btn" text bg style="margin-left: 5px;" @click="download(bak)"><span
class="iconbl bl-folder-download-line"></span></el-button>
</div>
</div>
@ -44,12 +75,31 @@ const backupList = ref<BackupFile[]>()
const getBackupList = () => {
articleBackupListApi().then(resp => {
backupList.value = resp.data
backupList.value = resp.data?.map((bak) => {
let desc = ''
let type = bak.filename.charAt(1)
let toLocal = bak.filename.charAt(2)
if (toLocal === 'L') {
desc += '本地路径'
} else if (toLocal === 'N') {
desc += '网络地址'
}
if (type === 'M') {
desc += ', Markdown'
} else if (type === 'H') {
desc += ', Html'
}
bak.desc = desc
return bak
})
})
}
const backupNow = () => {
articleBackupApi().then(_ => {
const backupNow = (type: 'MARKDOWN' | 'HTML', toLocal: 'YES' | 'NO') => {
articleBackupApi({ type: type, toLocal: toLocal }).then(_ => {
Notify.info('后台正在备份中, 请稍后刷新列表查看最新备份', '备份中')
})
}
@ -73,6 +123,7 @@ const download = (file: BackupFile) => {
a.setAttribute("href", objectUrl)
a.setAttribute("download", filename)
a.click()
a.remove()
})
}
@ -114,7 +165,7 @@ $height-title: 50px;
padding: 20px;
.workbench {
@include box(100%, 60px);
@include box(100%, 90px);
border-bottom: 1px solid var(--el-border-color);
margin-bottom: 10px;
@ -126,21 +177,27 @@ $height-title: 50px;
}
.bak-container {
@include box(100%, calc(100% - 70px));
@include box(100%, calc(100% - 100px));
@include flex(column, flex-start, flex-start);
align-content: flex-start;
flex-wrap: wrap;
overflow-x: overlay;
padding: 10px;
.bak-item {
width: 400px;
// border: 1px solid red;
width: 350px;
margin-bottom: 5px;
margin-right: 5px;
font-size: 14px;
padding: 5px 10px;
border-radius: 4px;
transition: box-shadow 0.1s;
position: relative;
&:hover {
.visible {
box-shadow: var(--bl-box-shadow);
.download-btn {
opacity: 1;
}
}
@ -155,12 +212,17 @@ $height-title: 50px;
}
.size {
.size,
.desc {
font-size: 12px;
color: var(--bl-text-color-light);
}
.visible {
.download-btn {
position: absolute;
right: 5px;
top: calc(50% - 12px);
opacity: 0;
}
}

View File

@ -1,7 +1,8 @@
<template>
<!-- 文件夹操作 -->
<div class="doc-workbench">
<ArticleTreeWorkbench @refresh-doc-tree="getDocTree" @show-sort="handleShowSort"></ArticleTreeWorkbench>
<ArticleTreeWorkbench @refresh-doc-tree="getDocTree" @show-sort="handleShowSort" ref="ArticleTreeWorkbenchRef">
</ArticleTreeWorkbench>
</div>
<div class="doc-trees-container" v-loading="docTreeLoading" element-loading-text="正在读取文档..."
@ -126,14 +127,21 @@
<span class="iconbl bl-planet-line"></span>浏览器打开
</div>
<div v-if="curDoc.ty === 3" @mouseenter="handleHoverRightMenuLevel2($event, 3)">
<div v-if="curDoc.ty === 3" @mouseenter="handleHoverRightMenuLevel2($event, 4)">
<span class="iconbl bl-a-rightsmallline-line"></span>
<span class="iconbl bl-file-download-line"></span>导出文章
<div class="menu-content-level2" :style="rMenuLevel2">
<div @click="articleDownload">
<span class="iconbl bl-file-markdown"></span>导出为 Markdown
<span class="iconbl bl-file-markdown"></span>导出为 MD
</div>
<div @click="articleBackup('MARKDOWN')">
<span class="iconbl bl-file-markdown"></span>导出为本地 MD
</div>
<div @click="articleDownloadHtml">
<span class="iconbl bl-HTML"></span>导出为 Html
<span class="iconbl bl-HTML"></span>导出为 HTML
</div>
<div @click="articleBackup('HTML')">
<span class="iconbl bl-HTML"></span>导出为本地 HTML
</div>
</div>
</div>
@ -188,7 +196,7 @@ import { isNotNull } from "@renderer/assets/utils/obj"
import { isEmpty } from 'lodash'
import { provideKeyDocTree } from '@renderer/views/doc/doc'
import { grammar } from './scripts/markedjs'
import { folderDelApi, articleDownloadApi, articleSyncApi, articleDelApi } from '@renderer/api/blossom'
import { folderDelApi, articleDownloadApi, articleSyncApi, articleDelApi, articleBackupApi } from '@renderer/api/blossom'
import { openExtenal, writeText, openNewArticleWindow } from '@renderer/assets/utils/electron'
import Notify from '@renderer/scripts/notify'
@ -291,6 +299,7 @@ const curDoc = ref<DocTree>({ i: 0, p: 0, n: '选择菜单', o: 0, t: [], s: 0,
const rMenu = ref<RightMenu>({ show: false, clientX: 0, clientY: 0 })
const rMenuLevel2 = ref<RightMenuLevel2>({ top: '0px' })
const ArticleDocTreeRightMenuRef = ref()
const ArticleTreeWorkbenchRef = ref()
/**
* 显示有检查菜单
@ -377,12 +386,13 @@ const articleDownload = () => {
a.setAttribute("href", objectUrl)
a.setAttribute("download", filename)
a.click()
a.remove()
})
}
/**
* 下载文章
* 下载HTML文章
*/
const articleDownloadHtml = () => {
articleDownloadHtmlApi({ id: curDoc.value.i }).then(resp => {
@ -398,6 +408,25 @@ const articleDownloadHtml = () => {
a.setAttribute("href", objectUrl)
a.setAttribute("download", filename)
a.click()
a.remove()
})
}
const articleBackup = (type: 'MARKDOWN' | 'HTML') => {
articleBackupApi({ type: type, articleId: curDoc.value.i, toLocal: 'YES' }).then(resp => {
ElMessageBox.confirm(
`由于导出为本地文章时需要导出图片等信息,所以文章将会以
<span style="color:#C02B2B;text-decoration: underline;">备份压缩包</span>
的形式存储在服务器上文件名为${resp.data.filename}你可以前往备份页面查看导出进度和导出文件压缩包`, {
confirmButtonText: '立即查看',
cancelButtonText: '稍后再说',
type: 'info',
draggable: true,
dangerouslyUseHTMLString: true,
}
).then(() => {
ArticleTreeWorkbenchRef.value.handleShowBackupDialog()
})
})
}

View File

@ -183,7 +183,7 @@ const handleShowBackupDialog = () => {
//#endregion
const emits = defineEmits(['refreshDocTree', 'show-sort'])
defineExpose({ handleShowBackupDialog })
</script>
<style scoped lang="scss">

View File

@ -40,6 +40,12 @@
margin-right: 5px;
}
// 拥有二级菜单的箭头指示
.bl-a-rightsmallline-line {
position: absolute;
right: -2px;
}
&:hover {
background: var(--el-color-primary-light-8);