pref: code optimization again. (#215)

pull/221/head
Ryan Wang 2020-07-14 16:51:40 +08:00 committed by GitHub
parent 6f3ea8ef64
commit 9828aaef74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 720 additions and 558 deletions

View File

@ -7,6 +7,7 @@
:visible="visible"
destroyOnClose
@close="onClose"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
type="flex"
@ -51,6 +52,7 @@
:total="pagination.total"
:defaultPageSize="pagination.size"
@change="handlePaginationChange"
showLessItems
></a-pagination>
</div>
<a-divider class="divider-transparent" />
@ -136,13 +138,6 @@ export default {
uploadHandler: attachmentApi.upload
}
},
watch: {
visible: function(newValue, oldValue) {
if (newValue) {
this.handleListAttachments()
}
}
},
methods: {
handleShowUploadModal() {
this.uploadVisible = true
@ -182,6 +177,11 @@ export default {
this.$refs.upload.handleClearFileList()
this.handlePaginationChange(1, this.pagination.size)
},
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListAttachments()
}
},
handleJudgeMediaType(attachment) {
var mediaType = attachment.mediaType
//

View File

@ -7,7 +7,7 @@
<a-layout-header
v-if="visible"
:class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
class="p-0"
style="padding:0"
>
<div
v-if="mode === 'sidemenu'"

View File

@ -30,12 +30,12 @@ export default {
...mapGetters(['options'])
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
onLogoClick() {
this.clickCount++
if (this.clickCount === 10) {
optionApi.save(this.optionsToCreate).then(response => {
this.loadOptions()
this.refreshOptionsCache()
this.$message.success(`开发者选项已启用!`)
this.clickCount = 0
this.$router.push({ name: 'ToolList' })

View File

@ -156,15 +156,6 @@ export default {
<style lang="less">
@import url('../components/global.less');
/*
* The following styles are auto-applied to elements with
* transition="page-transition" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the page transition by editing
* these styles.
*/
.page-transition-enter {
opacity: 0;
}

View File

@ -21,7 +21,7 @@ router.beforeEach((to, from, next) => {
// TODO Get installation status
if (!store.getters.options) {
store.dispatch('loadOptions').then()
store.dispatch('refreshOptionsCache').then()
}
next()

View File

@ -26,7 +26,7 @@ const option = {
}
},
actions: {
loadOptions({
refreshOptionsCache({
commit
}) {
return new Promise((resolve, reject) => {

View File

@ -26,7 +26,7 @@ const user = {
}
},
actions: {
loadUser({
refreshUserCache({
commit
}) {
return new Promise((resolve, reject) => {

View File

@ -170,6 +170,7 @@
showSizeChanger
@change="handlePaginationChange"
@showSizeChange="handlePaginationChange"
showLessItems
/>
</div>
<a-modal

View File

@ -7,6 +7,7 @@
:visible="visible"
destroyOnClose
@close="onClose"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
type="flex"
@ -52,6 +53,7 @@
:total="pagination.total"
:defaultPageSize="pagination.size"
@change="handlePaginationChange"
showLessItems
></a-pagination>
</div>
@ -59,7 +61,7 @@
v-model="detailVisible"
v-if="selectedAttachment"
:attachment="selectedAttachment"
@delete="loadAttachments"
@delete="handleListAttachments"
/>
<a-divider class="divider-transparent" />
<div class="bottom-control">
@ -139,13 +141,6 @@ export default {
})
}
},
watch: {
visible(value) {
if (value) {
this.loadAttachments()
}
}
},
methods: {
handleShowDetailDrawer(attachment) {
this.selectedAttachment = attachment
@ -193,7 +188,7 @@ export default {
})
return false
},
loadAttachments() {
handleListAttachments() {
this.loading = true
this.queryParam.page = this.pagination.page - 1
this.queryParam.size = this.pagination.size
@ -216,12 +211,17 @@ export default {
handlePaginationChange(page, pageSize) {
this.pagination.page = page
this.pagination.size = pageSize
this.loadAttachments()
this.handleListAttachments()
},
onUploadClose() {
this.$refs.upload.handleClearFileList()
this.handlePaginationChange(1, this.pagination.size)
},
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListAttachments()
}
},
handleJudgeMediaType(attachment) {
var mediaType = attachment.mediaType
//

View File

@ -388,6 +388,7 @@
showSizeChanger
@showSizeChange="handlePaginationChange"
@change="handlePaginationChange"
showLessItems
/>
</div>
</div>

View File

@ -6,6 +6,7 @@
:visible="visible"
destroyOnClose
@close="onClose"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
type="flex"
@ -49,6 +50,7 @@
:total="pagination.total"
:defaultPageSize="pagination.size"
@change="handlePaginationChange"
showLessItems
></a-pagination>
</div>
<a-divider class="divider-transparent" />
@ -168,15 +170,6 @@ export default {
default: 0
}
},
watch: {
visible(newValue, oldValue) {
this.$log.debug('old value', oldValue)
this.$log.debug('new value', newValue)
if (newValue) {
this.handleListComments()
}
}
},
methods: {
handleListComments() {
this.loading = true
@ -268,6 +261,11 @@ export default {
sort: ''
}
this.$emit('close', false)
},
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListComments()
}
}
}
}

View File

@ -7,6 +7,7 @@
:visible="visible"
destroyOnClose
@close="onClose"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
type="flex"
@ -42,6 +43,7 @@
showSizeChanger
@showSizeChange="handlePaginationChange"
@change="handlePaginationChange"
showLessItems
/>
</div>
</a-col>
@ -100,13 +102,6 @@ export default {
})
}
},
watch: {
visible(value) {
if (value) {
this.handleListLogs()
}
}
},
methods: {
handleListLogs() {
this.loading = true
@ -143,6 +138,11 @@ export default {
},
onClose() {
this.$emit('close', false)
},
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListLogs()
}
}
}
}

View File

@ -345,7 +345,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListMenus()
_this.handleListTeams()
})
@ -359,7 +359,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListMenus()
_this.handleListTeams()
})

View File

@ -192,7 +192,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.saving = false
}, 200)
}, 400)
})
}
}

View File

@ -421,7 +421,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.fetchButtonLoading = false
}, 200)
}, 400)
})
},
handleBranchFetching() {

View File

@ -7,6 +7,7 @@
destroyOnClose
@close="onClose"
:visible="visible"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
:gutter="12"
@ -56,11 +57,13 @@
style="padding-bottom: 50px;"
>
<a-spin :spinning="settingLoading">
<div class="card-container">
<div
class="card-container"
v-if="themeConfigurations.length>0"
>
<a-tabs
type="card"
defaultActiveKey="0"
v-if="themeConfigurations.length>0"
>
<a-tab-pane
v-for="(group, index) in themeConfigurations"
@ -159,12 +162,11 @@
</a-form>
</a-tab-pane>
</a-tabs>
<a-alert
message="当前主题暂无设置选项"
banner
v-if="themeConfigurations.length <=0 && !settingLoading"
/>
</div>
<a-empty
v-if="themeConfigurations.length <=0 && !settingLoading"
description="当前主题暂无设置选项"
/>
</a-spin>
</a-col>
@ -245,7 +247,7 @@ export default {
attachmentDrawerVisible: false,
themeConfigurations: [],
themeSettings: [],
settingLoading: false,
settingLoading: true,
selectedField: '',
wrapperCol: {
xl: { span: 12 },
@ -275,13 +277,6 @@ export default {
default: false
}
},
watch: {
visible(value) {
if (value) {
this.handleFetchConfiguration()
}
}
},
computed: {
...mapGetters(['options']),
author() {
@ -324,7 +319,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.saving = false
}, 200)
}, 400)
})
},
onClose() {
@ -339,6 +334,15 @@ export default {
// this.themeSettings[this.selectedField] = encodeURI(data.path)
this.attachmentDrawerVisible = false
},
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleFetchConfiguration()
} else {
this.themeConfigurations = []
this.themeSettings = []
this.settingLoading = true
}
},
toggleViewMode() {
this.viewMode = !this.viewMode
if (this.viewMode) {

View File

@ -368,7 +368,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListCategories()
})
} else {
@ -381,7 +381,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListCategories()
})
}

View File

@ -196,7 +196,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 200)
}, 400)
})
} else {
postApi
@ -209,7 +209,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 200)
}, 400)
})
}
} else {
@ -246,7 +246,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.previewSaving = false
}, 200)
}, 400)
})
})
} else {
@ -262,7 +262,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.previewSaving = false
}, 200)
}, 400)
})
})
}

View File

@ -478,6 +478,7 @@
showSizeChanger
@showSizeChange="handlePaginationChange"
@change="handlePaginationChange"
showLessItems
/>
</div>
</div>
@ -719,6 +720,7 @@ export default {
this.queryParam.status = null
this.handleClearRowKeys()
this.handlePaginationChange(1, this.pagination.size)
this.handleListCategories()
},
handleQuery() {
this.handleClearRowKeys()

View File

@ -205,7 +205,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListTags()
})
} else {
@ -218,7 +218,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListTags()
})
}

View File

@ -7,6 +7,7 @@
destroyOnClose
@close="onClose"
:visible="visible"
:afterVisibleChange="handleAfterVisibleChanged"
>
<div class="post-setting-drawer-content">
<div class="mb-4">
@ -384,13 +385,6 @@ export default {
},
selectedMetas(val) {
this.$emit('onRefreshPostMetas', val)
},
visible: function(newValue, oldValue) {
if (newValue) {
this.handleListCategories()
this.handleListPresetMetasField()
this.handleListCustomTpls()
}
}
},
computed: {
@ -409,6 +403,13 @@ export default {
...mapGetters(['options'])
},
methods: {
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListCategories()
this.handleListPresetMetasField()
this.handleListCustomTpls()
}
},
handleListCategories() {
categoryApi.listAll().then(response => {
this.categories = response.data.data
@ -506,7 +507,7 @@ export default {
setTimeout(() => {
this.saving = false
this.draftSaving = false
}, 200)
}, 400)
})
} else {
// Create the post
@ -529,7 +530,7 @@ export default {
setTimeout(() => {
this.saving = false
this.draftSaving = false
}, 200)
}, 400)
})
}
},

View File

@ -186,7 +186,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 200)
}, 400)
})
} else {
sheetApi
@ -199,7 +199,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 200)
}, 400)
})
}
} else {
@ -234,7 +234,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.previewSaving = false
}, 200)
}, 400)
})
})
} else {
@ -249,7 +249,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.previewSaving = false
}, 200)
}, 400)
})
})
}

View File

@ -314,6 +314,7 @@
showSizeChanger
@showSizeChange="handlePaginationChange"
@change="handlePaginationChange"
showLessItems
/>
</div>
<SheetSettingDrawer

View File

@ -7,6 +7,7 @@
destroyOnClose
@close="onClose"
:visible="visible"
:afterVisibleChange="handleAfterVisibleChanged"
>
<div class="post-setting-drawer-content">
<div class="mb-4">
@ -264,12 +265,6 @@ export default {
},
selectedMetas(val) {
this.$emit('onRefreshSheetMetas', val)
},
visible: function(newValue, oldValue) {
if (newValue) {
this.handleListCustomTpls()
this.handleListPresetMetasField()
}
}
},
computed: {
@ -286,6 +281,12 @@ export default {
...mapGetters(['options'])
},
methods: {
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListCustomTpls()
this.handleListPresetMetasField()
}
},
handleListPresetMetasField() {
if (this.metas.length <= 0) {
themeApi.getActivatedTheme().then(response => {
@ -359,7 +360,7 @@ export default {
setTimeout(() => {
this.saving = false
this.draftSaving = false
}, 200)
}, 400)
})
} else {
sheetApi
@ -381,7 +382,7 @@ export default {
setTimeout(() => {
this.saving = false
this.draftSaving = false
}, 200)
}, 400)
})
}
},

View File

@ -147,6 +147,7 @@
showSizeChanger
@showSizeChange="handlePaginationChange"
@change="handlePaginationChange"
showLessItems
/>
</div>
</a-list>
@ -184,9 +185,9 @@
<a-input v-model="options.journals_title" />
</a-form-item>
<a-form-item label="每页显示条数:">
<a-input
type="number"
<a-input-number
v-model="options.journals_page_size"
style="width:100%"
/>
</a-form-item>
</a-form>
@ -293,7 +294,7 @@ export default {
...mapGetters(['user'])
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
hanldeListJournals() {
this.listLoading = true
this.queryParam.page = this.pagination.page - 1
@ -402,7 +403,7 @@ export default {
})
.finally(() => {
this.hanldeListOptions()
this.loadOptions()
this.refreshOptionsCache()
})
}
}

View File

@ -337,7 +337,7 @@ export default {
this.handleListOptions()
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
handleListLinks() {
this.table.loading = true
linkApi
@ -392,7 +392,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListLinks()
_this.handleListLinkTeams()
})
@ -406,7 +406,7 @@ export default {
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
}, 400)
_this.handleListLinks()
_this.handleListLinkTeams()
})
@ -423,7 +423,7 @@ export default {
})
.finally(() => {
this.handleListOptions()
this.loadOptions()
this.refreshOptionsCache()
})
}
}

View File

@ -109,6 +109,7 @@
showSizeChanger
@change="handlePaginationChange"
@showSizeChange="handlePaginationChange"
showLessItems
/>
</div>
<div style="position: fixed;bottom: 30px;right: 30px;">
@ -140,9 +141,9 @@
<a-input v-model="options.photos_title" />
</a-form-item>
<a-form-item label="每页显示条数:">
<a-input
type="number"
<a-input-number
v-model="options.photos_page_size"
style="width:100%"
/>
</a-form-item>
</a-form>
@ -353,7 +354,7 @@ export default {
this.hanldeListOptions()
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
hanldeListPhotos() {
this.listLoading = true
this.queryParam.page = this.pagination.page - 1
@ -463,7 +464,7 @@ export default {
})
.finally(() => {
this.hanldeListOptions()
this.loadOptions()
this.refreshOptionsCache()
})
}
}

View File

@ -317,7 +317,7 @@ export default {
.finally(() => {
setTimeout(() => {
this.installing = false
}, 200)
}, 400)
})
},
handleInstall() {

View File

@ -16,6 +16,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="seo">
@ -26,6 +27,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="post">
@ -36,6 +38,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="comment">
@ -46,6 +49,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="attachment">
@ -56,6 +60,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="smtp">
@ -66,6 +71,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="other">
@ -76,6 +82,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
</a-tabs>
@ -93,6 +100,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="api">
@ -103,6 +111,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
<a-tab-pane key="advanced-other">
@ -113,6 +122,7 @@
:options="options"
@onChange="onOptionsChange"
@onSave="onSaveOptions"
:saving="saving"
/>
</a-tab-pane>
</a-tabs>
@ -166,14 +176,15 @@ export default {
data() {
return {
options: {},
advancedOptions: false
advancedOptions: false,
saving: false
}
},
created() {
this.hanldeListOptions()
},
methods: {
...mapActions(['loadUser', 'loadOptions']),
...mapActions(['refreshUserCache', 'refreshOptionsCache']),
hanldeListOptions() {
optionApi.listAll().then(response => {
this.options = response.data.data
@ -183,15 +194,19 @@ export default {
this.options = val
},
onSaveOptions() {
this.saving = true
optionApi
.save(this.options)
.then(response => {
this.$message.success('保存成功!')
})
.finally(() => {
setTimeout(() => {
this.saving = false
}, 400)
this.hanldeListOptions()
this.loadOptions()
this.loadUser()
this.refreshOptionsCache()
this.refreshUserCache()
})
}
}

View File

@ -6,6 +6,7 @@
:visible="visible"
destroyOnClose
@close="onClose"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
type="flex"
@ -33,8 +34,8 @@
type="link"
style="color: red"
icon="delete"
:loading="deleting"
@click="handleBackupDeleteClick(backup.filename)"
:loading="backup.deleting"
@click="handleBackupDeleteClick(backup)"
>删除</a-button>
<a-list-item-meta>
<a
@ -81,7 +82,6 @@ export default {
return {
backuping: false,
loading: false,
deleting: false,
backups: []
}
},
@ -96,14 +96,12 @@ export default {
default: true
}
},
watch: {
visible: function(newValue, oldValue) {
if (newValue) {
methods: {
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListBackups()
}
}
},
methods: {
},
handleListBackups() {
this.loading = true
backupApi
@ -127,21 +125,21 @@ export default {
.finally(() => {
setTimeout(() => {
this.backuping = false
}, 200)
}, 400)
this.handleListBackups()
})
},
handleBackupDeleteClick(filename) {
this.deleting = true
handleBackupDeleteClick(backup) {
backup.deleting = true
backupApi
.deleteWorkDirBackup(filename)
.deleteWorkDirBackup(backup.filename)
.then(response => {
this.$message.success('删除成功!')
})
.finally(() => {
setTimeout(() => {
this.deleting = false
}, 200)
backup.deleting = false
}, 400)
this.handleListBackups()
})
},

View File

@ -6,6 +6,7 @@
:visible="visible"
destroyOnClose
@close="onClose"
:afterVisibleChange="handleAfterVisibleChanged"
>
<a-row
type="flex"
@ -33,8 +34,8 @@
type="link"
style="color: red"
icon="delete"
:loading="deleting"
@click="handleFileDeleteClick(file.filename)"
:loading="file.deleting"
@click="handleFileDeleteClick(file)"
>删除</a-button>
<a-list-item-meta>
<a
@ -81,7 +82,6 @@ export default {
return {
backuping: false,
loading: false,
deleting: false,
files: []
}
},
@ -96,14 +96,12 @@ export default {
default: true
}
},
watch: {
visible: function(newValue, oldValue) {
if (newValue) {
methods: {
handleAfterVisibleChanged(visible) {
if (visible) {
this.handleListBackups()
}
}
},
methods: {
},
handleListBackups() {
this.loading = true
backupApi
@ -127,21 +125,21 @@ export default {
.finally(() => {
setTimeout(() => {
this.backuping = false
}, 200)
}, 400)
this.handleListBackups()
})
},
handleFileDeleteClick(filename) {
this.deleting = true
handleFileDeleteClick(file) {
file.deleting = true
backupApi
.deleteExportedData(filename)
.deleteExportedData(file.filename)
.then(response => {
this.$message.success('删除成功!')
})
.finally(() => {
setTimeout(() => {
this.deleting = false
}, 200)
file.deleting = false
}, 400)
this.handleListBackups()
})
},

View File

@ -127,6 +127,7 @@
showSizeChanger
@showSizeChange="handlePaginationChange"
@change="handlePaginationChange"
showLessItems
/>
</div>
</div>
@ -245,7 +246,7 @@ export default {
this.hanldeListOptions()
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
hanldeListOptions() {
this.loading = true
this.queryParam.page = this.pagination.page - 1
@ -274,7 +275,7 @@ export default {
})
.finally(() => {
this.hanldeListOptions()
this.loadOptions()
this.refreshOptionsCache()
})
},
handleEditOption(option) {
@ -321,7 +322,7 @@ export default {
})
.finally(() => {
this.hanldeListOptions()
this.loadOptions()
this.refreshOptionsCache()
})
} else {
this.optionToStage.type = this.optionType.CUSTOM.value
@ -334,7 +335,7 @@ export default {
})
.finally(() => {
this.hanldeListOptions()
this.loadOptions()
this.refreshOptionsCache()
})
}
}

View File

@ -34,7 +34,7 @@ export default {
this.loadFormOptions()
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
loadFormOptions() {
optionApi.listAll().then(response => {
this.options = response.data.data
@ -43,7 +43,7 @@ export default {
handleSaveOptions() {
optionApi.save(this.options).then(response => {
this.loadFormOptions()
this.loadOptions()
this.refreshOptionsCache()
this.$message.success('保存成功!')
if (!this.options.developer_mode) {
this.$router.push({ name: 'ToolList' })

View File

@ -1,22 +1,26 @@
<template>
<div>
<a-form
<a-form-model
ref="advancedOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item
<a-form-model-item
label="全局绝对路径:"
help="* 对网站上面的所有页面路径、本地附件路径、以及主题中的静态资源路径有效。"
>
<a-switch v-model="options.global_absolute_path_enabled" />
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -26,6 +30,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -35,7 +43,8 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
}
},
rules: {}
}
},
watch: {
@ -45,7 +54,12 @@ export default {
},
methods: {
handleSaveOptions() {
this.$emit('onSave')
const _this = this
_this.$refs.advancedOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,25 +1,29 @@
<template>
<div>
<a-form
<a-form-model
ref="apiOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="API 服务:">
<a-form-model-item label="API 服务:">
<a-switch v-model="options.api_enabled" />
</a-form-item>
<a-form-item label="Access key">
</a-form-model-item>
<a-form-model-item label="Access key">
<a-input-password
v-model="options.api_access_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -29,6 +33,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -38,7 +46,8 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
}
},
rules: {}
}
},
watch: {
@ -58,7 +67,12 @@ export default {
return
}
}
this.$emit('onSave')
const _this = this
_this.$refs.apiOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,25 +1,28 @@
<template>
<div>
<a-form
<a-form-model
ref="attachmentOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="上传图片时预览:">
<a-form-model-item label="上传图片时预览:">
<a-switch v-model="options.attachment_upload_image_preview_enable" />
</a-form-item>
<a-form-item label="最大上传文件数:">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="最大上传文件数:">
<a-input-number
v-model="options.attachment_upload_max_files"
style="width:100%"
/>
</a-form-item>
<a-form-item label="同时上传文件数:">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="同时上传文件数:">
<a-input-number
v-model="options.attachment_upload_max_parallel_uploads"
style="width:100%"
/>
</a-form-item>
<a-form-item label="存储位置:">
</a-form-model-item>
<a-form-model-item label="存储位置:">
<a-select v-model="options.attachment_type">
<a-select-option
v-for="item in Object.keys(attachmentType)"
@ -27,355 +30,356 @@
:value="item"
>{{ attachmentType[item].text }}</a-select-option>
</a-select>
</a-form-item>
</a-form-model-item>
<div
id="smmsForm"
v-show="options.attachment_type === 'SMMS'"
>
<a-form-item label="Secret Token">
<a-form-model-item label="Secret Token">
<a-input-password
v-model="options.smms_api_secret_token"
placeholder="需要到 sm.ms 官网注册后获取"
autocomplete="new-password"
/>
</a-form-item>
</a-form-model-item>
</div>
<div
id="upOssForm"
v-show="options.attachment_type === 'UPOSS'"
>
<a-form-item label="绑定域名协议:">
<a-form-model-item label="绑定域名协议:">
<a-select v-model="options.oss_upyun_domain_protocol">
<a-select-option value="https://">HTTPS</a-select-option>
<a-select-option value="http://">HTTP</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="绑定域名:">
</a-form-model-item>
<a-form-model-item label="绑定域名:">
<a-input
v-model="options.oss_upyun_domain"
placeholder="无需再加上 http:// 或者 https://"
/>
</a-form-item>
<a-form-item label="空间名称:">
</a-form-model-item>
<a-form-model-item label="空间名称:">
<a-input v-model="options.oss_upyun_bucket" />
</a-form-item>
<a-form-item label="操作员名称:">
</a-form-model-item>
<a-form-model-item label="操作员名称:">
<a-input v-model="options.oss_upyun_operator" />
</a-form-item>
<a-form-item label="操作员密码:">
</a-form-model-item>
<a-form-model-item label="操作员密码:">
<a-input-password
v-model="options.oss_upyun_password"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="文件目录:">
</a-form-model-item>
<a-form-model-item label="文件目录:">
<a-input v-model="options.oss_upyun_source" />
</a-form-item>
<a-form-item label="图片处理策略:">
</a-form-model-item>
<a-form-model-item label="图片处理策略:">
<a-input
v-model="options.oss_upyun_style_rule"
placeholder="间隔标识符+图片处理版本名称"
/>
</a-form-item>
<a-form-item label="缩略图处理策略:">
</a-form-model-item>
<a-form-model-item label="缩略图处理策略:">
<a-input
v-model="options.oss_upyun_thumbnail_style_rule"
placeholder="间隔标识符+图片处理版本名称,一般为后台展示所用"
/>
</a-form-item>
</a-form-model-item>
</div>
<div
id="qiniuOssForm"
v-show="options.attachment_type === 'QINIUOSS'"
>
<a-form-item label="绑定域名协议:">
<a-form-model-item label="绑定域名协议:">
<a-select v-model="options.oss_qiniu_domain_protocol">
<a-select-option value="https://">HTTPS</a-select-option>
<a-select-option value="http://">HTTP</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="绑定域名:">
</a-form-model-item>
<a-form-model-item label="绑定域名:">
<a-input
v-model="options.oss_qiniu_domain"
placeholder="无需再加上 http:// 或者 https://"
/>
</a-form-item>
<a-form-item label="区域:">
</a-form-model-item>
<a-form-model-item label="区域:">
<a-auto-complete
:dataSource="qiniuOssZones"
v-model="options.oss_qiniu_zone"
allowClear
/>
</a-form-item>
<a-form-item label="Access Key">
</a-form-model-item>
<a-form-model-item label="Access Key">
<a-input-password
v-model="options.oss_qiniu_access_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="Secret Key">
</a-form-model-item>
<a-form-model-item label="Secret Key">
<a-input-password
v-model="options.oss_qiniu_secret_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="文件目录:">
</a-form-model-item>
<a-form-model-item label="文件目录:">
<a-input
v-model="options.oss_qiniu_source"
placeholder="不填写则上传到根目录"
/>
</a-form-item>
<a-form-item label="Bucket">
</a-form-model-item>
<a-form-model-item label="Bucket">
<a-input
v-model="options.oss_qiniu_bucket"
placeholder="存储空间名称"
/>
</a-form-item>
<a-form-item label="图片处理策略:">
</a-form-model-item>
<a-form-model-item label="图片处理策略:">
<a-input
v-model="options.oss_qiniu_style_rule"
placeholder="样式分隔符+图片处理样式名称"
/>
</a-form-item>
<a-form-item label="缩略图处理策略:">
</a-form-model-item>
<a-form-model-item label="缩略图处理策略:">
<a-input
v-model="options.oss_qiniu_thumbnail_style_rule"
placeholder="样式分隔符+图片处理样式名称,一般为后台展示所用"
/>
</a-form-item>
</a-form-model-item>
</div>
<div
id="aliOssForm"
v-show="options.attachment_type === 'ALIOSS'"
>
<a-form-item label="绑定域名协议:">
<a-form-model-item label="绑定域名协议:">
<a-select v-model="options.oss_ali_domain_protocol">
<a-select-option value="https://">HTTPS</a-select-option>
<a-select-option value="http://">HTTP</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="绑定域名:">
</a-form-model-item>
<a-form-model-item label="绑定域名:">
<a-input
v-model="options.oss_ali_domain"
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
/>
</a-form-item>
<a-form-item label="Bucket">
</a-form-model-item>
<a-form-model-item label="Bucket">
<a-input
v-model="options.oss_ali_bucket_name"
placeholder="存储空间名称"
/>
</a-form-item>
<a-form-item label="EndPoint地域节点">
</a-form-model-item>
<a-form-model-item label="EndPoint地域节点">
<a-input v-model="options.oss_ali_endpoint" />
</a-form-item>
<a-form-item label="Access Key">
</a-form-model-item>
<a-form-model-item label="Access Key">
<a-input-password
v-model="options.oss_ali_access_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="Access Secret">
</a-form-model-item>
<a-form-model-item label="Access Secret">
<a-input-password
v-model="options.oss_ali_access_secret"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="文件目录:">
</a-form-model-item>
<a-form-model-item label="文件目录:">
<a-input
v-model="options.oss_ali_source"
placeholder="不填写则上传到根目录"
/>
</a-form-item>
<a-form-item label="图片处理策略:">
</a-form-model-item>
<a-form-model-item label="图片处理策略:">
<a-input
v-model="options.oss_ali_style_rule"
placeholder="请到阿里云控制台的图片处理获取"
/>
</a-form-item>
<a-form-item label="缩略图处理策略:">
</a-form-model-item>
<a-form-model-item label="缩略图处理策略:">
<a-input
v-model="options.oss_ali_thumbnail_style_rule"
placeholder="请到阿里云控制台的图片处理获取,一般为后台展示所用"
/>
</a-form-item>
</a-form-model-item>
</div>
<div
id="baiduBosForm"
v-show="options.attachment_type === 'BAIDUBOS'"
>
<a-form-item label="绑定域名协议:">
<a-form-model-item label="绑定域名协议:">
<a-select v-model="options.bos_baidu_domain_protocol">
<a-select-option value="https://">HTTPS</a-select-option>
<a-select-option value="http://">HTTP</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="绑定域名:">
</a-form-model-item>
<a-form-model-item label="绑定域名:">
<a-input
v-model="options.bos_baidu_domain"
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
/>
</a-form-item>
<a-form-item label="Bucket">
</a-form-model-item>
<a-form-model-item label="Bucket">
<a-input
v-model="options.bos_baidu_bucket_name"
placeholder="存储空间名称"
/>
</a-form-item>
<a-form-item label="EndPoint地域节点">
</a-form-model-item>
<a-form-model-item label="EndPoint地域节点">
<a-input v-model="options.bos_baidu_endpoint" />
</a-form-item>
<a-form-item label="Access Key">
</a-form-model-item>
<a-form-model-item label="Access Key">
<a-input-password
v-model="options.bos_baidu_access_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="Secret Key">
</a-form-model-item>
<a-form-model-item label="Secret Key">
<a-input-password
v-model="options.bos_baidu_secret_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="图片处理策略:">
</a-form-model-item>
<a-form-model-item label="图片处理策略:">
<a-input
v-model="options.bos_baidu_style_rule"
placeholder="请到百度云控制台的图片处理获取"
/>
</a-form-item>
<a-form-item label="缩略图处理策略:">
</a-form-model-item>
<a-form-model-item label="缩略图处理策略:">
<a-input
v-model="options.bos_baidu_thumbnail_style_rule"
placeholder="请到百度云控制台的图片处理获取,一般为后台展示所用"
/>
</a-form-item>
</a-form-model-item>
</div>
<div
id="tencentCosForm"
v-show="options.attachment_type === 'TENCENTCOS'"
>
<a-form-item label="绑定域名协议:">
<a-form-model-item label="绑定域名协议:">
<a-select v-model="options.cos_tencent_domain_protocol">
<a-select-option value="https://">HTTPS</a-select-option>
<a-select-option value="http://">HTTP</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="绑定域名:">
</a-form-model-item>
<a-form-model-item label="绑定域名:">
<a-input
v-model="options.cos_tencent_domain"
placeholder="如不填写,路径根域名将为 Bucket + 区域地址"
/>
</a-form-item>
<a-form-item label="Bucket">
</a-form-model-item>
<a-form-model-item label="Bucket">
<a-input
v-model="options.cos_tencent_bucket_name"
placeholder="存储桶名称"
/>
</a-form-item>
<a-form-item label="区域:">
</a-form-model-item>
<a-form-model-item label="区域:">
<a-auto-complete
:dataSource="tencentCosRegions"
v-model="options.cos_tencent_region"
allowClear
/>
</a-form-item>
<a-form-item label="Secret Id">
</a-form-model-item>
<a-form-model-item label="Secret Id">
<a-input-password
v-model="options.cos_tencent_secret_id"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="Secret Key">
</a-form-model-item>
<a-form-model-item label="Secret Key">
<a-input-password
v-model="options.cos_tencent_secret_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="文件目录:">
</a-form-model-item>
<a-form-model-item label="文件目录:">
<a-input
v-model="options.cos_tencent_source"
placeholder="不填写则上传到根目录"
/>
</a-form-item>
<a-form-item label="图片处理策略:">
</a-form-model-item>
<a-form-model-item label="图片处理策略:">
<a-input
v-model="options.cos_tencent_style_rule"
placeholder="请到腾讯云控制台的图片处理获取"
/>
</a-form-item>
<a-form-item label="缩略图处理策略:">
</a-form-model-item>
<a-form-model-item label="缩略图处理策略:">
<a-input
v-model="options.cos_tencent_thumbnail_style_rule"
placeholder="请到腾讯云控制台的图片处理获取,一般为后台展示所用"
/>
</a-form-item>
</a-form-model-item>
</div>
<div
id="huaweiObsForm"
v-show="options.attachment_type === 'HUAWEIOBS'"
>
<a-form-item label="绑定域名协议:">
<a-form-model-item label="绑定域名协议:">
<a-select v-model="options.obs_huawei_domain_protocol">
<a-select-option value="https://">HTTPS</a-select-option>
<a-select-option value="http://">HTTP</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="绑定域名:">
</a-form-model-item>
<a-form-model-item label="绑定域名:">
<a-input
v-model="options.obs_huawei_domain"
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
/>
</a-form-item>
<a-form-item label="Bucket桶名称">
</a-form-model-item>
<a-form-model-item label="Bucket桶名称">
<a-input
v-model="options.obs_huawei_bucket_name"
placeholder="桶名称"
/>
</a-form-item>
<a-form-item label="EndPoint终端节点">
</a-form-model-item>
<a-form-model-item label="EndPoint终端节点">
<a-input
v-model="options.obs_huawei_endpoint"
placeholder="Endpoint"
/>
</a-form-item>
<a-form-item label="Access Key">
</a-form-model-item>
<a-form-model-item label="Access Key">
<a-input-password
v-model="options.obs_huawei_access_key"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="Access Secret">
</a-form-model-item>
<a-form-model-item label="Access Secret">
<a-input-password
v-model="options.obs_huawei_access_secret"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="文件目录:">
</a-form-model-item>
<a-form-model-item label="文件目录:">
<a-input
v-model="options.obs_huawei_source"
placeholder="不填写则上传到根目录"
/>
</a-form-item>
<a-form-item label="图片处理策略:">
</a-form-model-item>
<a-form-model-item label="图片处理策略:">
<a-input
v-model="options.obs_huawei_style_rule"
placeholder="请到华为云控制台的图片处理创建"
/>
</a-form-item>
<a-form-item label="缩略图处理策略:">
</a-form-model-item>
<a-form-model-item label="缩略图处理策略:">
<a-input
v-model="options.obs_huawei_thumbnail_style_rule"
placeholder="请到华为云控制台的图片处理获取,一般为后台展示所用"
/>
</a-form-item>
</a-form-model-item>
</div>
<a-form-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -438,6 +442,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -450,7 +458,8 @@ export default {
xs: { span: 24 }
},
tencentCosRegions,
qiniuOssZones
qiniuOssZones,
rules: {}
}
},
watch: {
@ -659,7 +668,12 @@ export default {
}
break
}
this.$emit('onSave')
const _this = this
_this.$refs.attachmentOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,10 +1,13 @@
<template>
<div>
<a-form
<a-form-model
ref="commentOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="评论者头像:">
<a-form-model-item label="评论者头像:">
<a-select v-model="options.comment_gravatar_default">
<a-select-option value="mm">默认</a-select-option>
<a-select-option value="identicon">抽象几何图形</a-select-option>
@ -14,40 +17,40 @@
<a-select-option value="robohash">机器人</a-select-option>
<a-select-option value="blank">不显示头像</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="评论审核后才显示:">
</a-form-model-item>
<a-form-model-item label="评论审核后才显示:">
<a-switch v-model="options.comment_new_need_check" />
</a-form-item>
<a-form-item label="新评论通知:">
</a-form-model-item>
<a-form-model-item label="新评论通知:">
<a-switch v-model="options.comment_new_notice" />
</a-form-item>
<a-form-item label="评论回复通知对方:">
</a-form-model-item>
<a-form-model-item label="评论回复通知对方:">
<a-switch v-model="options.comment_reply_notice" />
</a-form-item>
<a-form-item
</a-form-model-item>
<a-form-model-item
label="API 评论开关:"
help="* 关闭之后将无法进行评论"
>
<a-switch v-model="options.comment_api_enabled" />
</a-form-item>
<a-form-item label="评论模块 JS">
</a-form-model-item>
<a-form-model-item label="评论模块 JS">
<a-input
type="textarea"
:autoSize="{ minRows: 2 }"
v-model="options.comment_internal_plugin_js"
placeholder="该设置仅对内置的评论模块有效"
/>
</a-form-item>
<a-form-item label="每页显示条数: ">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="每页显示条数: ">
<a-input-number
v-model="options.comment_page_size"
style="width:100%"
/>
</a-form-item>
<a-form-item label="占位提示:">
</a-form-model-item>
<a-form-model-item label="占位提示:">
<a-input v-model="options.comment_content_placeholder" />
</a-form-item>
<!-- <a-form-item
</a-form-model-item>
<!-- <a-form-model-item
label="自定义样式:"
>
@ -56,14 +59,15 @@
:autoSize="{ minRows: 5 }"
v-model="options.comment_custom_style"
/>
</a-form-item> -->
<a-form-item>
</a-form-model-item> -->
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -73,6 +77,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -82,7 +90,8 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
}
},
rules: {}
}
},
watch: {
@ -102,7 +111,12 @@ export default {
return
}
}
this.$emit('onSave')
const _this = this
_this.$refs.commentOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,65 +1,79 @@
<template>
<div>
<a-form
<a-form-model
ref="generalOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="博客标题:">
<a-form-model-item
label="博客标题:"
prop="blog_title"
>
<a-input v-model="options.blog_title" />
</a-form-item>
<a-form-item label="博客地址:">
</a-form-model-item>
<a-form-model-item
label="博客地址:"
prop="blog_url"
>
<a-input
v-model="options.blog_url"
placeholder="如https://halo.run"
/>
</a-form-item>
<a-form-item label="Logo">
</a-form-model-item>
<a-form-model-item
label="Logo"
prop="blog_logo"
>
<a-input v-model="options.blog_logo">
<a
href="javascript:void(0);"
slot="addonAfter"
@click="logoDrawerVisible = true"
@click="handleShowLogoSelector"
>
<a-icon type="picture" />
</a>
</a-input>
</a-form-item>
<a-form-item label="Favicon">
</a-form-model-item>
<a-form-model-item
label="Favicon"
prop="blog_favicon"
>
<a-input v-model="options.blog_favicon">
<a
href="javascript:void(0);"
slot="addonAfter"
@click="faviconDrawerVisible = true"
@click="handleShowFaviconSelector"
>
<a-icon type="picture" />
</a>
</a-input>
</a-form-item>
<a-form-item label="页脚信息:">
</a-form-model-item>
<a-form-model-item
label="页脚信息:"
prop="blog_footer_info"
>
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="options.blog_footer_info"
placeholder="支持 HTML 格式的文本"
/>
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
<AttachmentSelectDrawer
v-model="logoDrawerVisible"
@listenToSelect="handleSelectLogo"
title="选择 Logo"
/>
<AttachmentSelectDrawer
v-model="faviconDrawerVisible"
@listenToSelect="handleSelectFavicon"
title="选择 Favicon"
v-model="attachmentSelector.visible"
@listenToSelect="handleSelectAttachment"
:title="attachmentSelectorTitle"
/>
</div>
</template>
@ -71,6 +85,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -81,24 +99,49 @@ export default {
sm: { span: 12 },
xs: { span: 24 }
},
logoDrawerVisible: false,
faviconDrawerVisible: false
attachmentSelector: {
visible: false,
field: ''
},
rules: {
blog_title: [
{ required: true, message: '* 博客标题不能为空', trigger: ['change', 'blur'] },
{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }
],
blog_url: [
{ required: true, message: '* 博客地址不能为空', trigger: ['change', 'blur'] },
{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }
],
blog_logo: [
{ type: 'url', message: '* 链接格式不正确', trigger: ['change', 'blur'] },
{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }
],
blog_favicon: [
{ type: 'url', message: '* 链接格式不正确', trigger: ['change', 'blur'] },
{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }
],
blog_footer_info: [{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }]
}
}
},
computed: {
attachmentSelectorTitle() {
if (this.attachmentSelector.field === 'blog_logo') {
return '选择 Logo'
} else if (this.attachmentSelector.field === 'blog_favicon') {
return '选择 Favicon'
}
return ''
}
},
destroyed: function() {
if (this.faviconDrawerVisible) {
this.faviconDrawerVisible = false
}
if (this.logoDrawerVisible) {
this.logoDrawerVisible = false
if (this.attachmentSelector.visible) {
this.attachmentSelector.visible = false
}
},
beforeRouteLeave(to, from, next) {
if (this.faviconDrawerVisible) {
this.faviconDrawerVisible = false
}
if (this.logoDrawerVisible) {
this.logoDrawerVisible = false
if (this.attachmentSelector.visible) {
this.attachmentSelector.visible = false
}
next()
},
@ -109,30 +152,24 @@ export default {
},
methods: {
handleSaveOptions() {
if (!this.options.blog_title) {
this.$notification['error']({
message: '提示',
description: '博客标题不能为空!'
})
return
}
if (!this.options.blog_url) {
this.$notification['error']({
message: '提示',
description: '博客地址不能为空!'
})
return
}
this.$emit('onSave')
const _this = this
_this.$refs.generalOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
},
handleSelectLogo(data) {
this.$set(this.options, 'blog_logo', encodeURI(data.path))
this.logoDrawerVisible = false
handleShowLogoSelector() {
this.attachmentSelector.field = 'blog_logo'
this.attachmentSelector.visible = true
},
handleSelectFavicon(data) {
this.$set(this.options, 'blog_favicon', encodeURI(data.path))
this.faviconDrawerVisible = false
handleShowFaviconSelector() {
this.attachmentSelector.field = 'blog_favicon'
this.attachmentSelector.visible = true
},
handleSelectAttachment(attachment) {
this.$set(this.options, this.attachmentSelector.field, encodeURI(attachment.path))
this.attachmentSelector.visible = false
}
}
}

View File

@ -1,34 +1,37 @@
<template>
<div>
<a-form
<a-form-model
ref="otherOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="自定义全局 head">
<a-form-model-item label="自定义全局 head">
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="options.blog_custom_head"
placeholder="放置于每个页面的 <head></head> 标签中"
/>
</a-form-item>
<a-form-item label="自定义内容页 head">
</a-form-model-item>
<a-form-model-item label="自定义内容页 head">
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="options.blog_custom_content_head"
placeholder="仅放置于内容页面的 <head></head> 标签中"
/>
</a-form-item>
<a-form-item label="统计代码:">
</a-form-model-item>
<a-form-model-item label="统计代码:">
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="options.blog_statistics_code"
placeholder="第三方网站统计的代码Google Analytics、百度统计、CNZZ 等"
/>
</a-form-item>
<!-- <a-form-item
</a-form-model-item>
<!-- <a-form-model-item
label="黑名单 IP"
>
@ -38,14 +41,15 @@
v-model="options.blog_ip_blacklist"
placeholder="多个 IP 地址换行隔开"
/>
</a-form-item> -->
<a-form-item>
</a-form-model-item> -->
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -55,6 +59,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -64,7 +72,8 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
}
},
rules: {}
}
},
watch: {
@ -74,7 +83,12 @@ export default {
},
methods: {
handleSaveOptions() {
this.$emit('onSave')
const _this = this
_this.$refs.otherOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,10 +1,13 @@
<template>
<div>
<a-form
<a-form-model
ref="permalinkOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="文章固定链接类型:">
<a-form-model-item label="文章固定链接类型:">
<template slot="help">
<span v-if="options.post_permalink_type === 'DEFAULT'">{{ options.blog_url }}/{{ options.archives_prefix }}/${slug}{{ options.path_suffix }}</span>
<span v-else-if="options.post_permalink_type === 'DATE'">{{ options.blog_url }}{{ new Date() | moment_post_date }}${slug}{{ options.path_suffix }}</span>
@ -18,62 +21,63 @@
:value="item"
>{{ permalinkType[item].text }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="自定义页面前缀:">
</a-form-model-item>
<a-form-model-item label="自定义页面前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.sheet_prefix }}/${slug}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.sheet_prefix" />
</a-form-item>
<a-form-item label="友情链接页面前缀:">
</a-form-model-item>
<a-form-model-item label="友情链接页面前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.links_prefix }}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.links_prefix" />
</a-form-item>
<a-form-item label="图库页面前缀:">
</a-form-model-item>
<a-form-model-item label="图库页面前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.photos_prefix }}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.photos_prefix" />
</a-form-item>
<a-form-item label="日志页面前缀:">
</a-form-model-item>
<a-form-model-item label="日志页面前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.journals_prefix }}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.journals_prefix" />
</a-form-item>
<a-form-item label="归档前缀:">
</a-form-model-item>
<a-form-model-item label="归档前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.archives_prefix }}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.archives_prefix" />
</a-form-item>
<a-form-item label="分类前缀:">
</a-form-model-item>
<a-form-model-item label="分类前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.categories_prefix }}/${slug}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.categories_prefix" />
</a-form-item>
<a-form-item label="标签前缀:">
</a-form-model-item>
<a-form-model-item label="标签前缀:">
<template slot="help">
<span>{{ options.blog_url }}/{{ options.tags_prefix }}/${slug}{{ options.path_suffix }}</span>
</template>
<a-input v-model="options.tags_prefix" />
</a-form-item>
<a-form-item label="路径后缀:">
</a-form-model-item>
<a-form-model-item label="路径后缀:">
<template slot="help">
<span>* 格式为<code>.${suffix}</code>仅对内建路径有效</span>
</template>
<a-input v-model="options.path_suffix" />
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -84,6 +88,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -94,7 +102,8 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
}
},
rules: {}
}
},
watch: {
@ -104,7 +113,12 @@ export default {
},
methods: {
handleSaveOptions() {
this.$emit('onSave')
const _this = this
_this.$refs.permalinkOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,59 +1,63 @@
<template>
<div>
<a-form
<a-form-model
ref="postOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<!-- <a-form-item label="默认编辑器:">
<!-- <a-form-model-item label="默认编辑器:">
<a-select v-model="options.default_editor">
<a-select-option value="MARKDOWN">Markdown 编辑器</a-select-option>
<a-select-option value="RICHTEXT">富文本编辑器</a-select-option>
</a-select>
</a-form-item> -->
<a-form-item label="首页文章排序:">
</a-form-model-item> -->
<a-form-model-item label="首页文章排序:">
<a-select v-model="options.post_index_sort">
<a-select-option value="createTime">创建时间</a-select-option>
<a-select-option value="editTime">最后编辑时间</a-select-option>
<a-select-option value="visits">点击量</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="首页每页条数:">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="首页每页条数:">
<a-input-number
v-model="options.post_index_page_size"
style="width:100%"
/>
</a-form-item>
<a-form-item label="归档每页条数:">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="归档每页条数:">
<a-input-number
v-model="options.post_archives_page_size"
style="width:100%"
/>
</a-form-item>
<a-form-item label="RSS 内容类型:">
</a-form-model-item>
<a-form-model-item label="RSS 内容类型:">
<a-select v-model="options.rss_content_type">
<a-select-option value="full">全文</a-select-option>
<a-select-option value="summary">摘要</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="RSS 内容条数:">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="RSS 内容条数:">
<a-input-number
v-model="options.rss_page_size"
style="width:100%"
/>
</a-form-item>
<a-form-item label="文章摘要字数:">
<a-input
type="number"
</a-form-model-item>
<a-form-model-item label="文章摘要字数:">
<a-input-number
v-model="options.post_summary_length"
style="width:100%"
/>
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -63,6 +67,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -72,7 +80,8 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
}
},
rules: {}
}
},
watch: {
@ -82,7 +91,12 @@ export default {
},
methods: {
handleSaveOptions() {
this.$emit('onSave')
const _this = this
_this.$refs.postOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -1,32 +1,45 @@
<template>
<div>
<a-form
<a-form-model
ref="seoOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="屏蔽搜索引擎:">
<a-form-model-item
label="屏蔽搜索引擎:"
prop="seo_spider_disabled"
>
<a-switch v-model="options.seo_spider_disabled" />
</a-form-item>
<a-form-item label="关键词:">
</a-form-model-item>
<a-form-model-item
label="关键词:"
prop="seo_keywords"
>
<a-input
v-model="options.seo_keywords"
placeholder="多个关键词以英文状态下的逗号隔开"
/>
</a-form-item>
<a-form-item label="博客描述:">
</a-form-model-item>
<a-form-model-item
label="博客描述:"
prop="seo_description"
>
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="options.seo_description"
/>
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
@ -36,6 +49,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -45,6 +62,10 @@ export default {
lg: { span: 8 },
sm: { span: 12 },
xs: { span: 24 }
},
rules: {
seo_keywords: [{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }],
seo_description: [{ max: 1023, message: '* 字符数不能超过 1023', trigger: ['change', 'blur'] }]
}
}
},
@ -55,7 +76,12 @@ export default {
},
methods: {
handleSaveOptions() {
this.$emit('onSave')
const _this = this
_this.$refs.seoOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
}
}
}

View File

@ -5,71 +5,76 @@
tab="发信设置"
key="smtpoptions"
>
<a-form
<a-form-model
ref="smtpOptionsForm"
:model="options"
:rules="rules"
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="是否启用:">
<a-form-model-item label="是否启用:">
<a-switch v-model="options.email_enabled" />
</a-form-item>
<a-form-item label="SMTP 地址:">
</a-form-model-item>
<a-form-model-item label="SMTP 地址:">
<a-input v-model="options.email_host" />
</a-form-item>
<a-form-item label="发送协议:">
</a-form-model-item>
<a-form-model-item label="发送协议:">
<a-input v-model="options.email_protocol" />
</a-form-item>
<a-form-item label="SSL 端口:">
</a-form-model-item>
<a-form-model-item label="SSL 端口:">
<a-input v-model="options.email_ssl_port" />
</a-form-item>
<a-form-item label="邮箱账号:">
</a-form-model-item>
<a-form-model-item label="邮箱账号:">
<a-input v-model="options.email_username" />
</a-form-item>
<a-form-item label="邮箱密码:">
</a-form-model-item>
<a-form-model-item label="邮箱密码:">
<a-input-password
v-model="options.email_password"
placeholder="部分邮箱可能是授权码"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item label="发件人:">
</a-form-model-item>
<a-form-model-item label="发件人:">
<a-input v-model="options.email_from_name" />
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleSaveOptions"
:loading="saving"
>保存</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-tab-pane>
<a-tab-pane
tab="发送测试"
key="smtptest"
>
<a-form
<a-form-model
layout="vertical"
:wrapperCol="wrapperCol"
>
<a-form-item label="收件人:">
<a-form-model-item label="收件人:">
<a-input v-model="mailParam.to" />
</a-form-item>
<a-form-item label="主题:">
</a-form-model-item>
<a-form-model-item label="主题:">
<a-input v-model="mailParam.subject" />
</a-form-item>
<a-form-item label="内容:">
</a-form-model-item>
<a-form-model-item label="内容:">
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="mailParam.content"
/>
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-button
type="primary"
@click="handleTestMailClick"
:loading="sending"
>发送</a-button>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-tab-pane>
</a-tabs>
</div>
@ -82,6 +87,10 @@ export default {
options: {
type: Object,
required: true
},
saving: {
type: Boolean,
default: false
}
},
data() {
@ -92,7 +101,9 @@ export default {
sm: { span: 12 },
xs: { span: 24 }
},
mailParam: {}
mailParam: {},
sending: false,
rules: {}
}
},
watch: {
@ -147,7 +158,12 @@ export default {
return
}
}
this.$emit('onSave')
const _this = this
_this.$refs.smtpOptionsForm.validate(valid => {
if (valid) {
this.$emit('onSave')
}
})
},
handleTestMailClick() {
if (!this.mailParam.to) {
@ -171,9 +187,17 @@ export default {
})
return
}
mailApi.testMail(this.mailParam).then(response => {
this.$message.info(response.data.message)
})
this.sending = true
mailApi
.testMail(this.mailParam)
.then(response => {
this.$message.info(response.data.message)
})
.finally(() => {
setTimeout(() => {
this.sending = false
}, 400)
})
}
}
}

View File

@ -88,7 +88,7 @@ export default {
this.loadFormOptions()
},
methods: {
...mapActions(['loadOptions']),
...mapActions(['refreshOptionsCache']),
loadFormOptions() {
optionApi.listAll().then(response => {
this.options = response.data.data
@ -97,7 +97,7 @@ export default {
handleSaveOptions() {
optionApi.save(this.options).then(response => {
this.loadFormOptions()
this.loadOptions()
this.refreshOptionsCache()
this.$message.success('保存成功!')
})
}

View File

@ -218,7 +218,7 @@ export default {
}
},
methods: {
...mapActions(['login', 'loadUser', 'loadOptions']),
...mapActions(['login', 'refreshUserCache', 'refreshOptionsCache']),
...mapMutations({
setApiUrl: 'SET_API_URL',
restoreApiUrl: 'RESTORE_API_URL'
@ -277,13 +277,13 @@ export default {
.finally(() => {
setTimeout(() => {
this.landing = false
}, 200)
}, 400)
})
},
loginSuccess() {
// Cache the user info
this.loadUser()
this.loadOptions()
this.refreshUserCache()
this.refreshOptionsCache()
if (this.$route.query.redirect) {
this.$router.replace(this.$route.query.redirect)
} else {

View File

@ -10,41 +10,50 @@
:bordered="false"
:bodyStyle="{ padding: '16px' }"
>
<div class="profile-center-avatarHolder">
<div class="text-center mb-6">
<a-tooltip
placement="right"
:trigger="['hover']"
title="点击可修改头像"
>
<template slot="title">
<span>prompt text</span>
</template>
<div class="avatar">
<img
:src="user.avatar || '//cn.gravatar.com/avatar/?s=256&d=mm'"
@click="attachmentDrawerVisible = true"
>
</div>
<a-avatar
:size="104"
:src="user.avatar || '//cn.gravatar.com/avatar/?s=256&d=mm'"
@click="attachmentDrawerVisible = true"
class="cursor-pointer"
/>
</a-tooltip>
<div class="username">{{ user.nickname }}</div>
<div class="bio">{{ user.description }}</div>
<div
class="text-xl leading-5 font-medium mt-4 mb-1"
style="color: rgba(0, 0, 0, 0.85);"
>{{ user.nickname }}</div>
<div>{{ user.description }}</div>
</div>
<div class="profile-center-detail">
<p>
<a-icon type="link" /><a
<div>
<p class="mb-3">
<a-icon
type="link"
class="mr-3"
/><a
:href="options.blog_url"
target="method"
>{{ options.blog_url }}</a>
</p>
<p>
<a-icon type="mail" />{{ user.email }}
<p class="mb-3">
<a-icon
type="mail"
class="mr-3"
/>{{ user.email }}
</p>
<p>
<a-icon type="calendar" />{{ statistics.establishDays || 0 }}
<p class="mb-3">
<a-icon
type="calendar"
class="mr-3"
/>{{ statistics.establishDays || 0 }}
</p>
</div>
<a-divider />
<div class="general-profile">
<div>
<a-list
:loading="statisticsLoading"
itemLayout="horizontal"
@ -456,49 +465,3 @@ export default {
}
}
</script>
<style lang="less" scoped>
.profile-center-avatarHolder {
text-align: center;
margin-bottom: 24px;
& > .avatar {
margin: 0 auto;
width: 104px;
height: 104px;
margin-bottom: 20px;
border-radius: 50%;
overflow: hidden;
cursor: pointer;
img {
height: 100%;
width: 100%;
}
}
.username {
color: rgba(0, 0, 0, 0.85);
font-size: 20px;
line-height: 28px;
font-weight: 500;
margin-bottom: 4px;
}
}
.profile-center-detail {
p {
margin-bottom: 8px;
padding-left: 26px;
position: relative;
}
i {
position: absolute;
height: 14px;
width: 14px;
left: 0;
top: 4px;
}
}
</style>