feat: support export database. (halo-dev/console#101)

pull/3445/head
Ryan Wang 2020-03-17 15:15:44 +08:00 committed by GitHub
parent d1e520a476
commit 2c98963fbc
4 changed files with 226 additions and 31 deletions

View File

@ -6,7 +6,7 @@ const backupApi = {}
backupApi.importMarkdown = (formData, uploadProgress, cancelToken) => {
return service({
url: `${baseUrl}/import/markdown`,
url: `${baseUrl}/markdown`,
timeout: 8640000, // 24 hours
data: formData, // form data
onUploadProgress: uploadProgress,
@ -15,24 +15,49 @@ backupApi.importMarkdown = (formData, uploadProgress, cancelToken) => {
})
}
backupApi.backupHalo = () => {
backupApi.backupWorkDir = () => {
return service({
url: `${baseUrl}/halo`,
url: `${baseUrl}/work-dir`,
method: 'post',
timeout: 8640000 // 24 hours
})
}
backupApi.listHaloBackups = () => {
backupApi.listWorkDirBackups = () => {
return service({
url: `${baseUrl}/halo`,
url: `${baseUrl}/work-dir`,
method: 'get'
})
}
backupApi.deleteHaloBackup = filename => {
backupApi.deleteWorkDirBackup = filename => {
return service({
url: `${baseUrl}/halo`,
url: `${baseUrl}/work-dir`,
params: {
filename: filename
},
method: 'delete'
})
}
backupApi.exportData = () => {
return service({
url: `${baseUrl}/data`,
method: 'post',
timeout: 8640000 // 24 hours
})
}
backupApi.listExportedData = () => {
return service({
url: `${baseUrl}/data`,
method: 'get'
})
}
backupApi.deleteExportedData = filename => {
return service({
url: `${baseUrl}/data`,
params: {
filename: filename
},

View File

@ -64,12 +64,27 @@
<div slot="title">
<a-icon type="hdd" /> 博客备份
</div>
<p style="min-height: 50px;">备份全站数据支持下载到本地</p>
<a-button
type="primary"
style="float:right"
@click="backupDrawerVisible = true"
>备份</a-button>
<p style="min-height: 50px;">支持备份全站数据和数据导出支持下载到本地</p>
<a-dropdown style="float:right">
<a-menu slot="overlay">
<a-menu-item
key="1"
@click="backupWorkDirDrawerVisible = true"
>
整站备份
</a-menu-item>
<a-menu-item
key="2"
@click="exportDataDrawerVisible = true"
>
数据导出
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 备份
<a-icon type="down" />
</a-button>
</a-dropdown>
</a-card>
</a-col>
<a-col
@ -111,7 +126,8 @@
:uploadHandler="uploadHandler"
></FilePondUpload>
</a-modal>
<BackupDrawer v-model="backupDrawerVisible"></BackupDrawer>
<BackupWorkDirDrawer v-model="backupWorkDirDrawerVisible"></BackupWorkDirDrawer>
<ExportDataDrawer v-model="exportDataDrawerVisible"></ExportDataDrawer>
</div>
</div>
</template>
@ -119,13 +135,15 @@
<script>
import { mapGetters } from 'vuex'
import backupApi from '@/api/backup'
import BackupDrawer from './components/BackupDrawer'
import BackupWorkDirDrawer from './components/BackupWorkDirDrawer'
import ExportDataDrawer from './components/ExportDataDrawer'
export default {
components: { BackupDrawer },
components: { BackupWorkDirDrawer, ExportDataDrawer },
data() {
return {
backupDrawerVisible: false,
backupWorkDirDrawerVisible: false,
exportDataDrawerVisible: false,
markdownUpload: false,
uploadHandler: backupApi.importMarkdown
}

View File

@ -1,6 +1,6 @@
<template>
<a-drawer
title="博客备份"
title="整站备份"
:width="isMobile()?'100%':'480'"
closable
:visible="visible"
@ -72,7 +72,7 @@
type="dashed"
icon="reload"
:loading="loading"
@click="handleBAckupRefreshClick"
@click="handleBackupRefreshClick"
>刷新</a-button>
</div>
</a-drawer>
@ -81,7 +81,7 @@
import { mixin, mixinDevice } from '@/utils/mixin.js'
import backupApi from '@/api/backup'
export default {
name: 'BackupDrawer',
name: 'BackupWorkDirDrawer',
mixins: [mixin, mixinDevice],
data() {
return {
@ -105,15 +105,15 @@ export default {
watch: {
visible: function(newValue, oldValue) {
if (newValue) {
this.getBackups()
this.listBackups()
}
}
},
methods: {
getBackups() {
listBackups() {
this.loading = true
backupApi
.listHaloBackups()
.listWorkDirBackups()
.then(response => {
this.backups = response.data.data
})
@ -122,10 +122,10 @@ export default {
handleBackupClick() {
this.backuping = true
backupApi
.backupHalo()
.backupWorkDir()
.then(response => {
this.$notification.success({ message: '备份成功!' })
this.getBackups()
this.$message.success('备份成功!')
this.listBackups()
})
.finally(() => {
this.backuping = false
@ -134,15 +134,15 @@ export default {
handleBackupDeleteClick(filename) {
this.deleting = true
backupApi
.deleteHaloBackup(filename)
.deleteWorkDirBackup(filename)
.then(response => {
this.$notification.success({ message: '删除成功!' })
this.getBackups()
this.$message.success('删除成功!')
this.listBackups()
})
.finally(() => (this.deleting = false))
},
handleBAckupRefreshClick() {
this.getBackups()
handleBackupRefreshClick() {
this.listBackups()
},
onClose() {
this.$emit('close', false)

View File

@ -0,0 +1,152 @@
<template>
<a-drawer
title="数据导出"
:width="isMobile()?'100%':'480'"
closable
:visible="visible"
destroyOnClose
@close="onClose"
>
<a-row
type="flex"
align="middle"
>
<a-col :span="24">
<a-alert
message="注意:导出后的数据文件存储在临时文件中,重启服务器会造成备份文件的丢失,所以请尽快下载!"
banner
closable
/>
<a-divider>历史文件</a-divider>
<a-list
itemLayout="vertical"
size="small"
:dataSource="files"
>
<a-list-item
slot="renderItem"
slot-scope="file"
>
<a-button
slot="extra"
type="link"
style="color: red"
icon="delete"
:loading="deleting"
@click="handleFileDeleteClick(file.filename)"
>删除</a-button>
<a-list-item-meta>
<a
slot="title"
:href="file.downloadUrl"
>
<a-icon
type="schedule"
style="color: #52c41a"
/>
{{ file.filename }}
</a>
<p slot="description">{{ file.updateTime | timeAgo }}/{{ file.fileSize | fileSizeFormat }}</p>
</a-list-item-meta>
</a-list-item>
<div
v-if="loading"
class="loading-container"
style="position: absolute;bottom: 40px; width: 100%;text-align: center;"
>
<a-spin />
</div>
</a-list>
</a-col>
</a-row>
<a-divider class="divider-transparent" />
<div class="bottom-control">
<a-button
type="primary"
icon="download"
style="marginRight: 8px"
:loading="backuping"
@click="handleExportClick"
>备份</a-button>
<a-button
type="dashed"
icon="reload"
:loading="loading"
@click="handleFilesRefreshClick"
>刷新</a-button>
</div>
</a-drawer>
</template>
<script>
import { mixin, mixinDevice } from '@/utils/mixin.js'
import backupApi from '@/api/backup'
export default {
name: 'ExportDataDrawer',
mixins: [mixin, mixinDevice],
data() {
return {
backuping: false,
loading: false,
deleting: false,
files: []
}
},
model: {
prop: 'visible',
event: 'close'
},
props: {
visible: {
type: Boolean,
required: false,
default: true
}
},
watch: {
visible: function(newValue, oldValue) {
if (newValue) {
this.listFiles()
}
}
},
methods: {
listFiles() {
this.loading = true
backupApi
.listExportedData()
.then(response => {
this.files = response.data.data
})
.finally(() => (this.loading = false))
},
handleExportClick() {
this.backuping = true
backupApi
.exportData()
.then(response => {
this.$message.success('导出成功!')
this.listFiles()
})
.finally(() => {
this.backuping = false
})
},
handleFileDeleteClick(filename) {
this.deleting = true
backupApi
.deleteExportedData(filename)
.then(response => {
this.$message.success('删除成功!')
this.listFiles()
})
.finally(() => (this.deleting = false))
},
handleFilesRefreshClick() {
this.listFiles()
},
onClose() {
this.$emit('close', false)
}
}
}
</script>