refactor: system options page layout. (halo-dev/console#251)

* refactor: system options page layout.

* refactor: system options page layout.
pull/3445/head
Ryan Wang 2020-09-23 10:30:19 +08:00 committed by GitHub
parent ab0617251f
commit c9f4b5694c
13 changed files with 387 additions and 354 deletions

View File

@ -6,7 +6,7 @@
:boxShadow="false"
:toolbars="toolbars"
:ishljs="true"
:autofocus="false"
autofocus
@imgAdd="handleAttachmentUpload"
@save="handleSaveDraft"
/>
@ -20,19 +20,19 @@ import attachmentApi from '@/api/attachment'
export default {
name: 'MarkdownEditor',
components: {
haloEditor
haloEditor,
},
props: {
originalContent: {
type: String,
required: false,
default: ''
}
default: '',
},
},
data() {
return {
toolbars,
originalContentData: ''
originalContentData: '',
}
},
watch: {
@ -41,7 +41,7 @@ export default {
},
originalContentData(val) {
this.$emit('onContentChange', val)
}
},
},
methods: {
handleAttachmentUpload(pos, $file) {
@ -55,7 +55,7 @@ export default {
},
handleSaveDraft() {
this.$emit('onSaveDraft')
}
}
},
},
}
</script>

View File

@ -162,7 +162,7 @@ export const asyncRouterMap = [
{
path: '/system',
name: 'System',
component: PageView,
component: BlankLayout,
redirect: '/system/options',
meta: { title: '系统', icon: 'setting' },
children: [

View File

@ -15,6 +15,11 @@
slot="extra"
>
</slot>
<slot
name="footer"
slot="footer"
>
</slot>
</a-page-header>
</div>
</div>

View File

@ -44,6 +44,7 @@
v-if="editable"
>
<a-input
ref="nameInput"
v-model="attachment.name"
@blur="doUpdateAttachment"
/>
@ -57,7 +58,7 @@
<a href="javascript:void(0);">
<a-icon
type="edit"
@click="editable = !editable"
@click="handleEditName"
/>
</a>
</span>
@ -134,9 +135,7 @@
cancelText="取消"
v-if="addToPhoto"
>
<a-button
type="dashed"
>添加到图库</a-button>
<a-button type="dashed">添加到图库</a-button>
</a-popconfirm>
<a-popconfirm
title="你确定要删除该附件?"
@ -172,7 +171,7 @@ export default {
name: 'AttachmentDetailDrawer',
mixins: [mixin, mixinDevice],
components: {
'd-player': VueDPlayer
'd-player': VueDPlayer,
},
data() {
return {
@ -188,30 +187,30 @@ export default {
lang: 'zh-cn',
video: {
url: '',
type: 'auto'
}
}
type: 'auto',
},
},
}
},
model: {
prop: 'visible',
event: 'close'
event: 'close',
},
props: {
attachment: {
type: Object,
required: true
required: true,
},
addToPhoto: {
type: Boolean,
required: false,
default: false
default: false,
},
visible: {
type: Boolean,
required: false,
default: true
}
default: true,
},
},
mounted() {
this.player = this.$refs.player
@ -221,7 +220,7 @@ export default {
if (newValue) {
this.handleJudgeMediaType(newValue)
}
}
},
},
methods: {
handleDeleteAttachment() {
@ -242,28 +241,35 @@ export default {
this.deleteErrored = false
this.onClose()
},
handleEditName() {
this.editable = !this.editable
if (this.editable) {
this.$nextTick(() => {
this.$refs.nameInput.focus()
})
}
},
doUpdateAttachment() {
if (!this.attachment.name) {
this.$notification['error']({
message: '提示',
description: '附件名称不能为空!'
description: '附件名称不能为空!',
})
return
}
attachmentApi.update(this.attachment.id, this.attachment).then(response => {
attachmentApi.update(this.attachment.id, this.attachment).then((response) => {
this.$log.debug('Updated attachment', response.data.data)
this.$message.success('附件修改成功!')
})
this.editable = false
},
handleCopyNormalLink() {
const text = `${encodeURI(this.attachment.path)}`
this.$copyText(text)
.then(message => {
.then((message) => {
this.$log.debug('copy', message)
this.$message.success('复制成功!')
})
.catch(err => {
.catch((err) => {
this.$log.debug('copy.err', err)
this.$message.error('复制失败!')
})
@ -271,11 +277,11 @@ export default {
handleCopyMarkdownLink() {
const text = `![${this.attachment.name}](${encodeURI(this.attachment.path)})`
this.$copyText(text)
.then(message => {
.then((message) => {
this.$log.debug('copy', message)
this.$message.success('复制成功!')
})
.catch(err => {
.catch((err) => {
this.$log.debug('copy.err', err)
this.$message.error('复制失败!')
})
@ -285,7 +291,7 @@ export default {
this.photo['thumbnail'] = encodeURI(this.attachment.thumbPath)
this.photo['url'] = encodeURI(this.attachment.path)
this.photo['takeTime'] = new Date().getTime()
photoApi.create(this.photo).then(response => {
photoApi.create(this.photo).then((response) => {
this.$message.success('添加成功!')
this.photo = {}
})
@ -322,7 +328,7 @@ export default {
this.$set(this, 'photoPreviewVisible', photo)
this.$set(this, 'videoPreviewVisible', video)
this.$set(this, 'nonsupportPreviewVisible', nonsupport)
}
}
},
},
}
</script>

View File

@ -422,6 +422,7 @@
>
<a-form-model-item prop="content">
<a-input
ref="contentInput"
type="textarea"
:autoSize="{ minRows: 8 }"
v-model.trim="replyComment.content"
@ -450,39 +451,39 @@ const postColumns = [
dataIndex: 'author',
width: '150px',
ellipsis: true,
scopedSlots: { customRender: 'author' }
scopedSlots: { customRender: 'author' },
},
{
title: '内容',
dataIndex: 'content',
scopedSlots: { customRender: 'content' }
scopedSlots: { customRender: 'content' },
},
{
title: '状态',
className: 'status',
dataIndex: 'statusProperty',
width: '100px',
scopedSlots: { customRender: 'status' }
scopedSlots: { customRender: 'status' },
},
{
title: '评论文章',
dataIndex: 'post',
width: '200px',
ellipsis: true,
scopedSlots: { customRender: 'post' }
scopedSlots: { customRender: 'post' },
},
{
title: '日期',
dataIndex: 'createTime',
width: '170px',
scopedSlots: { customRender: 'createTime' }
scopedSlots: { customRender: 'createTime' },
},
{
title: '操作',
dataIndex: 'action',
width: '180px',
scopedSlots: { customRender: 'action' }
}
scopedSlots: { customRender: 'action' },
},
]
const sheetColumns = [
{
@ -490,45 +491,45 @@ const sheetColumns = [
dataIndex: 'author',
width: '150px',
ellipsis: true,
scopedSlots: { customRender: 'author' }
scopedSlots: { customRender: 'author' },
},
{
title: '内容',
dataIndex: 'content',
scopedSlots: { customRender: 'content' }
scopedSlots: { customRender: 'content' },
},
{
title: '状态',
className: 'status',
dataIndex: 'statusProperty',
width: '100px',
scopedSlots: { customRender: 'status' }
scopedSlots: { customRender: 'status' },
},
{
title: '评论页面',
dataIndex: 'sheet',
width: '200px',
ellipsis: true,
scopedSlots: { customRender: 'sheet' }
scopedSlots: { customRender: 'sheet' },
},
{
title: '日期',
dataIndex: 'createTime',
width: '170px',
scopedSlots: { customRender: 'createTime' }
scopedSlots: { customRender: 'createTime' },
},
{
title: '操作',
dataIndex: 'action',
width: '180px',
scopedSlots: { customRender: 'action' }
}
scopedSlots: { customRender: 'action' },
},
]
export default {
name: 'CommentTab',
mixins: [mixin, mixinDevice],
components: {
CommentDetail
CommentDetail,
},
props: {
type: {
@ -537,8 +538,8 @@ export default {
default: 'posts',
validator: function(value) {
return ['posts', 'sheets', 'journals'].indexOf(value) !== -1
}
}
},
},
},
data() {
return {
@ -548,14 +549,14 @@ export default {
page: 1,
size: 10,
sort: null,
total: 1
total: 1,
},
queryParam: {
page: 0,
size: 10,
sort: null,
keyword: null,
status: null
status: null,
},
selectedRowKeys: [],
selectedRows: [],
@ -563,13 +564,13 @@ export default {
selectedComment: {},
replyComment: {},
replyCommentRules: {
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }]
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }],
},
loading: false,
commentStatus: commentApi.commentStatus,
commentDetailVisible: false,
replying: false,
replyErrored: false
replyErrored: false,
}
},
created() {
@ -577,12 +578,12 @@ export default {
},
computed: {
formattedComments() {
return this.comments.map(comment => {
return this.comments.map((comment) => {
comment.statusProperty = this.commentStatus[comment.status]
comment.content = marked(decodeHTML(comment.content))
return comment
})
}
},
},
methods: {
handleListComments() {
@ -592,7 +593,7 @@ export default {
this.queryParam.sort = this.pagination.sort
commentApi
.queryComment(this.type, this.queryParam)
.then(response => {
.then((response) => {
this.comments = response.data.data.content
this.pagination.total = response.data.data.total
})
@ -609,7 +610,7 @@ export default {
handleEditStatusClick(commentId, status) {
commentApi
.updateStatus(this.type, commentId, status)
.then(response => {
.then((response) => {
this.$message.success('操作成功!')
})
.finally(() => {
@ -619,7 +620,7 @@ export default {
handleDeleteClick(commentId) {
commentApi
.delete(this.type, commentId)
.then(response => {
.then((response) => {
this.$message.success('删除成功!')
})
.finally(() => {
@ -639,10 +640,13 @@ export default {
} else {
this.replyComment.postId = comment.sheet.id
}
this.$nextTick(() => {
this.$refs.contentInput.focus()
})
},
handleCreateClick() {
const _this = this
_this.$refs.replyCommentForm.validate(valid => {
_this.$refs.replyCommentForm.validate((valid) => {
if (valid) {
_this.replying = true
commentApi
@ -687,7 +691,7 @@ export default {
}
commentApi
.updateStatusInBatch(this.type, this.selectedRowKeys, status)
.then(response => {
.then((response) => {
this.$log.debug(`commentIds: ${this.selectedRowKeys}, status: ${status}`)
this.selectedRowKeys = []
})
@ -702,7 +706,7 @@ export default {
}
commentApi
.deleteInBatch(this.type, this.selectedRowKeys)
.then(response => {
.then((response) => {
this.$log.debug(`delete: ${this.selectedRowKeys}`)
this.selectedRowKeys = []
})
@ -726,14 +730,14 @@ export default {
return {
props: {
disabled: this.queryParam.status == null || this.queryParam.status === '',
name: comment.author
}
name: comment.author,
},
}
},
handleShowDetailDrawer(comment) {
this.selectedComment = comment
this.commentDetailVisible = true
}
}
},
},
}
</script>

View File

@ -29,11 +29,11 @@
</a-col>
<a-divider />
<a-col :span="24">
<a-spin :spinning="loading">
<a-empty v-if="comments.length == 0" />
<a-spin :spinning="list.loading">
<a-empty v-if="list.data.length == 0" />
<TargetCommentTree
v-else
v-for="(comment, index) in comments"
v-for="(comment, index) in list.data"
:key="index"
:comment="comment"
@reply="handleCommentReply"
@ -46,9 +46,9 @@
<a-divider />
<div class="page-wrapper">
<a-pagination
:current="pagination.page"
:total="pagination.total"
:defaultPageSize="pagination.size"
:current="list.pagination.page"
:total="list.pagination.total"
:defaultPageSize="list.pagination.size"
@change="handlePaginationChange"
showLessItems
></a-pagination>
@ -57,59 +57,42 @@
<div class="bottom-control">
<a-button
type="primary"
@click="handleComment"
@click="handleCommentReply({})"
>评论</a-button>
</div>
<a-modal
v-if="selectedComment"
:title="'回复给:' + selectedComment.author"
v-model="replyCommentVisible"
@close="onReplyClose"
:title="replyModalTitle"
v-model="replyModal.visible"
@close="onReplyModalClose"
destroyOnClose
>
<template slot="footer">
<a-button
key="submit"
<ReactiveButton
type="primary"
@click="handleCreateClick"
>
回复
</a-button>
@click="handleReplyClick"
@callback="handleReplyCallback"
:loading="replyModal.saving"
:errored="replyModal.saveErrored"
text="回复"
loadedText="回复成功"
erroredText="回复失败"
></ReactiveButton>
</template>
<a-form layout="vertical">
<a-form-item>
<a-form-model
ref="replyCommentForm"
:model="replyModal.model"
:rules="replyModal.rules"
layout="vertical"
>
<a-form-model-item prop="content">
<a-input
ref="contentInput"
type="textarea"
:autoSize="{ minRows: 8 }"
v-model="replyComment.content"
v-model="replyModal.model.content"
/>
</a-form-item>
</a-form>
</a-modal>
<a-modal
title="评论"
v-model="commentVisible"
@close="onCommentClose"
destroyOnClose
>
<template slot="footer">
<a-button
key="submit"
type="primary"
@click="handleCreateClick"
>
回复
</a-button>
</template>
<a-form layout="vertical">
<a-form-item>
<a-input
type="textarea"
:autoSize="{ minRows: 8 }"
v-model="replyComment.content"
/>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-modal>
</a-drawer>
</template>
@ -123,111 +106,130 @@ export default {
components: { TargetCommentTree },
data() {
return {
comments: [],
loading: false,
selectedComment: {},
replyComment: {},
replyCommentVisible: false,
commentVisible: false,
pagination: {
page: 1,
size: 10,
sort: null,
total: 1
list: {
data: [],
loading: false,
selected: {},
pagination: {
page: 1,
size: 10,
sort: null,
total: 1,
},
queryParam: {
page: 0,
size: 10,
sort: null,
keyword: null,
},
},
replyModal: {
model: {},
visible: false,
saving: false,
saveErrored: false,
rules: {
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }],
},
},
queryParam: {
page: 0,
size: 10,
sort: null,
keyword: null
}
}
},
props: {
visible: {
type: Boolean,
required: false,
default: false
default: false,
},
title: {
type: String,
required: false,
default: ''
default: '',
},
description: {
type: String,
required: false,
default: ''
default: '',
},
target: {
type: String,
required: false,
default: ''
default: '',
},
id: {
type: Number,
required: false,
default: 0
}
default: 0,
},
},
computed: {
replyModalTitle() {
return this.list.selected.id ? `回复给:${this.list.selected.author}` : '评论'
},
},
methods: {
handleListComments() {
this.loading = true
this.queryParam.page = this.pagination.page - 1
this.queryParam.size = this.pagination.size
this.queryParam.sort = this.pagination.sort
this.list.loading = true
this.list.queryParam.page = this.list.pagination.page - 1
this.list.queryParam.size = this.list.pagination.size
this.list.queryParam.sort = this.list.pagination.sort
commentApi
.commentTree(this.target, this.id, this.queryParam)
.then(response => {
this.comments = response.data.data.content
this.pagination.total = response.data.data.total
.commentTree(this.target, this.id, this.list.queryParam)
.then((response) => {
this.list.data = response.data.data.content
this.list.pagination.total = response.data.data.total
})
.finally(() => {
setTimeout(() => {
this.loading = false
this.list.loading = false
}, 200)
})
},
handlePaginationChange(page, pageSize) {
this.pagination.page = page
this.pagination.size = pageSize
this.list.pagination.page = page
this.list.pagination.size = pageSize
this.handleListComments()
},
handleCommentReply(comment) {
this.selectedComment = comment
this.replyCommentVisible = true
this.replyComment.parentId = comment.id
this.replyComment.postId = this.id
this.list.selected = comment
this.replyModal.visible = true
this.replyModal.model.parentId = comment.id
this.replyModal.model.postId = this.id
this.$nextTick(() => {
this.$refs.contentInput.focus()
})
},
handleComment() {
this.replyComment.postId = this.id
this.commentVisible = true
handleReplyClick() {
const _this = this
_this.$refs.replyCommentForm.validate((valid) => {
if (valid) {
_this.replyModal.saving = true
commentApi
.create(_this.target, _this.replyModal.model)
.catch(() => {
_this.replyModal.saveErrored = true
})
.finally(() => {
setTimeout(() => {
_this.replyModal.saving = false
}, 400)
})
}
})
},
handleCreateClick() {
if (!this.replyComment.content) {
this.$notification['error']({
message: '提示',
description: '评论内容不能为空!'
})
return
handleReplyCallback() {
if (this.replyModal.saveErrored) {
this.replyModal.saveErrored = false
} else {
this.replyModal.model = {}
this.list.selected = {}
this.replyModal.visible = false
this.handleListComments()
}
commentApi
.create(this.target, this.replyComment)
.then(response => {
this.$message.success('回复成功!')
this.replyComment = {}
this.selectedComment = {}
this.replyCommentVisible = false
this.commentVisible = false
})
.finally(() => {
this.handleListComments()
})
},
handleEditStatusClick(comment, status) {
commentApi
.updateStatus(this.target, comment.id, status)
.then(response => {
.then((response) => {
this.$message.success('操作成功!')
})
.finally(() => {
@ -237,28 +239,24 @@ export default {
handleCommentDelete(comment) {
commentApi
.delete(this.target, comment.id)
.then(response => {
.then((response) => {
this.$message.success('删除成功!')
})
.finally(() => {
this.handleListComments()
})
},
onReplyClose() {
this.replyComment = {}
this.selectedComment = {}
this.replyCommentVisible = false
},
onCommentClose() {
this.replyComment = {}
this.commentVisible = false
onReplyModalClose() {
this.replyModal.model = {}
this.list.selected = {}
this.replyModal.visible = false
},
onClose() {
this.comments = []
this.pagination = {
this.list.data = []
this.list.pagination = {
page: 1,
size: 10,
sort: ''
sort: '',
}
this.$emit('close', false)
},
@ -266,7 +264,7 @@ export default {
if (visible) {
this.handleListComments()
}
}
}
},
},
}
</script>

View File

@ -5,7 +5,6 @@
>
<template slot="extra">
<a-button
key="2"
icon="reload"
:loading="list.loading"
@click="handleRefreshThemesCache"
@ -13,7 +12,6 @@
刷新
</a-button>
<a-button
key="1"
type="primary"
icon="plus"
@click="installModal.visible = true"

View File

@ -229,6 +229,7 @@
>
<a-form-model-item prop="sourceContent">
<a-input
ref="sourceContentInput"
type="textarea"
:autoSize="{ minRows: 8 }"
v-model="form.model.sourceContent"
@ -357,11 +358,17 @@ export default {
handleOpenPublishModal() {
this.form.visible = true
this.form.model = {}
this.$nextTick(() => {
this.$refs.sourceContentInput.focus()
})
},
handleOpenEditModal(item) {
this.form.model = item
this.form.isPublic = item.type !== 'INTIMATE'
this.form.visible = true
this.$nextTick(() => {
this.$refs.sourceContentInput.focus()
})
},
handleDelete(id) {
journalApi.delete(id).finally(() => {

View File

@ -1,5 +1,5 @@
<template>
<div>
<page-view>
<a-row>
<a-col :span="24">
<a-card
@ -52,19 +52,22 @@
target="_blank"
class="mr-3"
>开源组织
<a-icon type="link" /></a>
<a-icon type="link" />
</a>
<a
href="https://halo.run"
target="_blank"
class="mr-3"
>用户文档
<a-icon type="link" /></a>
<a-icon type="link" />
</a>
<a
href="https://bbs.halo.run"
target="_blank"
class="mr-3"
>在线社区
<a-icon type="link" /></a>
<a-icon type="link" />
</a>
</a-card>
<a-card
@ -108,14 +111,18 @@
>
<div v-html="versionContent"></div>
</a-modal>
</div>
</page-view>
</template>
<script>
import adminApi from '@/api/admin'
import axios from 'axios'
import marked from 'marked'
import { PageView } from '@/layouts'
export default {
components: {
PageView,
},
data() {
return {
environments: {},
@ -139,14 +146,14 @@ export default {
received_events_url: '',
type: '',
site_admin: false,
contributions: 0
}
contributions: 0,
},
],
contributorsLoading: true,
checking: false,
isLatest: false,
latestData: {},
versionContentVisible: false
versionContentVisible: false,
}
},
computed: {
@ -164,7 +171,7 @@ export default {
},
versionContentModalTitle() {
return `${this.latestData.name} 更新内容`
}
},
},
created() {
this.getEnvironments()
@ -172,7 +179,7 @@ export default {
},
methods: {
async getEnvironments() {
await adminApi.environments().then(response => {
await adminApi.environments().then((response) => {
this.environments = response.data.data
})
this.checkServerUpdate()
@ -183,11 +190,11 @@ export default {
运行模式${this.environments.mode}
User Agent${navigator.userAgent}`
this.$copyText(text)
.then(message => {
.then((message) => {
this.$log.debug('copy', message)
this.$message.success('复制成功!')
})
.catch(err => {
.catch((err) => {
this.$log.debug('copy.err', err)
this.$message.error('复制失败!')
})
@ -197,7 +204,7 @@ User Agent${navigator.userAgent}`
_this.contributorsLoading = true
axios
.get('https://api.github.com/repos/halo-dev/halo/contributors')
.then(response => {
.then((response) => {
_this.contributors = response.data
})
.catch(function(error) {
@ -214,7 +221,7 @@ User Agent${navigator.userAgent}`
_this.checking = true
axios
.get('https://api.github.com/repos/halo-dev/halo/releases/latest')
.then(response => {
.then((response) => {
const data = response.data
_this.latestData = data
if (data.draft || data.prerelease) {
@ -232,21 +239,21 @@ User Agent${navigator.userAgent}`
message: title,
description: content,
icon: <a-icon type="smile" style="color: #108ee9" />,
btn: h => {
btn: (h) => {
return h(
'a-button',
{
props: {
type: 'primary',
size: 'small'
size: 'small',
},
on: {
click: () => this.handleShowVersionContent()
}
click: () => this.handleShowVersionContent(),
},
},
'去看看'
)
}
},
})
})
.catch(function(error) {
@ -277,7 +284,7 @@ User Agent${navigator.userAgent}`
return -1
}
return major * 1000000 + minor * 1000 + micro
}
}
},
},
}
</script>

View File

@ -1,5 +1,13 @@
<template>
<div>
<page-view :title="advancedOptions?'高级选项':'基础选项'">
<template slot="extra">
<a-button
type="link"
@click="advancedOptions = !advancedOptions"
>
切换到{{ advancedOptions?'基础选项':'高级选项' }}
</a-button>
</template>
<a-row>
<a-col :span="24">
<div class="card-container">
@ -149,24 +157,10 @@
</div>
</a-col>
</a-row>
<div style="position: fixed;bottom: 30px;right: 30px;">
<a-tooltip placement="top">
<template slot="title">
<span>{{ advancedOptions?'基础选项':'高级选项' }}</span>
</template>
<a-button
type="primary"
shape="circle"
:icon="`${advancedOptions?'setting':'thunderbolt'}`"
size="large"
@click="advancedOptions = !advancedOptions"
></a-button>
</a-tooltip>
</div>
</div>
</page-view>
</template>
<script>
import { PageView } from '@/layouts'
import GeneralTab from './optiontabs/GeneralTab'
import SeoTab from './optiontabs/SeoTab'
import PostTab from './optiontabs/PostTab'
@ -182,6 +176,7 @@ import optionApi from '@/api/option'
import { mapActions } from 'vuex'
export default {
components: {
PageView,
GeneralTab,
SeoTab,
PostTab,
@ -191,14 +186,14 @@ export default {
OtherTab,
PermalinkTab,
ApiTab,
AdvancedOtherTab
AdvancedOtherTab,
},
data() {
return {
options: {},
advancedOptions: false,
saving: false,
errored: false
errored: false,
}
},
created() {
@ -207,7 +202,7 @@ export default {
methods: {
...mapActions(['refreshUserCache', 'refreshOptionsCache']),
hanldeListOptions() {
optionApi.listAll().then(response => {
optionApi.listAll().then((response) => {
this.options = response.data.data
})
},
@ -229,7 +224,7 @@ export default {
this.refreshOptionsCache()
this.refreshUserCache()
})
}
}
},
},
}
</script>

View File

@ -1,32 +1,31 @@
<template>
<div>
<div class="card-content">
<a-row :gutter="12">
<a-col
v-if="options.developer_mode"
:xl="6"
:lg="6"
:md="12"
:sm="24"
:xs="24"
class="pb-3"
<page-view>
<a-row :gutter="12">
<a-col
v-if="options.developer_mode"
:xl="6"
:lg="6"
:md="12"
:sm="24"
:xs="24"
class="pb-3"
>
<a-card
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<a-card
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<div slot="title">
<a-icon type="experiment" /> 开发者选项
</div>
<p style="min-height: 50px;">点击进入开发者选项页面</p>
<a-button
type="primary"
class="float-right"
@click="handleToDeveloperOptions()"
>进入</a-button>
</a-card>
</a-col>
<!-- <a-col
<div slot="title">
<a-icon type="experiment" /> 开发者选项
</div>
<p style="min-height: 50px;">点击进入开发者选项页面</p>
<a-button
type="primary"
class="float-right"
@click="handleToDeveloperOptions()"
>进入</a-button>
</a-card>
</a-col>
<!-- <a-col
:xl="6"
:lg="6"
:md="12"
@ -49,107 +48,107 @@
>管理</a-button>
</a-card>
</a-col> -->
<a-col
:xl="6"
:lg="6"
:md="12"
:sm="24"
:xs="24"
class="mb-3"
>
<a-card
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<div slot="title">
<a-icon type="hdd" /> 博客备份
</div>
<p style="min-height: 50px;">支持备份全站数据和数据导出支持下载到本地</p>
<a-dropdown class="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 class="ml-2"> 备份
<a-icon type="down" />
</a-button>
</a-dropdown>
</a-card>
</a-col>
<a-col
:xl="6"
:lg="6"
:md="12"
:sm="24"
:xs="24"
class="pb-3"
>
<a-card
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<div slot="title">
<a-icon type="file-markdown" /> Markdown 文章导入
</div>
<p style="min-height: 50px;">支持 Hexo/Jekyll 文章导入并解析元数据</p>
<a-button
type="primary"
class="float-right"
@click="markdownUpload = true"
>导入</a-button>
</a-card>
</a-col>
</a-row>
<a-modal
title="Markdown 文章导入"
v-model="markdownUpload"
:footer="null"
destroyOnClose
:afterClose="onUploadClose"
<a-col
:xl="6"
:lg="6"
:md="12"
:sm="24"
:xs="24"
class="mb-3"
>
<FilePondUpload
ref="upload"
name="file"
accept="text/markdown"
label="拖拽或点击选择 Markdown 文件到此处"
:uploadHandler="uploadHandler"
></FilePondUpload>
</a-modal>
<BackupWorkDirDrawer v-model="backupWorkDirDrawerVisible"></BackupWorkDirDrawer>
<ExportDataDrawer v-model="exportDataDrawerVisible"></ExportDataDrawer>
</div>
</div>
<a-card
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<div slot="title">
<a-icon type="hdd" /> 博客备份
</div>
<p style="min-height: 50px;">支持备份全站数据和数据导出支持下载到本地</p>
<a-dropdown class="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 class="ml-2"> 备份
<a-icon type="down" />
</a-button>
</a-dropdown>
</a-card>
</a-col>
<a-col
:xl="6"
:lg="6"
:md="12"
:sm="24"
:xs="24"
class="pb-3"
>
<a-card
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<div slot="title">
<a-icon type="file-markdown" /> Markdown 文章导入
</div>
<p style="min-height: 50px;">支持 Hexo/Jekyll 文章导入并解析元数据</p>
<a-button
type="primary"
class="float-right"
@click="markdownUpload = true"
>导入</a-button>
</a-card>
</a-col>
</a-row>
<a-modal
title="Markdown 文章导入"
v-model="markdownUpload"
:footer="null"
destroyOnClose
:afterClose="onUploadClose"
>
<FilePondUpload
ref="upload"
name="file"
accept="text/markdown"
label="拖拽或点击选择 Markdown 文件到此处"
:uploadHandler="uploadHandler"
></FilePondUpload>
</a-modal>
<BackupWorkDirDrawer v-model="backupWorkDirDrawerVisible"></BackupWorkDirDrawer>
<ExportDataDrawer v-model="exportDataDrawerVisible"></ExportDataDrawer>
</page-view>
</template>
<script>
import { mapGetters } from 'vuex'
import backupApi from '@/api/backup'
import { PageView } from '@/layouts'
import BackupWorkDirDrawer from './components/BackupWorkDirDrawer'
import ExportDataDrawer from './components/ExportDataDrawer'
export default {
components: { BackupWorkDirDrawer, ExportDataDrawer },
components: { PageView, BackupWorkDirDrawer, ExportDataDrawer },
data() {
return {
backupWorkDirDrawerVisible: false,
exportDataDrawerVisible: false,
markdownUpload: false,
uploadHandler: backupApi.importMarkdown
uploadHandler: backupApi.importMarkdown,
}
},
computed: {
...mapGetters(['options'])
...mapGetters(['options']),
},
methods: {
handleChange(info) {
@ -171,7 +170,7 @@ export default {
// },
onUploadClose() {
this.$refs.upload.handleClearFileList()
}
}
},
},
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<div>
<page-view>
<a-row>
<a-col :span="24">
<div
@ -48,10 +48,11 @@
/>
</a-col>
</a-row>
</div>
</page-view>
</template>
<script>
import { mapGetters } from 'vuex'
import { PageView } from '@/layouts'
import Environment from './tabs/Environment'
import RuntimeLogs from './tabs/RuntimeLogs'
import SettingsForm from './tabs/SettingsForm'
@ -59,14 +60,15 @@ import OptionsList from './tabs/OptionsList'
import StaticStorage from './tabs/StaticStorage'
export default {
components: {
PageView,
Environment,
RuntimeLogs,
SettingsForm,
OptionsList,
StaticStorage
StaticStorage,
},
computed: {
...mapGetters(['options'])
}
...mapGetters(['options']),
},
}
</script>

View File

@ -59,7 +59,7 @@
<a-button
type="primary"
icon="plus"
@click="form.visible=true"
@click="handleOpenFormModal"
>新增</a-button>
</div>
<div class="mt-4">
@ -105,7 +105,7 @@
>
<a
href="javascript:void(0);"
@click="handleEditOption(record)"
@click="handleOpenEditFormModal(record)"
>编辑</a>
<a-divider type="vertical" />
<a-popconfirm
@ -165,7 +165,10 @@
prop="key"
label="Key"
>
<a-input v-model="form.model.key" />
<a-input
ref="keyInput"
v-model="form.model.key"
/>
</a-form-model-item>
<a-form-model-item
prop="value"
@ -303,9 +306,18 @@ export default {
this.refreshOptionsCache()
})
},
handleEditOption(option) {
handleOpenFormModal() {
this.form.visible = true
this.$nextTick(() => {
this.$refs.keyInput.focus()
})
},
handleOpenEditFormModal(option) {
this.form.model = option
this.form.visible = true
this.$nextTick(() => {
this.$refs.keyInput.focus()
})
},
handlePaginationChange(page, pageSize) {
this.$log.debug(`Current: ${page}, PageSize: ${pageSize}`)