mirror of https://github.com/halo-dev/halo-admin
commit
ea6d157df3
|
@ -0,0 +1,2 @@
|
|||
NODE_ENV=production
|
||||
PUBLIC_PATH=https://cdn.jsdelivr.net/npm/halo-admin@1.2.0/dist/
|
|
@ -0,0 +1,2 @@
|
|||
NODE_ENV=development
|
||||
PUBLIC_PATH=/
|
|
@ -124,4 +124,23 @@ postApi.postStatus = {
|
|||
text: '私密'
|
||||
}
|
||||
}
|
||||
|
||||
postApi.permalinkType = {
|
||||
DEFAULT: {
|
||||
type: 'DEFAULT',
|
||||
text: '默认'
|
||||
},
|
||||
DATE: {
|
||||
type: 'DATE',
|
||||
text: '年月型'
|
||||
},
|
||||
DAY: {
|
||||
type: 'DAY',
|
||||
text: '年月日型'
|
||||
},
|
||||
ID: {
|
||||
type: 'ID',
|
||||
text: 'ID 型'
|
||||
}
|
||||
}
|
||||
export default postApi
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import service from '@/utils/service'
|
||||
|
||||
const baseUrl = '/api/admin/static_page'
|
||||
|
||||
const staticPageApi = {}
|
||||
|
||||
staticPageApi.list = () => {
|
||||
return service({
|
||||
url: baseUrl,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
staticPageApi.generate = () => {
|
||||
return service({
|
||||
url: `${baseUrl}/generate`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
staticPageApi.deploy = () => {
|
||||
return service({
|
||||
url: `${baseUrl}/deploy`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
staticPageApi.deployType = {
|
||||
GIT: {
|
||||
type: 'GIT',
|
||||
text: 'Git'
|
||||
},
|
||||
NETLIFY: {
|
||||
type: 'NETLIFY',
|
||||
text: 'Netlify'
|
||||
}
|
||||
}
|
||||
|
||||
export default staticPageApi
|
|
@ -79,7 +79,7 @@ export default {
|
|||
const subItem = [h('span', { slot: 'title' }, [this.renderIcon(h, menu.meta.icon), h('span', [menu.meta.title])])]
|
||||
const itemArr = []
|
||||
const pIndex_ = pIndex + '_' + index
|
||||
console.log('menu', menu)
|
||||
this.$log.debug('menu', menu)
|
||||
if (!menu.hideChildrenInMenu) {
|
||||
menu.children.forEach(function(item, i) {
|
||||
itemArr.push(this2_.renderItem(h, item, pIndex_, i))
|
||||
|
|
|
@ -120,7 +120,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
handleFilePondInit() {
|
||||
console.log('FilePond has initialized')
|
||||
this.$log.debug('FilePond has initialized')
|
||||
},
|
||||
handleClearFileList() {
|
||||
this.$refs.pond.removeFiles()
|
||||
|
|
|
@ -911,4 +911,8 @@ body {
|
|||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input-group-addon {
|
||||
line-height: initial !important;
|
||||
}
|
|
@ -185,6 +185,13 @@ export const asyncRouterMap = [
|
|||
component: () => import('@/views/system/ToolList'),
|
||||
meta: { title: '小工具', hiddenHeaderContent: false }
|
||||
},
|
||||
{
|
||||
path: '/system/tools/staticpages',
|
||||
name: 'StaticPagesManage',
|
||||
hidden: true,
|
||||
component: () => import('@/views/system/staticpages/StaticPagesManage'),
|
||||
meta: { title: '静态部署', hiddenHeaderContent: false }
|
||||
},
|
||||
{
|
||||
path: '/system/about',
|
||||
name: 'About',
|
||||
|
|
|
@ -8,7 +8,11 @@ const keys = [
|
|||
'developer_mode',
|
||||
'attachment_upload_image_preview_enable',
|
||||
'attachment_upload_max_parallel_uploads',
|
||||
'attachment_upload_max_files'
|
||||
'attachment_upload_max_files',
|
||||
'sheet_prefix',
|
||||
'post_permalink_type',
|
||||
'archives_prefix',
|
||||
'path_suffix'
|
||||
]
|
||||
const option = {
|
||||
state: {
|
||||
|
|
|
@ -22,6 +22,14 @@ Vue.filter('moment', function(dataStr, pattern = 'YYYY-MM-DD HH:mm') {
|
|||
return moment(dataStr).format(pattern)
|
||||
})
|
||||
|
||||
Vue.filter('moment_post_date', function(dataStr, pattern = '/YYYY/M/') {
|
||||
return moment(dataStr).format(pattern)
|
||||
})
|
||||
|
||||
Vue.filter('moment_post_day', function(dataStr, pattern = '/YYYY/M/D/') {
|
||||
return moment(dataStr).format(pattern)
|
||||
})
|
||||
|
||||
Vue.filter('timeAgo', timeAgo)
|
||||
|
||||
Vue.filter('fileSizeFormat', function(value) {
|
||||
|
|
|
@ -2,7 +2,7 @@ export function actionToObject(json) {
|
|||
try {
|
||||
return JSON.parse(json)
|
||||
} catch (e) {
|
||||
console.log('err', e.message)
|
||||
this.$log.debug('err', e.message)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
|
|
@ -269,11 +269,11 @@ export default {
|
|||
const text = `${encodeURI(this.attachment.path)}`
|
||||
this.$copyText(text)
|
||||
.then(message => {
|
||||
console.log('copy', message)
|
||||
this.$log.debug('copy', message)
|
||||
this.$message.success('复制成功!')
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('copy.err', err)
|
||||
this.$log.debug('copy.err', err)
|
||||
this.$message.error('复制失败!')
|
||||
})
|
||||
},
|
||||
|
@ -281,11 +281,11 @@ export default {
|
|||
const text = `})`
|
||||
this.$copyText(text)
|
||||
.then(message => {
|
||||
console.log('copy', message)
|
||||
this.$log.debug('copy', message)
|
||||
this.$message.success('复制成功!')
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('copy.err', err)
|
||||
this.$log.debug('copy.err', err)
|
||||
this.$message.error('复制失败!')
|
||||
})
|
||||
},
|
||||
|
|
|
@ -56,13 +56,13 @@
|
|||
<a
|
||||
slot="description"
|
||||
target="_blank"
|
||||
:href="options.blog_url+'/archives/'+comment.post.url"
|
||||
:href="comment.post.fullPath"
|
||||
v-if="this.type=='posts'"
|
||||
>{{ comment.post.title }}</a>
|
||||
<a
|
||||
slot="description"
|
||||
target="_blank"
|
||||
:href="options.blog_url+'/s/'+comment.sheet.url"
|
||||
:href="comment.sheet.fullPath"
|
||||
v-else-if="this.type=='sheets'"
|
||||
>{{ comment.sheet.title }}</a>
|
||||
<span
|
||||
|
@ -125,7 +125,6 @@
|
|||
</template>
|
||||
<script>
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import commentApi from '@/api/comment'
|
||||
export default {
|
||||
name: 'CommentDetail',
|
||||
|
@ -136,7 +135,6 @@ export default {
|
|||
detailLoading: true,
|
||||
editable: false,
|
||||
commentStatus: commentApi.commentStatus,
|
||||
options: [],
|
||||
keys: ['blog_url']
|
||||
}
|
||||
},
|
||||
|
@ -163,9 +161,6 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['options'])
|
||||
},
|
||||
watch: {
|
||||
visible: function(newValue, oldValue) {
|
||||
this.$log.debug('old value', oldValue)
|
||||
|
|
|
@ -187,12 +187,12 @@
|
|||
发表在
|
||||
<a
|
||||
v-if="type==='posts'"
|
||||
:href="options.blog_url+'/archives/'+item.post.url"
|
||||
:href="item.post.fullPath"
|
||||
target="_blank"
|
||||
>《{{ item.post.title }}》</a>
|
||||
<a
|
||||
v-if="type === 'sheets'"
|
||||
:href="options.blog_url+'/s/'+item.sheet.url"
|
||||
:href="item.sheet.fullPath"
|
||||
target="_blank"
|
||||
>《{{ item.sheet.title }}》</a>
|
||||
</template>
|
||||
|
@ -282,14 +282,14 @@
|
|||
v-if="type==='posts'"
|
||||
slot="post"
|
||||
slot-scope="post"
|
||||
:href="options.blog_url+'/archives/'+post.url"
|
||||
:href="post.fullPath"
|
||||
target="_blank"
|
||||
>{{ post.title }}</a>
|
||||
<a
|
||||
v-if="type === 'sheets'"
|
||||
slot="sheet"
|
||||
slot-scope="sheet"
|
||||
:href="options.blog_url+'/s/'+sheet.url"
|
||||
:href="sheet.fullPath"
|
||||
target="_blank"
|
||||
>{{ sheet.title }}</a>
|
||||
<span
|
||||
|
@ -429,7 +429,6 @@
|
|||
</template>
|
||||
<script>
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import CommentDetail from './CommentDetail'
|
||||
import marked from 'marked'
|
||||
import commentApi from '@/api/comment'
|
||||
|
@ -561,8 +560,7 @@ export default {
|
|||
comment.content = marked(comment.content)
|
||||
return comment
|
||||
})
|
||||
},
|
||||
...mapGetters(['options'])
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadComments() {
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
<a
|
||||
v-if="item.status=='PUBLISHED' || item.status == 'INTIMATE'"
|
||||
slot="title"
|
||||
:href="options.blog_url+'/archives/'+item.url"
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
>{{ item.title }}</a>
|
||||
<a
|
||||
|
@ -322,7 +322,6 @@
|
|||
|
||||
<script>
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { PageView } from '@/layouts'
|
||||
import AnalysisCard from './components/AnalysisCard'
|
||||
import RecentCommentTab from './components/RecentCommentTab'
|
||||
|
@ -396,8 +395,7 @@ export default {
|
|||
log.type = this.logType[log.type].text
|
||||
return log
|
||||
})
|
||||
},
|
||||
...mapGetters(['options'])
|
||||
}
|
||||
},
|
||||
destroyed: function() {
|
||||
if (this.logDrawerVisible) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
target="_blank"
|
||||
>{{ item.author }}</a> 发表在 《<a
|
||||
v-if="item.post.status=='PUBLISHED' || item.post.status=='INTIMATE'"
|
||||
:href="options.blog_url+'/archives/'+item.post.url"
|
||||
:href="item.post.fullPath"
|
||||
target="_blank"
|
||||
>{{ item.post.title }}</a><a
|
||||
v-else-if="item.post.status=='DRAFT'"
|
||||
|
@ -40,7 +40,7 @@
|
|||
target="_blank"
|
||||
>{{ item.author }}</a> 发表在 《<a
|
||||
v-if="item.sheet.status=='PUBLISHED'"
|
||||
:href="options.blog_url+'/s/'+item.sheet.url"
|
||||
:href="item.sheet.fullPath"
|
||||
target="_blank"
|
||||
>{{ item.sheet.title }}</a><a
|
||||
v-else-if="item.sheet.status=='DRAFT'"
|
||||
|
@ -71,7 +71,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import commentApi from '@/api/comment'
|
||||
import postApi from '@/api/post'
|
||||
import sheetApi from '@/api/sheet'
|
||||
|
@ -101,8 +100,7 @@ export default {
|
|||
comment.content = marked(comment.content)
|
||||
return comment
|
||||
})
|
||||
},
|
||||
...mapGetters(['options'])
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadComments()
|
||||
|
|
|
@ -32,6 +32,20 @@
|
|||
v-model="categoryToCreate.parentId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="封面图"
|
||||
help="* 在分类页面可展示,需要主题支持"
|
||||
>
|
||||
<a-input v-model="categoryToCreate.thumbnail">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="()=>this.thumbnailDrawerVisible = true"
|
||||
>
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="描述:"
|
||||
help="* 分类描述,部分主题可显示"
|
||||
|
@ -206,12 +220,19 @@
|
|||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<AttachmentSelectDrawer
|
||||
v-model="thumbnailDrawerVisible"
|
||||
@listenToSelect="handleSelectThumbnail"
|
||||
title="选择封面图"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import CategorySelectTree from './components/CategorySelectTree'
|
||||
import AttachmentSelectDrawer from '../attachment/components/AttachmentSelectDrawer'
|
||||
import categoryApi from '@/api/category'
|
||||
import menuApi from '@/api/menu'
|
||||
|
||||
|
@ -239,13 +260,14 @@ const columns = [
|
|||
}
|
||||
]
|
||||
export default {
|
||||
components: { CategorySelectTree },
|
||||
components: { CategorySelectTree, AttachmentSelectDrawer },
|
||||
mixins: [mixin, mixinDevice],
|
||||
data() {
|
||||
return {
|
||||
formType: 'create',
|
||||
categories: [],
|
||||
categoryToCreate: {},
|
||||
thumbnailDrawerVisible: false,
|
||||
menu: {},
|
||||
loading: false,
|
||||
columns
|
||||
|
@ -311,11 +333,15 @@ export default {
|
|||
},
|
||||
handleCategoryToMenu(category) {
|
||||
this.menu['name'] = category.name
|
||||
this.menu['url'] = `/categories/${category.slugName}`
|
||||
this.menu['url'] = `${category.fullPath}`
|
||||
menuApi.create(this.menu).then(response => {
|
||||
this.$message.success('添加到菜单成功!')
|
||||
this.menu = {}
|
||||
})
|
||||
},
|
||||
handleSelectThumbnail(data) {
|
||||
this.$set(this.categoryToCreate, 'thumbnail', encodeURI(data.path))
|
||||
this.thumbnailDrawerVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@
|
|||
/>
|
||||
<a
|
||||
v-if="item.status=='PUBLISHED' || item.status == 'INTIMATE'"
|
||||
:href="options.blog_url+'/archives/'+item.url"
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
style="text-decoration: none;"
|
||||
>
|
||||
|
@ -318,7 +318,7 @@
|
|||
/>
|
||||
<a
|
||||
v-if="record.status=='PUBLISHED' || record.status == 'INTIMATE'"
|
||||
:href="options.blog_url+'/archives/'+record.url"
|
||||
:href="record.fullPath"
|
||||
target="_blank"
|
||||
style="text-decoration: none;"
|
||||
>
|
||||
|
@ -518,7 +518,6 @@ import TargetCommentDrawer from '../comment/components/TargetCommentDrawer'
|
|||
import AttachmentSelectDrawer from '../attachment/components/AttachmentSelectDrawer'
|
||||
import TagSelect from './components/TagSelect'
|
||||
import CategoryTree from './components/CategoryTree'
|
||||
import { mapGetters } from 'vuex'
|
||||
import categoryApi from '@/api/category'
|
||||
import postApi from '@/api/post'
|
||||
const columns = [
|
||||
|
@ -620,8 +619,7 @@ export default {
|
|||
post.statusProperty = this.postStatus[post.status]
|
||||
return post
|
||||
})
|
||||
},
|
||||
...mapGetters(['options'])
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadPosts()
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
:xs="24"
|
||||
:style="{ 'padding-bottom': '12px' }"
|
||||
>
|
||||
<a-card :title="title" :bodyStyle="{ padding: '16px' }">
|
||||
<a-card
|
||||
:title="title"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-form layout="horizontal">
|
||||
<a-form-item
|
||||
label="名称:"
|
||||
|
@ -23,6 +26,20 @@
|
|||
>
|
||||
<a-input v-model="tagToCreate.slugName" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="封面图"
|
||||
help="* 在标签页面可展示,需要主题支持"
|
||||
>
|
||||
<a-input v-model="tagToCreate.thumbnail">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="()=>this.thumbnailDrawerVisible = true"
|
||||
>
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
type="primary"
|
||||
|
@ -64,8 +81,11 @@
|
|||
:xs="24"
|
||||
:style="{ 'padding-bottom': '12px' }"
|
||||
>
|
||||
<a-card title="所有标签" :bodyStyle="{ padding: '16px' }">
|
||||
<a-empty v-if="tags.length==0"/>
|
||||
<a-card
|
||||
title="所有标签"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-empty v-if="tags.length==0" />
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
v-for="tag in tags"
|
||||
|
@ -84,18 +104,27 @@
|
|||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<AttachmentSelectDrawer
|
||||
v-model="thumbnailDrawerVisible"
|
||||
@listenToSelect="handleSelectThumbnail"
|
||||
title="选择封面图"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tagApi from '@/api/tag'
|
||||
import AttachmentSelectDrawer from '../attachment/components/AttachmentSelectDrawer'
|
||||
|
||||
export default {
|
||||
components: { AttachmentSelectDrawer },
|
||||
data() {
|
||||
return {
|
||||
formType: 'create',
|
||||
tags: [],
|
||||
tagToCreate: {}
|
||||
tagToCreate: {},
|
||||
thumbnailDrawerVisible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -155,6 +184,10 @@ export default {
|
|||
})
|
||||
}
|
||||
this.handleAddTag()
|
||||
},
|
||||
handleSelectThumbnail(data) {
|
||||
this.$set(this.tagToCreate, 'thumbnail', encodeURI(data.path))
|
||||
this.thumbnailDrawerVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,13 @@
|
|||
>
|
||||
<a-input v-model="selectedPost.title" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="文章路径:"
|
||||
:help="options.blog_url+'/archives/' + (selectedPost.url ? selectedPost.url : '{auto_generate}')"
|
||||
>
|
||||
<a-form-item label="文章路径:">
|
||||
<template slot="help">
|
||||
<span v-if="options.post_permalink_type === 'DEFAULT'">{{ options.blog_url }}/{{ options.archives_prefix }}/{{ selectedPost.url?selectedPost.url:'${url}' }}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'DATE'">{{ options.blog_url }}{{ selectedPost.createTime?selectedPost.createTime:new Date() | moment_post_date }}{{ selectedPost.url?selectedPost.url:'${url}' }}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'DAY'">{{ options.blog_url }}{{ selectedPost.createTime?selectedPost.createTime:new Date() | moment_post_day }}{{ selectedPost.url?selectedPost.url:'${url}' }}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'ID'">{{ options.blog_url }}/?p={{ selectedPost.id?selectedPost.id:'${id}' }}</span>
|
||||
</template>
|
||||
<a-input v-model="selectedPost.url" />
|
||||
</a-form-item>
|
||||
<a-form-item label="访问密码:">
|
||||
|
@ -164,7 +167,7 @@
|
|||
<a-divider />
|
||||
|
||||
<div :style="{ marginBottom: '16px' }">
|
||||
<h3 class="post-setting-drawer-title">缩略图</h3>
|
||||
<h3 class="post-setting-drawer-title">封面图</h3>
|
||||
<div class="post-setting-drawer-item">
|
||||
<div class="post-thumb">
|
||||
<img
|
||||
|
@ -177,7 +180,7 @@
|
|||
<a-form-item>
|
||||
<a-input
|
||||
v-model="selectedPost.thumbnail"
|
||||
placeholder="点击缩略图选择图片,或者输入外部链接"
|
||||
placeholder="点击封面图选择图片,或者输入外部链接"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
|
|
@ -62,12 +62,12 @@
|
|||
style="max-width: 300px;display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
>
|
||||
<a
|
||||
:href="options.blog_url+item.url"
|
||||
:href="item.url"
|
||||
target="_blank"
|
||||
v-if="item.status"
|
||||
>{{ item.title }}</a>
|
||||
<a
|
||||
:href="options.blog_url+item.url"
|
||||
:href="item.url"
|
||||
target="_blank"
|
||||
disabled
|
||||
v-else
|
||||
|
@ -124,12 +124,12 @@
|
|||
</router-link>
|
||||
<a-divider type="vertical" />
|
||||
<a
|
||||
:href="options.blog_url+record.url"
|
||||
:href="record.url"
|
||||
target="_blank"
|
||||
v-if="record.status"
|
||||
>访问</a>
|
||||
<a
|
||||
:href="options.blog_url+record.url"
|
||||
:href="record.url"
|
||||
target="_blank"
|
||||
disabled
|
||||
v-else
|
||||
|
@ -247,7 +247,7 @@
|
|||
>
|
||||
<a
|
||||
v-if="item.status=='PUBLISHED'"
|
||||
:href="options.blog_url+'/archives/'+item.url"
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
style="text-decoration: none;"
|
||||
>
|
||||
|
@ -298,7 +298,7 @@
|
|||
>
|
||||
<a
|
||||
v-if="record.status=='PUBLISHED'"
|
||||
:href="options.blog_url+'/s/'+record.url"
|
||||
:href="record.fullPath"
|
||||
target="_blank"
|
||||
style="text-decoration: none;"
|
||||
>
|
||||
|
@ -497,7 +497,7 @@ const internalColumns = [
|
|||
dataIndex: 'title'
|
||||
},
|
||||
{
|
||||
title: '访问路径',
|
||||
title: '访问地址',
|
||||
dataIndex: 'url'
|
||||
},
|
||||
{
|
||||
|
@ -637,7 +637,7 @@ export default {
|
|||
},
|
||||
handleSheetToMenu(sheet) {
|
||||
this.menu['name'] = sheet.title
|
||||
this.menu['url'] = `/s/${sheet.url}`
|
||||
this.menu['url'] = `${sheet.fullPath}`
|
||||
menuApi.create(this.menu).then(response => {
|
||||
this.$message.success('添加到菜单成功!')
|
||||
this.menu = {}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</a-form-item>
|
||||
<a-form-item
|
||||
label="页面路径:"
|
||||
:help="options.blog_url+'/s/'+ (selectedSheet.url ? selectedSheet.url : '{auto_generate}')"
|
||||
:help="options.blog_url+'/'+options.sheet_prefix+'/'+ (selectedSheet.url ? selectedSheet.url : '{auto_generate}')"
|
||||
>
|
||||
<a-input v-model="selectedSheet.url" />
|
||||
</a-form-item>
|
||||
|
@ -85,7 +85,7 @@
|
|||
<a-divider />
|
||||
|
||||
<div :style="{ marginBottom: '16px' }">
|
||||
<h3 class="post-setting-drawer-title">缩略图</h3>
|
||||
<h3 class="post-setting-drawer-title">封面图</h3>
|
||||
<div class="post-setting-drawer-item">
|
||||
<div class="sheet-thumb">
|
||||
<img
|
||||
|
@ -98,7 +98,7 @@
|
|||
<a-form-item>
|
||||
<a-input
|
||||
v-model="selectedSheet.thumbnail"
|
||||
placeholder="点击缩略图选择图片,或者输入外部链接"
|
||||
placeholder="点击封面图选择图片,或者输入外部链接"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
|
|
@ -126,7 +126,10 @@
|
|||
|
||||
<a-list-item-meta>
|
||||
<template slot="description">
|
||||
<p v-html="item.content" class="journal-list-content"></p>
|
||||
<p
|
||||
v-html="item.content"
|
||||
class="journal-list-content"
|
||||
></p>
|
||||
</template>
|
||||
<span slot="title">{{ item.createTime | moment }}</span>
|
||||
<a-avatar
|
||||
|
@ -154,6 +157,40 @@
|
|||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<div style="position: fixed;bottom: 30px;right: 30px;">
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon="setting"
|
||||
size="large"
|
||||
@click="()=>this.optionFormVisible=true"
|
||||
></a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
v-model="optionFormVisible"
|
||||
title="页面设置"
|
||||
:afterClose="onOptionFormClose"
|
||||
>
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
@click="handleSaveOptions()"
|
||||
>保存</a-button>
|
||||
</template>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="页面标题:" help="* 需要主题进行适配">
|
||||
<a-input v-model="options.journals_title" />
|
||||
</a-form-item>
|
||||
<a-form-item label="每页显示条数:">
|
||||
<a-input
|
||||
type="number"
|
||||
v-model="options.journals_page_size"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 编辑日志弹窗 -->
|
||||
<a-modal v-model="visible">
|
||||
<template slot="title">
|
||||
|
@ -211,9 +248,10 @@
|
|||
import TargetCommentDrawer from '../../comment/components/TargetCommentDrawer'
|
||||
import AttachmentDrawer from '../../attachment/components/AttachmentDrawer'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import journalApi from '@/api/journal'
|
||||
import journalCommentApi from '@/api/journalComment'
|
||||
import optionApi from '@/api/option'
|
||||
export default {
|
||||
mixins: [mixin, mixinDevice],
|
||||
components: { TargetCommentDrawer, AttachmentDrawer },
|
||||
|
@ -225,6 +263,7 @@ export default {
|
|||
visible: false,
|
||||
journalCommentVisible: false,
|
||||
attachmentDrawerVisible: false,
|
||||
optionFormVisible: false,
|
||||
pagination: {
|
||||
page: 1,
|
||||
size: 10,
|
||||
|
@ -241,16 +280,19 @@ export default {
|
|||
comments: [],
|
||||
journal: {},
|
||||
isPublic: true,
|
||||
replyComment: {}
|
||||
replyComment: {},
|
||||
options: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadJournals()
|
||||
this.loadFormOptions()
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user'])
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadOptions']),
|
||||
loadJournals() {
|
||||
this.listLoading = true
|
||||
this.queryParam.page = this.pagination.page - 1
|
||||
|
@ -262,6 +304,11 @@ export default {
|
|||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
loadFormOptions() {
|
||||
optionApi.listAll().then(response => {
|
||||
this.options = response.data.data
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.handlePaginationChange(1, this.pagination.size)
|
||||
},
|
||||
|
@ -332,6 +379,17 @@ export default {
|
|||
this.queryParam.keyword = null
|
||||
this.queryParam.type = null
|
||||
this.handlePaginationChange(1, this.pagination.size)
|
||||
},
|
||||
handleSaveOptions() {
|
||||
optionApi.save(this.options).then(response => {
|
||||
this.loadFormOptions()
|
||||
this.loadOptions()
|
||||
this.$message.success('保存成功!')
|
||||
this.optionFormVisible = false
|
||||
})
|
||||
},
|
||||
onOptionFormClose() {
|
||||
this.optionFormVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,11 +195,40 @@
|
|||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div style="position: fixed;bottom: 30px;right: 30px;">
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon="setting"
|
||||
size="large"
|
||||
@click="()=>this.optionFormVisible=true"
|
||||
></a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
v-model="optionFormVisible"
|
||||
title="页面设置"
|
||||
:afterClose="onOptionFormClose"
|
||||
>
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
@click="handleSaveOptions()"
|
||||
>保存</a-button>
|
||||
</template>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="页面标题:" help="* 需要主题进行适配">
|
||||
<a-input v-model="options.links_title" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import optionApi from '@/api/option'
|
||||
import linkApi from '@/api/link'
|
||||
const columns = [
|
||||
{
|
||||
|
@ -231,12 +260,14 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
formType: 'create',
|
||||
optionFormVisible: false,
|
||||
data: [],
|
||||
loading: false,
|
||||
columns,
|
||||
links: [],
|
||||
link: {},
|
||||
teams: []
|
||||
teams: [],
|
||||
options: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -250,8 +281,10 @@ export default {
|
|||
created() {
|
||||
this.loadLinks()
|
||||
this.loadTeams()
|
||||
this.loadFormOptions()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadOptions']),
|
||||
loadLinks() {
|
||||
this.loading = true
|
||||
linkApi.listAll().then(response => {
|
||||
|
@ -264,6 +297,11 @@ export default {
|
|||
this.teams = response.data.data
|
||||
})
|
||||
},
|
||||
loadFormOptions() {
|
||||
optionApi.listAll().then(response => {
|
||||
this.options = response.data.data
|
||||
})
|
||||
},
|
||||
handleSaveClick() {
|
||||
this.createOrUpdateLink()
|
||||
},
|
||||
|
@ -318,6 +356,17 @@ export default {
|
|||
})
|
||||
}
|
||||
this.handleAddLink()
|
||||
},
|
||||
handleSaveOptions() {
|
||||
optionApi.save(this.options).then(response => {
|
||||
this.loadFormOptions()
|
||||
this.loadOptions()
|
||||
this.$message.success('保存成功!')
|
||||
this.optionFormVisible = false
|
||||
})
|
||||
},
|
||||
onOptionFormClose() {
|
||||
this.optionFormVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,10 @@
|
|||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="table-operator" style="margin-bottom: 0;">
|
||||
<div
|
||||
class="table-operator"
|
||||
style="margin-bottom: 0;"
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
|
@ -85,7 +88,10 @@
|
|||
@click="showDrawer(item)"
|
||||
>
|
||||
<div class="photo-thumb">
|
||||
<img :src="item.thumbnail" loading="lazy">
|
||||
<img
|
||||
:src="item.thumbnail"
|
||||
loading="lazy"
|
||||
>
|
||||
</div>
|
||||
<a-card-meta style="padding: 0.8rem;">
|
||||
<ellipsis
|
||||
|
@ -110,6 +116,39 @@
|
|||
@showSizeChange="handlePaginationChange"
|
||||
/>
|
||||
</div>
|
||||
<div style="position: fixed;bottom: 30px;right: 30px;">
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon="setting"
|
||||
size="large"
|
||||
@click="()=>this.optionFormVisible=true"
|
||||
></a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
v-model="optionFormVisible"
|
||||
title="页面设置"
|
||||
:afterClose="onOptionFormClose"
|
||||
>
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
@click="handleSaveOptions()"
|
||||
>保存</a-button>
|
||||
</template>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="页面标题:" help="* 需要主题进行适配">
|
||||
<a-input v-model="options.photos_title" />
|
||||
</a-form-item>
|
||||
<a-form-item label="每页显示条数:">
|
||||
<a-input
|
||||
type="number"
|
||||
v-model="options.photos_page_size"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<a-drawer
|
||||
title="图片详情"
|
||||
:width="isMobile()?'100%':'460'"
|
||||
|
@ -137,7 +176,7 @@
|
|||
</div>
|
||||
</a-skeleton>
|
||||
</a-col>
|
||||
<a-divider style="margin: 24px 0 12px 0;"/>
|
||||
<a-divider style="margin: 24px 0 12px 0;" />
|
||||
|
||||
<a-col :span="24">
|
||||
<a-skeleton
|
||||
|
@ -289,9 +328,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import AttachmentSelectDrawer from '../../attachment/components/AttachmentSelectDrawer'
|
||||
import photoApi from '@/api/photo'
|
||||
import optionApi from '@/api/option'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -304,6 +345,7 @@ export default {
|
|||
drawerLoading: false,
|
||||
listLoading: true,
|
||||
thumDrawerVisible: false,
|
||||
optionFormVisible: false,
|
||||
photo: {},
|
||||
photos: [],
|
||||
teams: [],
|
||||
|
@ -319,14 +361,17 @@ export default {
|
|||
sort: null,
|
||||
keyword: null,
|
||||
team: null
|
||||
}
|
||||
},
|
||||
options: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadPhotos()
|
||||
this.loadTeams()
|
||||
this.loadFormOptions()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadOptions']),
|
||||
loadPhotos() {
|
||||
this.listLoading = true
|
||||
this.queryParam.page = this.pagination.page - 1
|
||||
|
@ -338,6 +383,11 @@ export default {
|
|||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
loadFormOptions() {
|
||||
optionApi.listAll().then(response => {
|
||||
this.options = response.data.data
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.handlePaginationChange(1, this.pagination.size)
|
||||
},
|
||||
|
@ -406,6 +456,17 @@ export default {
|
|||
this.drawerVisible = false
|
||||
this.photo = {}
|
||||
this.editable = false
|
||||
},
|
||||
handleSaveOptions() {
|
||||
optionApi.save(this.options).then(response => {
|
||||
this.loadFormOptions()
|
||||
this.loadOptions()
|
||||
this.$message.success('保存成功!')
|
||||
this.optionFormVisible = false
|
||||
})
|
||||
},
|
||||
onOptionFormClose() {
|
||||
this.optionFormVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<a-icon type="copy" />
|
||||
</a>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
<!-- <a-popconfirm
|
||||
slot="extra"
|
||||
placement="left"
|
||||
okText="确定"
|
||||
|
@ -41,7 +41,7 @@
|
|||
icon="cloud-download"
|
||||
>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</a-popconfirm> -->
|
||||
|
||||
<ul style="margin: 0;padding: 0;list-style: none;">
|
||||
<li>Server 版本:{{ environments.version }}</li>
|
||||
|
@ -55,10 +55,10 @@
|
|||
href="https://github.com/halo-dev"
|
||||
target="_blank"
|
||||
style="margin-right: 10px;"
|
||||
>开源地址
|
||||
>开源组织
|
||||
<a-icon type="link" /></a>
|
||||
<a
|
||||
href="https://halo.run/guide"
|
||||
href="https://halo.run"
|
||||
target="_blank"
|
||||
style="margin-right: 10px;"
|
||||
>用户文档
|
||||
|
@ -75,39 +75,26 @@
|
|||
title="开发者"
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
:loading="contributorsLoading"
|
||||
>
|
||||
<a
|
||||
:href="item.github"
|
||||
v-for="(item,index) in developers"
|
||||
:href="item.html_url"
|
||||
v-for="(item,index) in contributors"
|
||||
:key="index"
|
||||
target="_blank"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="item.name"
|
||||
:title="item.login"
|
||||
>
|
||||
<a-avatar
|
||||
size="large"
|
||||
:src="item.avatar"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:src="item.avatar_url"
|
||||
:style="{ marginRight: '10px',marginBottom: '10px'}"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a>
|
||||
</a-card>
|
||||
|
||||
<a-card
|
||||
title="时间轴"
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-timeline>
|
||||
<a-timeline-item>...</a-timeline-item>
|
||||
<a-timeline-item
|
||||
v-for="(item, index) in steps"
|
||||
:key="index"
|
||||
>{{ item.date }} {{ item.content }}</a-timeline-item>
|
||||
</a-timeline>
|
||||
</a-card>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -122,104 +109,37 @@ export default {
|
|||
return {
|
||||
adminVersion: this.VERSION,
|
||||
environments: {},
|
||||
developers: [
|
||||
contributors: [
|
||||
{
|
||||
name: 'Ryan Wang',
|
||||
avatar: '//cn.gravatar.com/avatar/7cc7f29278071bd4dce995612d428834?s=256&d=mm',
|
||||
website: 'https://ryanc.cc',
|
||||
github: 'https://github.com/ruibaby'
|
||||
},
|
||||
{
|
||||
name: 'John Niang',
|
||||
avatar: '//cn.gravatar.com/avatar/1dcf60ef27363dae539385d5bae9b2bd?s=256&d=mm',
|
||||
website: 'https://johnniang.me',
|
||||
github: 'https://github.com/johnniang'
|
||||
},
|
||||
{
|
||||
name: 'Aquan',
|
||||
avatar: '//cn.gravatar.com/avatar/3958035fa354403fa9ca3fca36b08068?s=256&d=mm',
|
||||
website: 'https://blog.eunji.cn',
|
||||
github: 'https://github.com/aquanlerou'
|
||||
},
|
||||
{
|
||||
name: 'appdev',
|
||||
avatar: '//cn.gravatar.com/avatar/08cf681fb7c6ad1b4fe70a8269c2103c?s=256&d=mm',
|
||||
website: 'https://www.apkdv.com',
|
||||
github: 'https://github.com/appdev'
|
||||
},
|
||||
{
|
||||
name: 'guqing',
|
||||
avatar: '//cn.gravatar.com/avatar/ad062ba572c8b006bfd2cbfc43fdee5e?s=256&d=mm',
|
||||
website: 'http://www.guqing.xyz',
|
||||
github: 'https://github.com/guqing'
|
||||
login: '',
|
||||
id: 0,
|
||||
node_id: '',
|
||||
avatar_url: '',
|
||||
gravatar_id: '',
|
||||
url: '',
|
||||
html_url: '',
|
||||
followers_url: '',
|
||||
following_url: '',
|
||||
gists_url: '',
|
||||
starred_url: '',
|
||||
subscriptions_url: '',
|
||||
organizations_url: '',
|
||||
repos_url: '',
|
||||
events_url: '',
|
||||
received_events_url: '',
|
||||
type: '',
|
||||
site_admin: false,
|
||||
contributions: 0
|
||||
}
|
||||
],
|
||||
steps: [
|
||||
{
|
||||
date: '2019-09-11',
|
||||
content: 'Halo v1.1.0 发布'
|
||||
},
|
||||
{
|
||||
date: '2019-07-09',
|
||||
content: 'Halo v1.0.3 发布'
|
||||
},
|
||||
{
|
||||
date: '2019-07-08',
|
||||
content: 'Star 数达到 6500'
|
||||
},
|
||||
{
|
||||
date: '2019-06-01',
|
||||
content: '1.0 正式版发布'
|
||||
},
|
||||
{
|
||||
date: '2019-05-03',
|
||||
content: 'Star 数达到 3300'
|
||||
},
|
||||
{
|
||||
date: '2019-01-30',
|
||||
content: 'John Niang 加入开发'
|
||||
},
|
||||
{
|
||||
date: '2018-10-18',
|
||||
content: '构建镜像到 Docker hub'
|
||||
},
|
||||
{
|
||||
date: '2018-09-22',
|
||||
content: 'Star 数达到 800'
|
||||
},
|
||||
{
|
||||
date: '2018-05-02',
|
||||
content: '第一条 Issue'
|
||||
},
|
||||
{
|
||||
date: '2018-05-01',
|
||||
content: 'Star 数达到 100'
|
||||
},
|
||||
{
|
||||
date: '2018-04-29',
|
||||
content: '第一个 Pull request'
|
||||
},
|
||||
{
|
||||
date: '2018-04-28',
|
||||
content: '正式开源'
|
||||
},
|
||||
{
|
||||
date: '2018-03-21',
|
||||
content: '确定命名为 Halo,并上传到 Github'
|
||||
}
|
||||
],
|
||||
updating: false
|
||||
contributorsLoading: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getEnvironments()
|
||||
this.fetchContributors()
|
||||
this.checkServerUpdate()
|
||||
this.checkAdminUpdate()
|
||||
},
|
||||
computed: {
|
||||
updateText() {
|
||||
return this.updating ? '更新中...' : '更新'
|
||||
}
|
||||
// this.checkAdminUpdate()
|
||||
},
|
||||
methods: {
|
||||
getEnvironments() {
|
||||
|
@ -227,36 +147,49 @@ export default {
|
|||
this.environments = response.data.data
|
||||
})
|
||||
},
|
||||
confirmUpdate() {
|
||||
this.updating = true
|
||||
adminApi
|
||||
.updateAdminAssets()
|
||||
.then(response => {
|
||||
this.$notification.success({
|
||||
message: '更新成功',
|
||||
description: '请刷新后体验最新版本!'
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.updating = false
|
||||
})
|
||||
},
|
||||
// confirmUpdate() {
|
||||
// this.updating = true
|
||||
// adminApi
|
||||
// .updateAdminAssets()
|
||||
// .then(response => {
|
||||
// this.$notification.success({
|
||||
// message: '更新成功',
|
||||
// description: '请刷新后体验最新版本!'
|
||||
// })
|
||||
// })
|
||||
// .finally(() => {
|
||||
// this.updating = false
|
||||
// })
|
||||
// },
|
||||
handleCopyEnvironments() {
|
||||
const text = `Server 版本:${this.environments.version}
|
||||
Admin 版本:${this.adminVersion}
|
||||
数据库:${this.environments.database}
|
||||
运行模式:${this.environments.mode}
|
||||
UA 信息:${navigator.userAgent}`
|
||||
User Agent:${navigator.userAgent}`
|
||||
this.$copyText(text)
|
||||
.then(message => {
|
||||
console.log('copy', message)
|
||||
this.$log.debug('copy', message)
|
||||
this.$message.success('复制成功!')
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('copy.err', err)
|
||||
this.$log.debug('copy.err', err)
|
||||
this.$message.error('复制失败!')
|
||||
})
|
||||
},
|
||||
async fetchContributors() {
|
||||
this.contributorsLoading = true
|
||||
const _this = this
|
||||
axios
|
||||
.get('https://api.github.com/repos/halo-dev/halo/contributors')
|
||||
.then(response => {
|
||||
_this.contributors = response.data
|
||||
this.contributorsLoading = false
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Fetch contributors error', error)
|
||||
})
|
||||
},
|
||||
async checkServerUpdate() {
|
||||
const _this = this
|
||||
|
||||
|
@ -300,48 +233,48 @@ UA 信息:${navigator.userAgent}`
|
|||
console.error('Check update fail', error)
|
||||
})
|
||||
},
|
||||
async checkAdminUpdate() {
|
||||
const _this = this
|
||||
// async checkAdminUpdate() {
|
||||
// const _this = this
|
||||
|
||||
axios
|
||||
.get('https://api.github.com/repos/halo-dev/halo-admin/releases/latest')
|
||||
.then(response => {
|
||||
const data = response.data
|
||||
if (data.draft || data.prerelease) {
|
||||
return
|
||||
}
|
||||
const current = _this.calculateIntValue(_this.adminVersion)
|
||||
const latest = _this.calculateIntValue(data.name)
|
||||
if (current >= latest) {
|
||||
return
|
||||
}
|
||||
const title = '新版本提醒'
|
||||
const content = '检测到 Admin 新版本:' + data.name + ',点击下方按钮可直接更新为最新版本。'
|
||||
this.$notification.open({
|
||||
message: title,
|
||||
description: content,
|
||||
icon: <a-icon type="smile" style="color: #108ee9" />,
|
||||
btn: h => {
|
||||
return h(
|
||||
'a-button',
|
||||
{
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'small'
|
||||
},
|
||||
on: {
|
||||
click: () => _this.confirmUpdate()
|
||||
}
|
||||
},
|
||||
'点击更新'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Check update fail', error)
|
||||
})
|
||||
},
|
||||
// axios
|
||||
// .get('https://api.github.com/repos/halo-dev/halo-admin/releases/latest')
|
||||
// .then(response => {
|
||||
// const data = response.data
|
||||
// if (data.draft || data.prerelease) {
|
||||
// return
|
||||
// }
|
||||
// const current = _this.calculateIntValue(_this.adminVersion)
|
||||
// const latest = _this.calculateIntValue(data.name)
|
||||
// if (current >= latest) {
|
||||
// return
|
||||
// }
|
||||
// const title = '新版本提醒'
|
||||
// const content = '检测到 Admin 新版本:' + data.name + ',点击下方按钮可直接更新为最新版本。'
|
||||
// this.$notification.open({
|
||||
// message: title,
|
||||
// description: content,
|
||||
// icon: <a-icon type="smile" style="color: #108ee9" />,
|
||||
// btn: h => {
|
||||
// return h(
|
||||
// 'a-button',
|
||||
// {
|
||||
// props: {
|
||||
// type: 'primary',
|
||||
// size: 'small'
|
||||
// },
|
||||
// on: {
|
||||
// click: () => _this.confirmUpdate()
|
||||
// }
|
||||
// },
|
||||
// '点击更新'
|
||||
// )
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// .catch(function(error) {
|
||||
// console.error('Check update fail', error)
|
||||
// })
|
||||
// },
|
||||
calculateIntValue(version) {
|
||||
version = version.replace(/v/g, '')
|
||||
const ss = version.split('.')
|
||||
|
|
|
@ -247,8 +247,8 @@ export default {
|
|||
handleNextStep(e) {
|
||||
e.preventDefault()
|
||||
this.bloggerForm.validateFields((error, values) => {
|
||||
console.log('error', error)
|
||||
console.log('Received values of form: ', values)
|
||||
this.$log.debug('error', error)
|
||||
this.$log.debug('Received values of form: ', values)
|
||||
if (error != null) {
|
||||
} else {
|
||||
this.stepCurrent++
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div class="card-container">
|
||||
<a-tabs type="card">
|
||||
<a-tabs
|
||||
type="card"
|
||||
class="general"
|
||||
v-if="!advancedOptions"
|
||||
>
|
||||
<a-tab-pane key="general">
|
||||
<span slot="tab">
|
||||
<a-icon type="tool" />常规设置
|
||||
|
@ -70,7 +74,7 @@
|
|||
<a-form-item label="屏蔽搜索引擎:">
|
||||
<a-switch v-model="options.seo_spider_disabled" />
|
||||
</a-form-item>
|
||||
<a-form-item label="关键词: ">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input
|
||||
v-model="options.seo_keywords"
|
||||
placeholder="多个关键词以英文状态下的逗号隔开"
|
||||
|
@ -247,6 +251,7 @@
|
|||
<a-input-password
|
||||
v-model="options.smms_api_secret_token"
|
||||
placeholder="需要到 sm.ms 官网注册后获取"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
@ -273,7 +278,10 @@
|
|||
<a-input v-model="options.oss_upyun_operator" />
|
||||
</a-form-item>
|
||||
<a-form-item label="操作员密码:">
|
||||
<a-input-password v-model="options.oss_upyun_password" />
|
||||
<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" />
|
||||
|
@ -315,10 +323,16 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="Access Key:">
|
||||
<a-input-password v-model="options.oss_qiniu_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" />
|
||||
<a-input-password
|
||||
v-model="options.oss_qiniu_secret_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="文件目录:">
|
||||
<a-input
|
||||
|
@ -371,10 +385,16 @@
|
|||
<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" />
|
||||
<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" />
|
||||
<a-input-password
|
||||
v-model="options.oss_ali_access_secret"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="文件目录:">
|
||||
<a-input
|
||||
|
@ -421,10 +441,16 @@
|
|||
<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" />
|
||||
<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" />
|
||||
<a-input-password
|
||||
v-model="options.bos_baidu_secret_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图片处理策略:">
|
||||
<a-input
|
||||
|
@ -469,10 +495,16 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="Secret Id:">
|
||||
<a-input-password v-model="options.cos_tencent_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" />
|
||||
<a-input-password
|
||||
v-model="options.cos_tencent_secret_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="文件目录:">
|
||||
<a-input
|
||||
|
@ -534,6 +566,7 @@
|
|||
<a-input-password
|
||||
v-model="options.email_password"
|
||||
placeholder="部分邮箱可能是授权码"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="发件人:">
|
||||
|
@ -579,28 +612,6 @@
|
|||
</a-tabs>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="api">
|
||||
<span slot="tab">
|
||||
<a-icon type="thunderbolt" />API 设置
|
||||
</span>
|
||||
<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" />
|
||||
</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 key="other">
|
||||
<span slot="tab">
|
||||
<a-icon type="align-left" />其他设置
|
||||
|
@ -653,10 +664,158 @@
|
|||
</a-form>
|
||||
</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>
|
||||
<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 }}/${url}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'DATE'">{{ options.blog_url }}{{ new Date() | moment_post_date }}${url}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'DAY'">{{ options.blog_url }}{{ new Date() | moment_post_day }}${url}{{ 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 }}/${url}{{ 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 }}</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 }}</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 }}</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 }}/${slugName}{{ 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 }}/${slugName}{{ options.path_suffix }}</span>
|
||||
</template>
|
||||
<a-input v-model="options.tags_prefix" />
|
||||
</a-form-item>
|
||||
<a-form-item label="路径后缀:">
|
||||
<template slot="help">
|
||||
<span>仅对内建路径有效</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>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="api">
|
||||
<span slot="tab">
|
||||
<a-icon type="api" />API 设置
|
||||
</span>
|
||||
<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>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="advanced-other">
|
||||
<span slot="tab">
|
||||
<a-icon type="align-left" />其他设置
|
||||
</span>
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<AttachmentSelectDrawer
|
||||
v-model="logoDrawerVisible"
|
||||
@listenToSelect="handleSelectLogo"
|
||||
|
@ -675,6 +834,7 @@ import { mapActions } from 'vuex'
|
|||
import optionApi from '@/api/option'
|
||||
import mailApi from '@/api/mail'
|
||||
import attachmentApi from '@/api/attachment'
|
||||
import postApi from '@/api/post'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -683,6 +843,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
attachmentType: attachmentApi.type,
|
||||
permalinkType: postApi.permalinkType,
|
||||
wrapperCol: {
|
||||
xl: { span: 8 },
|
||||
lg: { span: 8 },
|
||||
|
@ -693,6 +854,7 @@ export default {
|
|||
faviconDrawerVisible: false,
|
||||
options: [],
|
||||
mailParam: {},
|
||||
advancedOptions: false,
|
||||
tencentCosRegions: [
|
||||
{
|
||||
text: '北京一区',
|
||||
|
@ -1069,6 +1231,9 @@ export default {
|
|||
handleSelectFavicon(data) {
|
||||
this.options.blog_favicon = encodeURI(data.path)
|
||||
this.faviconDrawerVisible = false
|
||||
},
|
||||
handleAdvancedOptions() {
|
||||
this.advancedOptions = !this.advancedOptions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<div slot="title">
|
||||
<a-icon type="experiment" /> 开发者选项
|
||||
</div>
|
||||
<p>点击进入开发者选项页面</p>
|
||||
<p style="min-height: 50px;">点击进入开发者选项页面</p>
|
||||
<a-button
|
||||
type="primary"
|
||||
style="float:right"
|
||||
|
@ -26,6 +26,29 @@
|
|||
>进入</a-button>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
:style="{ marginBottom: '12px' }"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<div slot="title">
|
||||
<a-icon type="html5" /> 静态部署
|
||||
</div>
|
||||
<p style="min-height: 50px;">生成静态页面并部署到 Github Pages 之类的托管平台</p>
|
||||
<a-button
|
||||
type="primary"
|
||||
style="float:right"
|
||||
@click="handleToStaticPagesManage"
|
||||
>管理</a-button>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
|
@ -41,7 +64,7 @@
|
|||
<div slot="title">
|
||||
<a-icon type="hdd" /> 博客备份
|
||||
</div>
|
||||
<p>支持备份全站数据</p>
|
||||
<p style="min-height: 50px;">备份全站数据,支持下载到本地</p>
|
||||
<a-button
|
||||
type="primary"
|
||||
style="float:right"
|
||||
|
@ -64,7 +87,7 @@
|
|||
<div slot="title">
|
||||
<a-icon type="file-markdown" /> Markdown 文章导入
|
||||
</div>
|
||||
<p>支持 Hexo/Jekyll 文章导入并解析元数据</p>
|
||||
<p style="min-height: 50px;">支持 Hexo/Jekyll 文章导入并解析元数据</p>
|
||||
<a-button
|
||||
type="primary"
|
||||
style="float:right"
|
||||
|
@ -117,7 +140,7 @@ export default {
|
|||
handleChange(info) {
|
||||
const status = info.file.status
|
||||
if (status !== 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
this.$log.debug(info.file, info.fileList)
|
||||
}
|
||||
if (status === 'done') {
|
||||
this.$message.success(`${info.file.name} 导入成功!`)
|
||||
|
@ -128,6 +151,9 @@ export default {
|
|||
handleToDeveloperOptions() {
|
||||
this.$router.push({ name: 'DeveloperOptions' })
|
||||
},
|
||||
handleToStaticPagesManage() {
|
||||
this.$router.push({ name: 'StaticPagesManage' })
|
||||
},
|
||||
onUploadClose() {
|
||||
this.$refs.upload.handleClearFileList()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<template>
|
||||
<a-form layout="vertical">
|
||||
<a-form
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-item label="开发者选项:">
|
||||
<a-switch v-model="options.developer_mode" />
|
||||
</a-form-item>
|
||||
|
@ -18,7 +21,13 @@ export default {
|
|||
name: 'SettingsForm',
|
||||
data() {
|
||||
return {
|
||||
options: []
|
||||
options: [],
|
||||
wrapperCol: {
|
||||
xl: { span: 8 },
|
||||
lg: { span: 8 },
|
||||
sm: { span: 12 },
|
||||
xs: { span: 24 }
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</div>
|
||||
<div style="margin-top:15px">
|
||||
<a-table
|
||||
:rowKey="record => record.name"
|
||||
:rowKey="record => record.id"
|
||||
:columns="columns"
|
||||
:dataSource="sortedStatics"
|
||||
:pagination="false"
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div class="card-container">
|
||||
<a-tabs type="card">
|
||||
<a-tab-pane key="environment">
|
||||
<span slot="tab">
|
||||
<a-icon type="folder" />文件列表
|
||||
</span>
|
||||
<StaticPagesList />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="runtimeLogs">
|
||||
<span slot="tab">
|
||||
<a-icon type="appstore" />部署平台
|
||||
</span>
|
||||
<DeploySettingsForm />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="optionsList">
|
||||
<span slot="tab">
|
||||
<a-icon type="setting" />配置
|
||||
</span>
|
||||
<SettingsForm />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import StaticPagesList from './tabs/StaticPagesList'
|
||||
import DeploySettingsForm from './tabs/DeploySettingsForm'
|
||||
import SettingsForm from './tabs/SettingsForm'
|
||||
export default {
|
||||
name: 'StaticPagesManage',
|
||||
components: {
|
||||
StaticPagesList,
|
||||
DeploySettingsForm,
|
||||
SettingsForm
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<a-form
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-item label="部署平台:">
|
||||
<a-select v-model="options.static_deploy_type">
|
||||
<a-select-option
|
||||
v-for="item in Object.keys(deployType)"
|
||||
:key="item"
|
||||
:value="item"
|
||||
>{{ deployType[item].text }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<div
|
||||
id="gitForm"
|
||||
v-show="options.static_deploy_type === 'GIT'"
|
||||
>
|
||||
<a-form-item label="域名:">
|
||||
<a-input v-model="options.git_static_deploy_domain" />
|
||||
</a-form-item>
|
||||
<a-form-item label="仓库:">
|
||||
<a-input v-model="options.git_static_deploy_repository" />
|
||||
</a-form-item>
|
||||
<a-form-item label="分支:">
|
||||
<a-input v-model="options.git_static_deploy_branch" />
|
||||
</a-form-item>
|
||||
<a-form-item label="仓库用户名:">
|
||||
<a-input v-model="options.git_static_deploy_username" />
|
||||
</a-form-item>
|
||||
<a-form-item label="邮箱:">
|
||||
<a-input v-model="options.git_static_deploy_email" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Token:">
|
||||
<a-input-password
|
||||
v-model="options.git_static_deploy_token"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="CNAME:">
|
||||
<a-input v-model="options.git_static_deploy_cname" />
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div
|
||||
id="netlifyForm"
|
||||
v-show="options.static_deploy_type === 'NETLIFY'"
|
||||
>
|
||||
<a-form-item label="域名:">
|
||||
<a-input v-model="options.netlify_static_deploy_domain" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Site ID:">
|
||||
<a-input v-model="options.netlify_static_deploy_site_id" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Token:">
|
||||
<a-input-password
|
||||
v-model="options.netlify_static_deploy_token"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleSaveOptions"
|
||||
>保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
<script>
|
||||
import staticPageApi from '@/api/staticPage'
|
||||
import optionApi from '@/api/option'
|
||||
import { mapActions } from 'vuex'
|
||||
export default {
|
||||
name: 'DeploySettingsForm',
|
||||
data() {
|
||||
return {
|
||||
deployType: staticPageApi.deployType,
|
||||
wrapperCol: {
|
||||
xl: { span: 8 },
|
||||
lg: { span: 8 },
|
||||
sm: { span: 12 },
|
||||
xs: { span: 24 }
|
||||
},
|
||||
options: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadFormOptions()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadOptions']),
|
||||
loadFormOptions() {
|
||||
optionApi.listAll().then(response => {
|
||||
this.options = response.data.data
|
||||
})
|
||||
},
|
||||
handleSaveOptions() {
|
||||
optionApi.save(this.options).then(response => {
|
||||
this.loadFormOptions()
|
||||
this.loadOptions()
|
||||
this.$message.success('保存成功!')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,10 @@
|
|||
<template>
|
||||
<div>
|
||||
SettingsForm
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'SettingsForm'
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,113 @@
|
|||
<template>
|
||||
<div class="option-tab-wrapper">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<div class="table-operator">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="reload"
|
||||
@click="handleGenerate"
|
||||
>生成</a-button>
|
||||
<a-button
|
||||
icon="cloud-upload"
|
||||
@click="handleDeploy"
|
||||
:loading="deployLoading"
|
||||
:disabled="deployLoading"
|
||||
>
|
||||
部署
|
||||
</a-button>
|
||||
<a-button
|
||||
icon="sync"
|
||||
@click="loadStaticPageList"
|
||||
:loading="loading"
|
||||
:disabled="loading"
|
||||
>
|
||||
刷新
|
||||
</a-button>
|
||||
</div>
|
||||
<div style="margin-top:15px">
|
||||
<a-table
|
||||
:rowKey="record => record.id"
|
||||
:columns="columns"
|
||||
:dataSource="staticPages"
|
||||
:pagination="false"
|
||||
size="middle"
|
||||
:loading="loading"
|
||||
>
|
||||
<span
|
||||
slot="name"
|
||||
slot-scope="name"
|
||||
>
|
||||
<ellipsis
|
||||
:length="64"
|
||||
tooltip
|
||||
>
|
||||
{{ name }}
|
||||
</ellipsis>
|
||||
</span>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import staticPageApi from '@/api/staticPage'
|
||||
const columns = [
|
||||
{
|
||||
title: '文件名',
|
||||
dataIndex: 'name',
|
||||
scopedSlots: { customRender: 'name' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: 'StaticPagesList',
|
||||
data() {
|
||||
return {
|
||||
columns: columns,
|
||||
staticPages: [],
|
||||
loading: false,
|
||||
deployLoading: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadStaticPageList()
|
||||
},
|
||||
methods: {
|
||||
loadStaticPageList() {
|
||||
this.loading = true
|
||||
staticPageApi.list().then(response => {
|
||||
this.staticPages = response.data.data
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleGenerate() {
|
||||
this.loading = true
|
||||
const hide = this.$message.loading('生成中...', 0)
|
||||
staticPageApi
|
||||
.generate()
|
||||
.then(response => {
|
||||
this.$message.success('生成成功!')
|
||||
})
|
||||
.finally(response => {
|
||||
this.loadStaticPageList()
|
||||
hide()
|
||||
})
|
||||
},
|
||||
handleDeploy() {
|
||||
this.deployLoading = true
|
||||
const hide = this.$message.loading('部署中...', 0)
|
||||
staticPageApi
|
||||
.deploy()
|
||||
.then(response => {
|
||||
this.$message.success('部署成功!')
|
||||
})
|
||||
.finally(response => {
|
||||
this.deployLoading = false
|
||||
hide()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -47,6 +47,7 @@
|
|||
:style="{'animation-delay': '0.3s'}"
|
||||
>
|
||||
<a-button
|
||||
:loading="landing"
|
||||
type="primary"
|
||||
:block="true"
|
||||
@click="handleLogin"
|
||||
|
@ -139,7 +140,8 @@ export default {
|
|||
apiModifyVisible: false,
|
||||
defaultApiBefore: window.location.protocol + '//',
|
||||
apiUrl: window.location.host,
|
||||
resetPasswordButton: false
|
||||
resetPasswordButton: false,
|
||||
landing: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -169,11 +171,17 @@ export default {
|
|||
this.$message.warn('密码不能为空!')
|
||||
return
|
||||
}
|
||||
|
||||
this.login({ username: this.username, password: this.password }).then(response => {
|
||||
// Go to dashboard
|
||||
this.loginSuccess()
|
||||
})
|
||||
this.landing = true
|
||||
this.login({ username: this.username, password: this.password })
|
||||
.then(response => {
|
||||
// Go to dashboard
|
||||
this.loginSuccess()
|
||||
})
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
this.landing = false
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
loginSuccess() {
|
||||
// Cache the user info
|
||||
|
|
|
@ -107,13 +107,22 @@
|
|||
</span>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="原密码:">
|
||||
<a-input-password v-model="passwordParam.oldPassword" />
|
||||
<a-input-password
|
||||
v-model="passwordParam.oldPassword"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="新密码:">
|
||||
<a-input-password v-model="passwordParam.newPassword" />
|
||||
<a-input-password
|
||||
v-model="passwordParam.newPassword"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="确认密码:">
|
||||
<a-input-password v-model="passwordParam.confirmPassword" />
|
||||
<a-input-password
|
||||
v-model="passwordParam.confirmPassword"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
|
|
|
@ -15,19 +15,19 @@ const assetsCDN = {
|
|||
axios: 'axios',
|
||||
marked: 'marked'
|
||||
},
|
||||
css: [
|
||||
],
|
||||
css: [],
|
||||
js: [
|
||||
'//cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
|
||||
'//cdn.jsdelivr.net/npm/vue-router@3.1.3/dist/vue-router.min.js',
|
||||
'//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',
|
||||
'//cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
|
||||
'//cdn.jsdelivr.net/npm/marked@0.8.0/marked.min.js'
|
||||
'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/vue-router@3.1.3/dist/vue-router.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/marked@0.8.0/marked.min.js'
|
||||
]
|
||||
}
|
||||
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
publicPath: process.env.PUBLIC_PATH,
|
||||
configureWebpack: {
|
||||
plugins: [
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
||||
|
|
Loading…
Reference in New Issue