mirror of https://github.com/halo-dev/halo
refactor: options page. (halo-dev/console#89)
* refactor: options page. * fix: option api.pull/3445/head
parent
70538d7caf
commit
8308c66dc1
|
@ -4,16 +4,21 @@ const baseUrl = '/api/admin/options'
|
||||||
|
|
||||||
const optionApi = {}
|
const optionApi = {}
|
||||||
|
|
||||||
optionApi.listAll = keys => {
|
optionApi.listAll = () => {
|
||||||
return service({
|
return service({
|
||||||
url: `${baseUrl}/map_view`,
|
url: `${baseUrl}/map_view`,
|
||||||
params: {
|
|
||||||
key: keys
|
|
||||||
},
|
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optionApi.listAllByKeys = keys => {
|
||||||
|
return service({
|
||||||
|
url: `${baseUrl}/map_view/keys`,
|
||||||
|
data: keys,
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
optionApi.query = params => {
|
optionApi.query = params => {
|
||||||
return service({
|
return service({
|
||||||
url: `${baseUrl}/list_view`,
|
url: `${baseUrl}/list_view`,
|
||||||
|
|
|
@ -175,8 +175,8 @@ export const asyncRouterMap = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/system/options',
|
path: '/system/options',
|
||||||
name: 'OptionForm',
|
name: 'SystemOptions',
|
||||||
component: () => import('@/views/system/OptionForm'),
|
component: () => import('@/views/system/SystemOptions'),
|
||||||
meta: { title: '博客设置', hiddenHeaderContent: false }
|
meta: { title: '博客设置', hiddenHeaderContent: false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,7 @@ const option = {
|
||||||
}) {
|
}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
optionApi
|
optionApi
|
||||||
.listAll(keys)
|
.listAllByKeys(keys)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
commit('SET_OPTIONS', response.data.data)
|
commit('SET_OPTIONS', response.data.data)
|
||||||
resolve(response)
|
resolve(response)
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
</template>
|
</template>
|
||||||
<a-tag
|
<a-tag
|
||||||
color="blue"
|
color="blue"
|
||||||
style="margin-bottom: 8px"
|
style="margin-bottom: 8px;cursor:pointer;"
|
||||||
@click="handleEditTag(tag)"
|
@click="handleEditTag(tag)"
|
||||||
>{{ tag.name }}</a-tag>
|
>{{ tag.name }}</a-tag>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,198 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="24">
|
||||||
|
<div class="card-container">
|
||||||
|
<a-tabs
|
||||||
|
type="card"
|
||||||
|
class="general"
|
||||||
|
v-if="!advancedOptions"
|
||||||
|
>
|
||||||
|
<a-tab-pane key="general">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="tool" />常规设置
|
||||||
|
</span>
|
||||||
|
<GeneralTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="seo">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="global" />SEO 设置
|
||||||
|
</span>
|
||||||
|
<SeoTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="post">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="form" />文章设置
|
||||||
|
</span>
|
||||||
|
<PostTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="comment">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="message" />评论设置
|
||||||
|
</span>
|
||||||
|
<CommentTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="attachment">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="picture" />附件设置
|
||||||
|
</span>
|
||||||
|
<AttachmentTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="smtp">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="mail" />SMTP 服务
|
||||||
|
</span>
|
||||||
|
<SmtpTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="other">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="align-left" />其他设置
|
||||||
|
</span>
|
||||||
|
<OtherTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
|
||||||
|
<a-tabs
|
||||||
|
type="card"
|
||||||
|
class="advanced"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
<a-tab-pane key="permalink">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="link" />固定链接
|
||||||
|
</span>
|
||||||
|
<PermalinkTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="api">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="api" />API 设置
|
||||||
|
</span>
|
||||||
|
<ApiTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="advanced-other">
|
||||||
|
<span slot="tab">
|
||||||
|
<a-icon type="align-left" />其他设置
|
||||||
|
</span>
|
||||||
|
<AdvancedOtherTab
|
||||||
|
:options="options"
|
||||||
|
@onChange="onOptionsChange"
|
||||||
|
@onSave="onSaveOptions"
|
||||||
|
/>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</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="handleAdvancedOptions()"
|
||||||
|
></a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import GeneralTab from './optiontabs/GeneralTab'
|
||||||
|
import SeoTab from './optiontabs/SeoTab'
|
||||||
|
import PostTab from './optiontabs/PostTab'
|
||||||
|
import CommentTab from './optiontabs/CommentTab'
|
||||||
|
import AttachmentTab from './optiontabs/AttachmentTab'
|
||||||
|
import SmtpTab from './optiontabs/SmtpTab'
|
||||||
|
import OtherTab from './optiontabs/OtherTab'
|
||||||
|
import PermalinkTab from './optiontabs/PermalinkTab'
|
||||||
|
import ApiTab from './optiontabs/ApiTab'
|
||||||
|
import AdvancedOtherTab from './optiontabs/AdvancedOtherTab'
|
||||||
|
import optionApi from '@/api/option'
|
||||||
|
|
||||||
|
import { mapActions } from 'vuex'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GeneralTab,
|
||||||
|
SeoTab,
|
||||||
|
PostTab,
|
||||||
|
CommentTab,
|
||||||
|
AttachmentTab,
|
||||||
|
SmtpTab,
|
||||||
|
OtherTab,
|
||||||
|
PermalinkTab,
|
||||||
|
ApiTab,
|
||||||
|
AdvancedOtherTab
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
advancedOptions: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadFormOptions()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['loadUser', 'loadOptions']),
|
||||||
|
handleAdvancedOptions() {
|
||||||
|
this.advancedOptions = !this.advancedOptions
|
||||||
|
},
|
||||||
|
loadFormOptions() {
|
||||||
|
optionApi.listAll().then(response => {
|
||||||
|
this.options = response.data.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onOptionsChange(val) {
|
||||||
|
this.options = val
|
||||||
|
},
|
||||||
|
onSaveOptions() {
|
||||||
|
optionApi.save(this.options).then(response => {
|
||||||
|
this.loadFormOptions()
|
||||||
|
this.loadOptions()
|
||||||
|
this.loadUser()
|
||||||
|
this.$message.success('保存成功!')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,52 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item
|
||||||
|
label="全局绝对路径:"
|
||||||
|
help="* 对网站上面的所有页面路径、本地附件路径、以及主题中的静态资源路径有效。"
|
||||||
|
>
|
||||||
|
<a-switch v-model="options.global_absolute_path_enabled" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AdvancedOtherTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item label="API 服务:">
|
||||||
|
<a-switch v-model="options.api_enabled" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Access key:">
|
||||||
|
<a-input-password
|
||||||
|
v-model="options.api_access_key"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ApiTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
// API 配置验证
|
||||||
|
if (this.options.api_enabled) {
|
||||||
|
if (!this.options.api_access_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Access key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,577 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item label="上传图片时预览:">
|
||||||
|
<a-switch v-model="options.attachment_upload_image_preview_enable" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="最大上传文件数:">
|
||||||
|
<a-input
|
||||||
|
type="number"
|
||||||
|
v-model="options.attachment_upload_max_files"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="同时上传文件数:">
|
||||||
|
<a-input
|
||||||
|
type="number"
|
||||||
|
v-model="options.attachment_upload_max_parallel_uploads"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="存储位置:">
|
||||||
|
<a-select v-model="options.attachment_type">
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in Object.keys(attachmentType)"
|
||||||
|
:key="item"
|
||||||
|
:value="item"
|
||||||
|
>{{ attachmentType[item].text }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<div
|
||||||
|
id="smmsForm"
|
||||||
|
v-show="options.attachment_type === 'SMMS'"
|
||||||
|
>
|
||||||
|
<a-form-item label="Secret Token:">
|
||||||
|
<a-input-password
|
||||||
|
v-model="options.smms_api_secret_token"
|
||||||
|
placeholder="需要到 sm.ms 官网注册后获取"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="upOssForm"
|
||||||
|
v-show="options.attachment_type === 'UPOSS'"
|
||||||
|
>
|
||||||
|
<a-form-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-input
|
||||||
|
v-model="options.oss_upyun_domain"
|
||||||
|
placeholder="无需再加上 http:// 或者 https://"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="空间名称:">
|
||||||
|
<a-input v-model="options.oss_upyun_bucket" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="操作员名称:">
|
||||||
|
<a-input v-model="options.oss_upyun_operator" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="操作员密码:">
|
||||||
|
<a-input-password
|
||||||
|
v-model="options.oss_upyun_password"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="文件目录:">
|
||||||
|
<a-input v-model="options.oss_upyun_source" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图片处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_upyun_style_rule"
|
||||||
|
placeholder="间隔标识符+图片处理版本名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="缩略图处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_upyun_thumbnail_style_rule"
|
||||||
|
placeholder="间隔标识符+图片处理版本名称,一般为后台展示所用"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="qiniuOssForm"
|
||||||
|
v-show="options.attachment_type === 'QINIUOSS'"
|
||||||
|
>
|
||||||
|
<a-form-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-input
|
||||||
|
v-model="options.oss_qiniu_domain"
|
||||||
|
placeholder="无需再加上 http:// 或者 https://"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="区域:">
|
||||||
|
<a-auto-complete
|
||||||
|
:dataSource="qiniuOssZones"
|
||||||
|
v-model="options.oss_qiniu_zone"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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-input-password
|
||||||
|
v-model="options.oss_qiniu_secret_key"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="文件目录:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_qiniu_source"
|
||||||
|
placeholder="不填写则上传到根目录"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Bucket:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_qiniu_bucket"
|
||||||
|
placeholder="存储空间名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图片处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_qiniu_style_rule"
|
||||||
|
placeholder="样式分隔符+图片处理样式名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="缩略图处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_qiniu_thumbnail_style_rule"
|
||||||
|
placeholder="样式分隔符+图片处理样式名称,一般为后台展示所用"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="aliOssForm"
|
||||||
|
v-show="options.attachment_type === 'ALIOSS'"
|
||||||
|
>
|
||||||
|
<a-form-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-input
|
||||||
|
v-model="options.oss_ali_domain"
|
||||||
|
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Bucket:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_ali_bucket_name"
|
||||||
|
placeholder="存储空间名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="EndPoint(地域节点):">
|
||||||
|
<a-input v-model="options.oss_ali_endpoint" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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-input-password
|
||||||
|
v-model="options.oss_ali_access_secret"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="文件目录:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_ali_source"
|
||||||
|
placeholder="不填写则上传到根目录"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图片处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_ali_style_rule"
|
||||||
|
placeholder="请到阿里云控制台的图片处理获取"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="缩略图处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.oss_ali_thumbnail_style_rule"
|
||||||
|
placeholder="请到阿里云控制台的图片处理获取,一般为后台展示所用"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="baiduBosForm"
|
||||||
|
v-show="options.attachment_type === 'BAIDUBOS'"
|
||||||
|
>
|
||||||
|
<a-form-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-input
|
||||||
|
v-model="options.bos_baidu_domain"
|
||||||
|
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Bucket:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.bos_baidu_bucket_name"
|
||||||
|
placeholder="存储空间名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="EndPoint(地域节点):">
|
||||||
|
<a-input v-model="options.bos_baidu_endpoint" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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-input-password
|
||||||
|
v-model="options.bos_baidu_secret_key"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图片处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.bos_baidu_style_rule"
|
||||||
|
placeholder="请到百度云控制台的图片处理获取"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="缩略图处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.bos_baidu_thumbnail_style_rule"
|
||||||
|
placeholder="请到百度云控制台的图片处理获取,一般为后台展示所用"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="tencentCosForm"
|
||||||
|
v-show="options.attachment_type === 'TENCENTCOS'"
|
||||||
|
>
|
||||||
|
<a-form-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-input
|
||||||
|
v-model="options.cos_tencent_domain"
|
||||||
|
placeholder="如不填写,路径根域名将为 Bucket + 区域地址"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Bucket:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.cos_tencent_bucket_name"
|
||||||
|
placeholder="存储桶名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="区域:">
|
||||||
|
<a-auto-complete
|
||||||
|
:dataSource="tencentCosRegions"
|
||||||
|
v-model="options.cos_tencent_region"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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-input-password
|
||||||
|
v-model="options.cos_tencent_secret_key"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="文件目录:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.cos_tencent_source"
|
||||||
|
placeholder="不填写则上传到根目录"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图片处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.cos_tencent_style_rule"
|
||||||
|
placeholder="请到腾讯云控制台的图片处理获取"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="缩略图处理策略:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.cos_tencent_thumbnail_style_rule"
|
||||||
|
placeholder="请到腾讯云控制台的图片处理获取,一般为后台展示所用"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import attachmentApi from '@/api/attachment'
|
||||||
|
const tencentCosRegions = [
|
||||||
|
{
|
||||||
|
text: '北京一区',
|
||||||
|
value: 'ap-beijing-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '北京',
|
||||||
|
value: 'ap-beijing'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '上海(华东)',
|
||||||
|
value: 'ap-shanghai'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '广州(华南)',
|
||||||
|
value: 'ap-guangzhou'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '成都(西南)',
|
||||||
|
value: 'ap-chengdu'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '重庆',
|
||||||
|
value: 'ap-chongqing'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const qiniuOssZones = [
|
||||||
|
{
|
||||||
|
text: '自动选择',
|
||||||
|
value: 'auto'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '华东',
|
||||||
|
value: 'z0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '华北',
|
||||||
|
value: 'z1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '华南',
|
||||||
|
value: 'z2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '北美',
|
||||||
|
value: 'na0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '东南亚',
|
||||||
|
value: 'as0'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
export default {
|
||||||
|
name: 'AttachmentTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
attachmentType: attachmentApi.type,
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
},
|
||||||
|
tencentCosRegions,
|
||||||
|
qiniuOssZones
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
// 附件配置验证
|
||||||
|
switch (this.options.attachment_type) {
|
||||||
|
case 'SMMS':
|
||||||
|
if (!this.options.smms_api_secret_token) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Secret Token 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'UPOSS':
|
||||||
|
if (!this.options.oss_upyun_domain) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '绑定域名不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_upyun_bucket) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '空间名称不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_upyun_operator) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '操作员名称不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_upyun_password) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '操作员密码不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_upyun_source) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '文件目录不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'QINIUOSS':
|
||||||
|
if (!this.options.oss_qiniu_domain) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '绑定域名不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_qiniu_access_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Access Key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_qiniu_secret_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Secret Key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_qiniu_bucket) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Bucket 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'ALIOSS':
|
||||||
|
if (!this.options.oss_ali_bucket_name) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Bucket 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_ali_endpoint) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'EndPoint(地域节点) 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_ali_access_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Access Key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.oss_ali_access_secret) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Access Secret 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'BAIDUBOS':
|
||||||
|
if (!this.options.bos_baidu_bucket_name) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Bucket 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.bos_baidu_endpoint) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'EndPoint(地域节点) 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.bos_baidu_access_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Access Key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.bos_baidu_secret_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Secret Key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'TENCENTCOS':
|
||||||
|
if (!this.options.cos_tencent_bucket_name) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Bucket 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.cos_tencent_region) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '区域不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.cos_tencent_secret_id) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Secret Id 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.cos_tencent_secret_key) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'Secret Key 不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,109 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-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>
|
||||||
|
<a-select-option value="monsterid">小怪物</a-select-option>
|
||||||
|
<a-select-option value="wavatar">Wavatar</a-select-option>
|
||||||
|
<a-select-option value="retro">复古</a-select-option>
|
||||||
|
<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-switch v-model="options.comment_new_need_check" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="新评论通知:">
|
||||||
|
<a-switch v-model="options.comment_new_notice" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="评论回复通知对方:">
|
||||||
|
<a-switch v-model="options.comment_reply_notice" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="API 评论开关:"
|
||||||
|
help="* 关闭之后将无法进行评论"
|
||||||
|
>
|
||||||
|
<a-switch v-model="options.comment_api_enabled" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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"
|
||||||
|
v-model="options.comment_page_size"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="占位提示:">
|
||||||
|
<a-input v-model="options.comment_content_placeholder" />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item
|
||||||
|
label="自定义样式:"
|
||||||
|
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
type="textarea"
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
v-model="options.comment_custom_style"
|
||||||
|
/>
|
||||||
|
</a-form-item> -->
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'CommentTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
// 新评论通知和回复通知验证
|
||||||
|
if (this.options.comment_new_notice || this.options.comment_reply_notice) {
|
||||||
|
if (!this.options.email_enabled) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '新评论通知或回复通知需要打开和配置 SMTP 服务!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,143 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item label="博客标题:">
|
||||||
|
<a-input v-model="options.blog_title" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="博客地址:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.blog_url"
|
||||||
|
placeholder="如:https://halo.run"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Logo:">
|
||||||
|
<a-input v-model="options.blog_logo">
|
||||||
|
<a
|
||||||
|
href="javascript:void(0);"
|
||||||
|
slot="addonAfter"
|
||||||
|
@click="()=>this.logoDrawerVisible = true"
|
||||||
|
>
|
||||||
|
<a-icon type="picture" />
|
||||||
|
</a>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Favicon:">
|
||||||
|
<a-input v-model="options.blog_favicon">
|
||||||
|
<a
|
||||||
|
href="javascript:void(0);"
|
||||||
|
slot="addonAfter"
|
||||||
|
@click="()=>this.faviconDrawerVisible = true"
|
||||||
|
>
|
||||||
|
<a-icon type="picture" />
|
||||||
|
</a>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="页脚信息:">
|
||||||
|
<a-input
|
||||||
|
type="textarea"
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
v-model="options.blog_footer_info"
|
||||||
|
placeholder="支持 HTML 格式的文本"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
|
||||||
|
<AttachmentSelectDrawer
|
||||||
|
v-model="logoDrawerVisible"
|
||||||
|
@listenToSelect="handleSelectLogo"
|
||||||
|
title="选择 Logo"
|
||||||
|
/>
|
||||||
|
<AttachmentSelectDrawer
|
||||||
|
v-model="faviconDrawerVisible"
|
||||||
|
@listenToSelect="handleSelectFavicon"
|
||||||
|
title="选择 Favicon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AttachmentSelectDrawer from '../../attachment/components/AttachmentSelectDrawer'
|
||||||
|
export default {
|
||||||
|
name: 'GeneralTab',
|
||||||
|
components: {
|
||||||
|
AttachmentSelectDrawer
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
},
|
||||||
|
logoDrawerVisible: false,
|
||||||
|
faviconDrawerVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyed: function() {
|
||||||
|
if (this.faviconDrawerVisible) {
|
||||||
|
this.faviconDrawerVisible = false
|
||||||
|
}
|
||||||
|
if (this.logoDrawerVisible) {
|
||||||
|
this.logoDrawerVisible = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeRouteLeave(to, from, next) {
|
||||||
|
if (this.faviconDrawerVisible) {
|
||||||
|
this.faviconDrawerVisible = false
|
||||||
|
}
|
||||||
|
if (this.logoDrawerVisible) {
|
||||||
|
this.logoDrawerVisible = false
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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')
|
||||||
|
},
|
||||||
|
handleSelectLogo(data) {
|
||||||
|
this.$set(this.options, 'blog_logo', encodeURI(data.path))
|
||||||
|
this.logoDrawerVisible = false
|
||||||
|
},
|
||||||
|
handleSelectFavicon(data) {
|
||||||
|
this.$set(this.options, 'blog_favicon', encodeURI(data.path))
|
||||||
|
this.faviconDrawerVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,81 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-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-input
|
||||||
|
type="textarea"
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
v-model="options.blog_custom_content_head"
|
||||||
|
placeholder="仅放置于内容页面的 <head></head> 标签中"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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
|
||||||
|
label="黑名单 IP:"
|
||||||
|
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
type="textarea"
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
v-model="options.blog_ip_blacklist"
|
||||||
|
placeholder="多个 IP 地址换行隔开"
|
||||||
|
/>
|
||||||
|
</a-form-item> -->
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'OtherTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,111 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-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>
|
||||||
|
<span v-else-if="options.post_permalink_type === 'DAY'">{{ options.blog_url }}{{ new Date() | moment_post_day }}${slug}{{ options.path_suffix }}</span>
|
||||||
|
<span v-else-if="options.post_permalink_type === 'ID'">{{ options.blog_url }}/?p=${id}</span>
|
||||||
|
</template>
|
||||||
|
<a-select v-model="options.post_permalink_type">
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in Object.keys(permalinkType)"
|
||||||
|
:key="item"
|
||||||
|
:value="item"
|
||||||
|
>{{ permalinkType[item].text }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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="友情链接页面前缀:">
|
||||||
|
<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="图库页面前缀:">
|
||||||
|
<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="日志页面前缀:">
|
||||||
|
<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="归档前缀:">
|
||||||
|
<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="分类前缀:">
|
||||||
|
<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="标签前缀:">
|
||||||
|
<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="路径后缀:">
|
||||||
|
<template slot="help">
|
||||||
|
<span>* 格式为:<code>.${suffix}</code>,仅对内建路径有效</span>
|
||||||
|
</template>
|
||||||
|
<a-input v-model="options.path_suffix" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import postApi from '@/api/post'
|
||||||
|
export default {
|
||||||
|
name: 'PermalinkTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
permalinkType: postApi.permalinkType,
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,89 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-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-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"
|
||||||
|
v-model="options.post_index_page_size"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="归档每页条数:">
|
||||||
|
<a-input
|
||||||
|
type="number"
|
||||||
|
v-model="options.post_archives_page_size"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-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"
|
||||||
|
v-model="options.rss_page_size"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="文章摘要字数:">
|
||||||
|
<a-input
|
||||||
|
type="number"
|
||||||
|
v-model="options.post_summary_length"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'PostTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,62 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item label="屏蔽搜索引擎:">
|
||||||
|
<a-switch v-model="options.seo_spider_disabled" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="关键词:">
|
||||||
|
<a-input
|
||||||
|
v-model="options.seo_keywords"
|
||||||
|
placeholder="多个关键词以英文状态下的逗号隔开"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="博客描述:">
|
||||||
|
<a-input
|
||||||
|
type="textarea"
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
v-model="options.seo_description"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SeoTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
this.$emit('onSave')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,180 @@
|
||||||
|
<template>
|
||||||
|
<div class="custom-tab-wrapper">
|
||||||
|
<a-tabs>
|
||||||
|
<a-tab-pane
|
||||||
|
tab="发信设置"
|
||||||
|
key="smtpoptions"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item label="是否启用:">
|
||||||
|
<a-switch v-model="options.email_enabled" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="SMTP 地址:">
|
||||||
|
<a-input v-model="options.email_host" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="发送协议:">
|
||||||
|
<a-input v-model="options.email_protocol" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="SSL 端口:">
|
||||||
|
<a-input v-model="options.email_ssl_port" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="邮箱账号:">
|
||||||
|
<a-input v-model="options.email_username" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="邮箱密码:">
|
||||||
|
<a-input-password
|
||||||
|
v-model="options.email_password"
|
||||||
|
placeholder="部分邮箱可能是授权码"
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="发件人:">
|
||||||
|
<a-input v-model="options.email_from_name" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveOptions"
|
||||||
|
>保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane
|
||||||
|
tab="发送测试"
|
||||||
|
key="smtptest"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
:wrapperCol="wrapperCol"
|
||||||
|
>
|
||||||
|
<a-form-item label="收件人:">
|
||||||
|
<a-input v-model="mailParam.to" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="主题:">
|
||||||
|
<a-input v-model="mailParam.subject" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="内容:">
|
||||||
|
<a-input
|
||||||
|
type="textarea"
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
v-model="mailParam.content"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleTestMailClick"
|
||||||
|
>发送</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import mailApi from '@/api/mail'
|
||||||
|
export default {
|
||||||
|
name: 'SmtpTab',
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wrapperCol: {
|
||||||
|
xl: { span: 8 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
sm: { span: 12 },
|
||||||
|
xs: { span: 24 }
|
||||||
|
},
|
||||||
|
mailParam: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options(val) {
|
||||||
|
this.$emit('onChange', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSaveOptions() {
|
||||||
|
// SMTP 配置验证
|
||||||
|
if (this.options.email_enabled) {
|
||||||
|
if (!this.options.email_host) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'SMTP 地址不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.email_protocol) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '发送协议不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.email_ssl_port) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: 'SSL 端口不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.email_username) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '邮箱账号不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.email_password) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '邮箱密码不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.options.email_from_name) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '发件人不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$emit('onSave')
|
||||||
|
},
|
||||||
|
handleTestMailClick() {
|
||||||
|
if (!this.mailParam.to) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '收件人不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.mailParam.subject) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '主题不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.mailParam.content) {
|
||||||
|
this.$notification['error']({
|
||||||
|
message: '提示',
|
||||||
|
description: '内容不能为空!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mailApi.testMail(this.mailParam).then(response => {
|
||||||
|
this.$message.info(response.data.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue