mirror of https://github.com/halo-dev/halo-admin
chore: remove unnecessary dependencies.
parent
14eda89f81
commit
17e0f47465
|
@ -0,0 +1,3 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
|
@ -0,0 +1,14 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
extends: ['plugin:vue/essential', 'eslint:recommended', '@vue/prettier'],
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
yarn.lock
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
|
@ -11,6 +11,7 @@ yarn.lock
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
|
@ -19,4 +20,4 @@ yarn-error.log*
|
|||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
*.sw?
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app',
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
'useBuiltIns': 'entry'
|
||||
}
|
||||
]
|
||||
]
|
||||
presets: ['@vue/cli-plugin-babel/preset']
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"include": ["./src/**/*"]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
94
package.json
94
package.json
|
@ -47,110 +47,34 @@
|
|||
"vuex": "^3.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@vue/cli-plugin-babel": "^3.8.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "^4.5.4",
|
||||
"@vue/cli-plugin-unit-jest": "^4.5.4",
|
||||
"@vue/cli-service": "^4.5.4",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/test-utils": "^1.1.3",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babel-plugin-import": "^1.13.3",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-html": "^6.1.1",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"generate-asset-webpack-plugin": "^0.3.0",
|
||||
"husky": "^4.3.8",
|
||||
"prettier": "^1.19.1",
|
||||
"less": "^3.13.1",
|
||||
"less-loader": "^5.0.0",
|
||||
"lint-staged": "^10.5.4",
|
||||
"tailwindcss": "^1.8.8",
|
||||
"vue-svg-component-runtime": "^1.0.1",
|
||||
"vue-svg-icon-loader": "^2.1.1",
|
||||
"vue-template-compiler": "^2.6.12"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/strongly-recommended",
|
||||
"@vue/standard"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"rules": {
|
||||
"space-before-function-paren": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"generator-star-spacing": "off",
|
||||
"no-mixed-operators": 0,
|
||||
"vue/max-attributes-per-line": [
|
||||
2,
|
||||
{
|
||||
"singleline": 5,
|
||||
"multiline": {
|
||||
"max": 1,
|
||||
"allowFirstLine": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"vue/attribute-hyphenation": 0,
|
||||
"vue/html-self-closing": 0,
|
||||
"vue/component-name-in-template-casing": 0,
|
||||
"vue/html-closing-bracket-spacing": 0,
|
||||
"vue/singleline-html-element-content-newline": 0,
|
||||
"vue/no-unused-components": 0,
|
||||
"vue/multiline-html-element-content-newline": 0,
|
||||
"vue/no-use-v-if-with-v-for": 0,
|
||||
"vue/html-closing-bracket-newline": 0,
|
||||
"vue/no-parsing-error": 0,
|
||||
"no-console": 0,
|
||||
"no-tabs": 0,
|
||||
"quotes": [
|
||||
2,
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true,
|
||||
"allowTemplateLiterals": true
|
||||
}
|
||||
],
|
||||
"semi": [
|
||||
2,
|
||||
"never",
|
||||
{
|
||||
"beforeStatementContinuationChars": "never"
|
||||
}
|
||||
],
|
||||
"no-delete-var": 2,
|
||||
"prefer-const": [
|
||||
2,
|
||||
{
|
||||
"ignoreReadBeforeAssign": false
|
||||
}
|
||||
],
|
||||
"comma-dangle": 0
|
||||
}
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,vue}": [
|
||||
"eslint --fix",
|
||||
"*.{js,jsx,vue}": [
|
||||
"vue-cli-service lint",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
require('tailwindcss')
|
||||
]
|
||||
plugins: [require('autoprefixer'), require('tailwindcss')]
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
<template>
|
||||
<a-config-provider :locale="locale">
|
||||
<div
|
||||
id="app"
|
||||
class="h-full"
|
||||
>
|
||||
<div id="app" class="h-full">
|
||||
<router-view />
|
||||
</div>
|
||||
</a-config-provider>
|
||||
|
@ -21,7 +18,7 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
const { $store } = this
|
||||
deviceEnquire((deviceType) => {
|
||||
deviceEnquire(deviceType => {
|
||||
switch (deviceType) {
|
||||
case DEVICE_TYPE.DESKTOP:
|
||||
$store.commit('TOGGLE_DEVICE', 'desktop')
|
||||
|
|
|
@ -12,7 +12,7 @@ journalApi.query = params => {
|
|||
})
|
||||
}
|
||||
|
||||
journalApi.create = (journal) => {
|
||||
journalApi.create = journal => {
|
||||
return service({
|
||||
url: baseUrl,
|
||||
data: journal,
|
||||
|
|
|
@ -4,7 +4,7 @@ const baseUrl = '/api/admin/journals/comments'
|
|||
|
||||
const journalCommentApi = {}
|
||||
|
||||
journalCommentApi.create = (comment) => {
|
||||
journalCommentApi.create = comment => {
|
||||
return service({
|
||||
url: baseUrl,
|
||||
data: comment,
|
||||
|
|
|
@ -11,7 +11,7 @@ linkApi.listAll = () => {
|
|||
})
|
||||
}
|
||||
|
||||
linkApi.create = (link) => {
|
||||
linkApi.create = link => {
|
||||
return service({
|
||||
url: baseUrl,
|
||||
data: link,
|
||||
|
|
|
@ -4,7 +4,7 @@ const baseUrl = '/api/admin/logs'
|
|||
|
||||
const logApi = {}
|
||||
|
||||
logApi.listLatest = (top) => {
|
||||
logApi.listLatest = top => {
|
||||
return service({
|
||||
url: `${baseUrl}/latest`,
|
||||
params: {
|
||||
|
|
|
@ -12,7 +12,7 @@ photoApi.query = params => {
|
|||
})
|
||||
}
|
||||
|
||||
photoApi.create = (photo) => {
|
||||
photoApi.create = photo => {
|
||||
return service({
|
||||
url: baseUrl,
|
||||
data: photo,
|
||||
|
|
|
@ -105,6 +105,6 @@ sheetApi.permalinkType = {
|
|||
ROOT: {
|
||||
type: 'ROOT',
|
||||
text: '根路径'
|
||||
},
|
||||
}
|
||||
}
|
||||
export default sheetApi
|
||||
|
|
|
@ -30,7 +30,7 @@ userApi.updatePassword = (oldPassword, newPassword) => {
|
|||
})
|
||||
}
|
||||
|
||||
userApi.mfaGenerate = (mfaType) => {
|
||||
userApi.mfaGenerate = mfaType => {
|
||||
return service({
|
||||
url: `${baseUrl}/mfa/generate`,
|
||||
method: 'put',
|
||||
|
@ -52,7 +52,7 @@ userApi.mfaUpdate = (mfaType, mfaKey, authcode) => {
|
|||
})
|
||||
}
|
||||
|
||||
userApi.mfaCheck = (authcode) => {
|
||||
userApi.mfaCheck = authcode => {
|
||||
return service({
|
||||
url: `${baseUrl}/mfa/check`,
|
||||
method: 'put',
|
||||
|
|
|
@ -2,32 +2,21 @@
|
|||
<div>
|
||||
<a-drawer
|
||||
:title="title"
|
||||
:width="isMobile()?'100%':drawerWidth"
|
||||
:width="isMobile() ? '100%' : drawerWidth"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-input-search
|
||||
placeholder="搜索"
|
||||
v-model="queryParam.keyword"
|
||||
@search="handleQuery()"
|
||||
enterButton
|
||||
/>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-input-search placeholder="搜索" v-model="queryParam.keyword" @search="handleQuery()" enterButton />
|
||||
</a-row>
|
||||
<a-divider />
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-spin :spinning="loading">
|
||||
<a-empty v-if="attachments.length==0" />
|
||||
<a-empty v-if="attachments.length == 0" />
|
||||
<div
|
||||
v-else
|
||||
class="attach-item"
|
||||
|
@ -36,11 +25,7 @@
|
|||
@click="handleSelectAttachment(item)"
|
||||
>
|
||||
<span v-show="!handleJudgeMediaType(item)">当前格式不支持预览</span>
|
||||
<img
|
||||
:src="item.thumbPath"
|
||||
v-show="handleJudgeMediaType(item)"
|
||||
loading="lazy"
|
||||
>
|
||||
<img :src="item.thumbPath" v-show="handleJudgeMediaType(item)" loading="lazy" />
|
||||
</div>
|
||||
</a-spin>
|
||||
</a-col>
|
||||
|
@ -58,30 +43,14 @@
|
|||
<a-divider class="divider-transparent" />
|
||||
<div class="bottom-control">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="dashed"
|
||||
v-if="isChooseAvatar"
|
||||
@click="handleSelectGravatar"
|
||||
>使用 Gravatar</a-button>
|
||||
<a-button
|
||||
@click="handleShowUploadModal"
|
||||
type="primary"
|
||||
>上传附件</a-button>
|
||||
<a-button type="dashed" v-if="isChooseAvatar" @click="handleSelectGravatar">使用 Gravatar</a-button>
|
||||
<a-button @click="handleShowUploadModal" type="primary">上传附件</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
||||
<a-modal
|
||||
title="上传附件"
|
||||
v-model="uploadVisible"
|
||||
:footer="null"
|
||||
:afterClose="onUploadClose"
|
||||
destroyOnClose
|
||||
>
|
||||
<FilePondUpload
|
||||
ref="upload"
|
||||
:uploadHandler="uploadHandler"
|
||||
></FilePondUpload>
|
||||
<a-modal title="上传附件" v-model="uploadVisible" :footer="null" :afterClose="onUploadClose" destroyOnClose>
|
||||
<FilePondUpload ref="upload" :uploadHandler="uploadHandler"></FilePondUpload>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -150,7 +119,7 @@ export default {
|
|||
this.queryParam.sort = this.pagination.sort
|
||||
attachmentApi
|
||||
.query(this.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.attachments = response.data.data.content
|
||||
this.pagination.total = response.data.data.total
|
||||
})
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
:loading="loading"
|
||||
:size="size"
|
||||
:block="block"
|
||||
>{{ computedText }}</a-button>
|
||||
>{{ computedText }}</a-button
|
||||
>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
|
@ -14,45 +15,45 @@ export default {
|
|||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'primary',
|
||||
default: 'primary'
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
default: 'default'
|
||||
},
|
||||
block: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
errored: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: '',
|
||||
default: ''
|
||||
},
|
||||
loadedText: {
|
||||
type: String,
|
||||
default: '',
|
||||
default: ''
|
||||
},
|
||||
erroredText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
hasError: false,
|
||||
hasError: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -68,7 +69,7 @@ export default {
|
|||
this.$emit('callback')
|
||||
}, 400)
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
computedType() {
|
||||
|
@ -88,12 +89,12 @@ export default {
|
|||
return this.hasError ? this.erroredText : this.loadedText
|
||||
}
|
||||
return this.text
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
this.$emit('click')
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -20,19 +20,19 @@ import attachmentApi from '@/api/attachment'
|
|||
export default {
|
||||
name: 'MarkdownEditor',
|
||||
components: {
|
||||
haloEditor,
|
||||
haloEditor
|
||||
},
|
||||
props: {
|
||||
originalContent: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
toolbars,
|
||||
originalContentData: '',
|
||||
originalContentData: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -41,13 +41,13 @@ export default {
|
|||
},
|
||||
originalContentData(val) {
|
||||
this.$emit('onContentChange', val)
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAttachmentUpload(pos, $file) {
|
||||
var formdata = new FormData()
|
||||
formdata.append('file', $file)
|
||||
attachmentApi.upload(formdata).then((response) => {
|
||||
attachmentApi.upload(formdata).then(response => {
|
||||
var responseObject = response.data
|
||||
var HaloEditor = this.$refs.md
|
||||
HaloEditor.$img2Url(pos, encodeURI(responseObject.data.path))
|
||||
|
@ -55,7 +55,7 @@ export default {
|
|||
},
|
||||
handleSaveDraft() {
|
||||
this.$emit('onSaveDraft')
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-input
|
||||
type="textarea"
|
||||
v-model="originalContent"
|
||||
:rows="16"
|
||||
/>
|
||||
<a-input type="textarea" v-model="originalContent" :rows="16" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
|
|
@ -42,7 +42,7 @@ export default {
|
|||
},
|
||||
render() {
|
||||
const { tooltip, length } = this.$props
|
||||
const str = this.$slots.default.map((vNode) => vNode.text).join('')
|
||||
const str = this.$slots.default.map(vNode => vNode.text).join('')
|
||||
const fullLength = getStrFullLength(str)
|
||||
const strDom = tooltip && fullLength > length ? this.getTooltip(str, fullLength) : this.getStrDom(str, fullLength)
|
||||
return strDom
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
<template>
|
||||
<div
|
||||
class="footer text-center"
|
||||
style="padding: 0 16px;margin: 48px 0 0;"
|
||||
>
|
||||
<div
|
||||
class="copyright"
|
||||
style="color: rgba(0, 0, 0, 0.45);font-size: 14px;"
|
||||
>
|
||||
<div class="footer text-center" style="padding: 0 16px;margin: 48px 0 0;">
|
||||
<div class="copyright" style="color: rgba(0, 0, 0, 0.45);font-size: 14px;">
|
||||
Proudly power by
|
||||
<router-link :to="{ name:'About' }">
|
||||
<router-link :to="{ name: 'About' }">
|
||||
Halo
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
|
@ -1,54 +1,30 @@
|
|||
<template>
|
||||
<transition name="showHeader">
|
||||
<div
|
||||
v-if="visible"
|
||||
class="header-animat"
|
||||
>
|
||||
<div v-if="visible" class="header-animat">
|
||||
<a-layout-header
|
||||
v-if="visible"
|
||||
:class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
|
||||
:class="[
|
||||
fixedHeader && 'ant-header-fixedHeader',
|
||||
sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed'
|
||||
]"
|
||||
style="padding:0"
|
||||
>
|
||||
<div
|
||||
v-if="mode === 'sidemenu'"
|
||||
class="header"
|
||||
>
|
||||
<div v-if="mode === 'sidemenu'" class="header">
|
||||
<a-icon
|
||||
v-if="device==='mobile'"
|
||||
v-if="device === 'mobile'"
|
||||
class="trigger"
|
||||
:type="collapsed ? 'menu-fold' : 'menu-unfold'"
|
||||
@click="toggle"
|
||||
/>
|
||||
<a-icon
|
||||
v-else
|
||||
class="trigger"
|
||||
:type="collapsed ? 'menu-unfold' : 'menu-fold'"
|
||||
@click="toggle"
|
||||
/>
|
||||
<a-icon v-else class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggle" />
|
||||
<user-menu></user-menu>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
:class="['top-nav-header-index', theme]"
|
||||
>
|
||||
<div v-else :class="['top-nav-header-index', theme]">
|
||||
<div class="header-index-wide">
|
||||
<div class="header-index-left">
|
||||
<logo
|
||||
class="top-nav-header"
|
||||
v-if="device !== 'mobile'"
|
||||
/>
|
||||
<s-menu
|
||||
v-if="device !== 'mobile'"
|
||||
mode="horizontal"
|
||||
:menu="menus"
|
||||
:theme="theme"
|
||||
/>
|
||||
<a-icon
|
||||
v-else
|
||||
class="trigger"
|
||||
:type="collapsed ? 'menu-fold' : 'menu-unfold'"
|
||||
@click="toggle"
|
||||
/>
|
||||
<logo class="top-nav-header" v-if="device !== 'mobile'" />
|
||||
<s-menu v-if="device !== 'mobile'" mode="horizontal" :menu="menus" :theme="theme" />
|
||||
<a-icon v-else class="trigger" :type="collapsed ? 'menu-fold' : 'menu-unfold'" @click="toggle" />
|
||||
</div>
|
||||
<user-menu class="header-index-right"></user-menu>
|
||||
</div>
|
||||
|
|
|
@ -10,66 +10,41 @@
|
|||
<a-form-model-item
|
||||
v-if="!form.needAuthCode"
|
||||
class="animated fadeInUp"
|
||||
:style="{'animation-delay': '0.1s'}"
|
||||
:style="{ 'animation-delay': '0.1s' }"
|
||||
prop="username"
|
||||
>
|
||||
<a-input
|
||||
placeholder="用户名/邮箱"
|
||||
v-model="form.model.username"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="user"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input placeholder="用户名/邮箱" v-model="form.model.username">
|
||||
<a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
v-if="!form.needAuthCode"
|
||||
class="animated fadeInUp"
|
||||
:style="{'animation-delay': '0.2s'}"
|
||||
:style="{ 'animation-delay': '0.2s' }"
|
||||
prop="password"
|
||||
>
|
||||
<a-input
|
||||
v-model="form.model.password"
|
||||
type="password"
|
||||
placeholder="密码"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="lock"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.password" type="password" placeholder="密码">
|
||||
<a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
v-if="form.needAuthCode"
|
||||
class="animated fadeInUp"
|
||||
:style="{'animation-delay': '0.1s'}"
|
||||
:style="{ 'animation-delay': '0.1s' }"
|
||||
prop="authcode"
|
||||
>
|
||||
<a-input
|
||||
placeholder="两步验证码"
|
||||
v-model="form.model.authcode"
|
||||
:maxLength="6"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="safety-certificate"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input placeholder="两步验证码" v-model="form.model.authcode" :maxLength="6">
|
||||
<a-icon slot="prefix" type="safety-certificate" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
class="animated fadeInUp"
|
||||
:style="{'animation-delay': '0.3s'}"
|
||||
>
|
||||
<a-form-model-item class="animated fadeInUp" :style="{ 'animation-delay': '0.3s' }">
|
||||
<a-button
|
||||
:loading="form.logging"
|
||||
type="primary"
|
||||
:block="true"
|
||||
@click="form.needAuthCode ? handleLogin() : handleLoginClick()"
|
||||
>{{ buttonName }}</a-button>
|
||||
>{{ buttonName }}</a-button
|
||||
>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</div>
|
||||
|
@ -92,33 +67,33 @@ export default {
|
|||
model: {
|
||||
authcode: null,
|
||||
password: null,
|
||||
username: null,
|
||||
username: null
|
||||
},
|
||||
rules: {
|
||||
username: [{ required: true, message: '* 用户名/邮箱不能为空', trigger: ['change'] }],
|
||||
password: [{ required: true, message: '* 密码不能为空', trigger: ['change'] }],
|
||||
authcode: [{ validator: authcodeValidate, trigger: ['change'] }],
|
||||
authcode: [{ validator: authcodeValidate, trigger: ['change'] }]
|
||||
},
|
||||
needAuthCode: false,
|
||||
logging: false,
|
||||
},
|
||||
logging: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
buttonName() {
|
||||
return this.form.needAuthCode ? '验证' : '登录'
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['login', 'refreshUserCache', 'refreshOptionsCache']),
|
||||
handleLoginClick() {
|
||||
const _this = this
|
||||
_this.$refs.loginForm.validate((valid) => {
|
||||
_this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.logging = true
|
||||
adminApi
|
||||
.loginPreCheck(_this.form.model.username, _this.form.model.password)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
const data = response.data.data
|
||||
if (data && data.needMFACode) {
|
||||
_this.form.needAuthCode = true
|
||||
|
@ -138,11 +113,11 @@ export default {
|
|||
handleLogin() {
|
||||
const _this = this
|
||||
_this.form.logging = true
|
||||
_this.$refs.loginForm.validate((valid) => {
|
||||
_this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this
|
||||
.login(_this.form.model)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
_this.$emit('success')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -152,7 +127,7 @@ export default {
|
|||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -34,5 +34,4 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<a-layout-sider
|
||||
:class="['sider', isDesktop() ? null : 'shadow', theme, fixSiderbar ? 'ant-fixed-sidemenu' : null ]"
|
||||
:class="['sider', isDesktop() ? null : 'shadow', theme, fixSiderbar ? 'ant-fixed-sidemenu' : null]"
|
||||
width="256px"
|
||||
:collapsible="collapsible"
|
||||
v-model="collapsed"
|
||||
|
|
|
@ -1,32 +1,15 @@
|
|||
<template>
|
||||
<div
|
||||
class="setting-drawer"
|
||||
ref="settingDrawer"
|
||||
>
|
||||
<a-drawer
|
||||
width="300"
|
||||
closable
|
||||
@close="onClose"
|
||||
:visible="layoutSetting"
|
||||
>
|
||||
<div class="setting-drawer" ref="settingDrawer">
|
||||
<a-drawer width="300" closable @close="onClose" :visible="layoutSetting">
|
||||
<div class="setting-drawer-index-content">
|
||||
<div class="mb-6">
|
||||
<h3 class="setting-drawer-index-title">整体风格设置</h3>
|
||||
<div class="setting-drawer-index-blockChecbox">
|
||||
<a-tooltip>
|
||||
<template slot="title">暗色菜单风格</template>
|
||||
<div
|
||||
class="setting-drawer-index-item"
|
||||
@click="handleMenuTheme('dark')"
|
||||
>
|
||||
<img
|
||||
src="/images/dark.svg"
|
||||
alt="dark"
|
||||
>
|
||||
<div
|
||||
class="setting-drawer-index-selectIcon"
|
||||
v-if="navTheme === 'dark'"
|
||||
>
|
||||
<div class="setting-drawer-index-item" @click="handleMenuTheme('dark')">
|
||||
<img src="/images/dark.svg" alt="dark" />
|
||||
<div class="setting-drawer-index-selectIcon" v-if="navTheme === 'dark'">
|
||||
<a-icon type="check" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -34,18 +17,9 @@
|
|||
|
||||
<a-tooltip>
|
||||
<template slot="title">亮色菜单风格</template>
|
||||
<div
|
||||
class="setting-drawer-index-item"
|
||||
@click="handleMenuTheme('light')"
|
||||
>
|
||||
<img
|
||||
src="/images/dark.svg"
|
||||
alt="light"
|
||||
>
|
||||
<div
|
||||
class="setting-drawer-index-selectIcon"
|
||||
v-if="navTheme !== 'dark'"
|
||||
>
|
||||
<div class="setting-drawer-index-item" @click="handleMenuTheme('light')">
|
||||
<img src="/images/dark.svg" alt="light" />
|
||||
<div class="setting-drawer-index-selectIcon" v-if="navTheme !== 'dark'">
|
||||
<a-icon type="check" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,20 +30,10 @@
|
|||
<div class="mb-6">
|
||||
<h3 class="setting-drawer-index-title">主题色</h3>
|
||||
<div class="h-5">
|
||||
<a-tooltip
|
||||
class="setting-drawer-theme-color-colorBlock"
|
||||
v-for="(item, index) in colorList"
|
||||
:key="index"
|
||||
>
|
||||
<a-tooltip class="setting-drawer-theme-color-colorBlock" v-for="(item, index) in colorList" :key="index">
|
||||
<template slot="title">{{ item.key }}</template>
|
||||
<a-tag
|
||||
:color="item.color"
|
||||
@click="changeColor(item.color)"
|
||||
>
|
||||
<a-icon
|
||||
type="check"
|
||||
v-if="item.color === primaryColor"
|
||||
></a-icon>
|
||||
<a-tag :color="item.color" @click="changeColor(item.color)">
|
||||
<a-icon type="check" v-if="item.color === primaryColor"></a-icon>
|
||||
</a-tag>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
@ -79,34 +43,16 @@
|
|||
<h3 class="setting-drawer-index-title">导航模式</h3>
|
||||
|
||||
<div class="setting-drawer-index-blockChecbox">
|
||||
<div
|
||||
class="setting-drawer-index-item"
|
||||
@click="handleLayout('sidemenu')"
|
||||
>
|
||||
<img
|
||||
src="/images/sidemenu.svg"
|
||||
alt="sidemenu"
|
||||
>
|
||||
<div
|
||||
class="setting-drawer-index-selectIcon"
|
||||
v-if="layoutMode === 'sidemenu'"
|
||||
>
|
||||
<div class="setting-drawer-index-item" @click="handleLayout('sidemenu')">
|
||||
<img src="/images/sidemenu.svg" alt="sidemenu" />
|
||||
<div class="setting-drawer-index-selectIcon" v-if="layoutMode === 'sidemenu'">
|
||||
<a-icon type="check" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="setting-drawer-index-item"
|
||||
@click="handleLayout('topmenu')"
|
||||
>
|
||||
<img
|
||||
src="/images/topmenu.svg"
|
||||
alt="topmenu"
|
||||
>
|
||||
<div
|
||||
class="setting-drawer-index-selectIcon"
|
||||
v-if="layoutMode !== 'sidemenu'"
|
||||
>
|
||||
<div class="setting-drawer-index-item" @click="handleLayout('topmenu')">
|
||||
<img src="/images/topmenu.svg" alt="topmenu" />
|
||||
<div class="setting-drawer-index-selectIcon" v-if="layoutMode !== 'sidemenu'">
|
||||
<a-icon type="check" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -127,10 +73,7 @@
|
|||
@change="handleContentWidthChange"
|
||||
>
|
||||
<a-select-option value="Fixed">固定</a-select-option>
|
||||
<a-select-option
|
||||
value="Fluid"
|
||||
v-if="layoutMode != 'sidemenu'"
|
||||
>流式</a-select-option>
|
||||
<a-select-option value="Fluid" v-if="layoutMode != 'sidemenu'">流式</a-select-option>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
<a-list-item-meta>
|
||||
|
@ -138,12 +81,7 @@
|
|||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-switch
|
||||
slot="actions"
|
||||
size="small"
|
||||
:defaultChecked="fixedHeader"
|
||||
@change="handleFixedHeader"
|
||||
/>
|
||||
<a-switch slot="actions" size="small" :defaultChecked="fixedHeader" @change="handleFixedHeader" />
|
||||
<a-list-item-meta>
|
||||
<div slot="title">固定 Header</div>
|
||||
</a-list-item-meta>
|
||||
|
@ -157,10 +95,7 @@
|
|||
@change="handleFixedHeaderHidden"
|
||||
/>
|
||||
<a-list-item-meta>
|
||||
<a-tooltip
|
||||
slot="title"
|
||||
placement="left"
|
||||
>
|
||||
<a-tooltip slot="title" placement="left">
|
||||
<template slot="title">固定 Header 时可配置</template>
|
||||
<div :style="{ opacity: !fixedHeader ? '0.5' : '1' }">下滑时隐藏 Header</div>
|
||||
</a-tooltip>
|
||||
|
@ -170,15 +105,12 @@
|
|||
<a-switch
|
||||
slot="actions"
|
||||
size="small"
|
||||
:disabled="(layoutMode === 'topmenu')"
|
||||
:disabled="layoutMode === 'topmenu'"
|
||||
:defaultChecked="fixSiderbar"
|
||||
@change="handleFixSiderbar"
|
||||
/>
|
||||
<a-list-item-meta>
|
||||
<div
|
||||
slot="title"
|
||||
:style="{ opacity: (layoutMode==='topmenu') ? '0.5' : '1' }"
|
||||
>固定侧边菜单</div>
|
||||
<div slot="title" :style="{ opacity: layoutMode === 'topmenu' ? '0.5' : '1' }">固定侧边菜单</div>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
@ -190,16 +122,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import SettingItem from '@/components/SettingDrawer/SettingItem'
|
||||
import config from '@/config/defaultSettings'
|
||||
import { updateTheme, colorList } from './setting'
|
||||
import { mixin, mixinDevice } from '@/mixins/mixin'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SettingItem
|
||||
},
|
||||
mixins: [mixin, mixinDevice],
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<div
|
||||
class="head-info"
|
||||
:class="center && 'center'"
|
||||
>
|
||||
<div class="head-info" :class="center && 'center'">
|
||||
<span>{{ title }}</span>
|
||||
<p>{{ content }}</p>
|
||||
<em v-if="bordered" />
|
||||
|
|
|
@ -10,22 +10,10 @@
|
|||
>
|
||||
<template slot="content">
|
||||
<div class="custom-tab-wrapper">
|
||||
<a-tabs
|
||||
v-model="activeKey"
|
||||
@change="handleTabsChanged"
|
||||
>
|
||||
<a-tab-pane
|
||||
tab="文章"
|
||||
key="post"
|
||||
>
|
||||
<a-list
|
||||
:loading="postCommentsLoading"
|
||||
:dataSource="converttedPostComments"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item"
|
||||
>
|
||||
<a-tabs v-model="activeKey" @change="handleTabsChanged">
|
||||
<a-tab-pane tab="文章" key="post">
|
||||
<a-list :loading="postCommentsLoading" :dataSource="converttedPostComments">
|
||||
<a-list-item slot="renderItem" slot-scope="item">
|
||||
<a-list-item-meta>
|
||||
<a-avatar
|
||||
class="bg-white"
|
||||
|
@ -34,10 +22,8 @@
|
|||
size="large"
|
||||
/>
|
||||
<template slot="title">
|
||||
<a
|
||||
:href="item.authorUrl"
|
||||
target="_blank"
|
||||
>{{ item.author }}</a>:<span v-html="item.content"></span>
|
||||
<a :href="item.authorUrl" target="_blank">{{ item.author }}</a
|
||||
>:<span v-html="item.content"></span>
|
||||
</template>
|
||||
<template slot="description">
|
||||
{{ item.createTime | timeAgo }}
|
||||
|
@ -46,18 +32,9 @@
|
|||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
tab="页面"
|
||||
key="sheet"
|
||||
>
|
||||
<a-list
|
||||
:loading="sheetCommentsLoading"
|
||||
:dataSource="converttedSheetComments"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item"
|
||||
>
|
||||
<a-tab-pane tab="页面" key="sheet">
|
||||
<a-list :loading="sheetCommentsLoading" :dataSource="converttedSheetComments">
|
||||
<a-list-item slot="renderItem" slot-scope="item">
|
||||
<a-list-item-meta>
|
||||
<a-avatar
|
||||
class="bg-white"
|
||||
|
@ -66,10 +43,8 @@
|
|||
size="large"
|
||||
/>
|
||||
<template slot="title">
|
||||
<a
|
||||
:href="item.authorUrl"
|
||||
target="_blank"
|
||||
>{{ item.author }}</a>:<span v-html="item.content"></span>
|
||||
<a :href="item.authorUrl" target="_blank">{{ item.author }}</a
|
||||
>:<span v-html="item.content"></span>
|
||||
</template>
|
||||
<template slot="description">
|
||||
{{ item.createTime | timeAgo }}
|
||||
|
@ -82,10 +57,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<span class="header-comment">
|
||||
<a-badge
|
||||
dot
|
||||
v-if="postComments.length > 0 || sheetComments.length > 0"
|
||||
>
|
||||
<a-badge dot v-if="postComments.length > 0 || sheetComments.length > 0">
|
||||
<a-icon type="bell" />
|
||||
</a-badge>
|
||||
<a-badge v-else>
|
||||
|
@ -114,13 +86,13 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
converttedPostComments() {
|
||||
return this.postComments.map((comment) => {
|
||||
return this.postComments.map(comment => {
|
||||
comment.content = marked(decodeHTML(comment.content))
|
||||
return comment
|
||||
})
|
||||
},
|
||||
converttedSheetComments() {
|
||||
return this.sheetComments.map((comment) => {
|
||||
return this.sheetComments.map(comment => {
|
||||
comment.content = marked(decodeHTML(comment.content))
|
||||
return comment
|
||||
})
|
||||
|
@ -148,7 +120,7 @@ export default {
|
|||
}
|
||||
commentApi
|
||||
.latestComment('posts', 5, 'AUDITING')
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.postComments = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -163,7 +135,7 @@ export default {
|
|||
}
|
||||
commentApi
|
||||
.latestComment('sheets', 5, 'AUDITING')
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.sheetComments = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
<template>
|
||||
<div class="logo">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="onLogoClick()"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="onLogoClick()">
|
||||
<h1 class="logo-title">Halo</h1>
|
||||
<h1
|
||||
class="logo-sub-title"
|
||||
style="padding-left: 10px;"
|
||||
>Dashboard</h1>
|
||||
<h1 class="logo-sub-title" style="padding-left: 10px;">Dashboard</h1>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -34,7 +28,7 @@ export default {
|
|||
onLogoClick() {
|
||||
this.clickCount++
|
||||
if (this.clickCount === 10) {
|
||||
optionApi.save(this.optionsToCreate).then((response) => {
|
||||
optionApi.save(this.optionsToCreate).then(() => {
|
||||
this.refreshOptionsCache()
|
||||
this.$message.success(`开发者选项已启用!`)
|
||||
this.clickCount = 0
|
||||
|
|
|
@ -1,26 +1,14 @@
|
|||
<template>
|
||||
<div class="user-wrapper">
|
||||
<a
|
||||
:href="options.blog_url"
|
||||
target="_blank"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="bottom"
|
||||
title="点击跳转到首页"
|
||||
>
|
||||
<a :href="options.blog_url" target="_blank">
|
||||
<a-tooltip placement="bottom" title="点击跳转到首页">
|
||||
<span class="action">
|
||||
<a-icon type="link" />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
@click="handleShowLayoutSetting"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="bottom"
|
||||
title="后台布局设置"
|
||||
>
|
||||
<a href="javascript:void(0)" @click="handleShowLayoutSetting">
|
||||
<a-tooltip placement="bottom" title="后台布局设置">
|
||||
<span class="action">
|
||||
<a-icon type="setting" />
|
||||
</span>
|
||||
|
@ -28,20 +16,10 @@
|
|||
</a>
|
||||
<header-comment class="action" />
|
||||
<a-dropdown>
|
||||
<span
|
||||
class="action ant-dropdown-link user-dropdown-menu"
|
||||
v-if="user"
|
||||
>
|
||||
<a-avatar
|
||||
class="avatar"
|
||||
size="small"
|
||||
:src="user.avatar || '//cn.gravatar.com/avatar/?s=256&d=mm'"
|
||||
/>
|
||||
<span class="action ant-dropdown-link user-dropdown-menu" v-if="user">
|
||||
<a-avatar class="avatar" size="small" :src="user.avatar || '//cn.gravatar.com/avatar/?s=256&d=mm'" />
|
||||
</span>
|
||||
<a-menu
|
||||
slot="overlay"
|
||||
class="user-dropdown-menu-wrapper"
|
||||
>
|
||||
<a-menu slot="overlay" class="user-dropdown-menu-wrapper">
|
||||
<a-menu-item key="0">
|
||||
<router-link :to="{ name: 'Profile' }">
|
||||
<a-icon type="user" />
|
||||
|
@ -50,10 +28,7 @@
|
|||
</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="1">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleLogout"
|
||||
>
|
||||
<a href="javascript:;" @click="handleLogout">
|
||||
<a-icon type="logout" />
|
||||
<span>退出登录</span>
|
||||
</a>
|
||||
|
@ -89,7 +64,7 @@ export default {
|
|||
.then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
that.$message.error({
|
||||
title: '错误',
|
||||
description: err.message
|
||||
|
|
|
@ -42,45 +42,45 @@ const FilePond = vueFilePond(FilePondPluginImagePreview, FilePondPluginFileValid
|
|||
export default {
|
||||
name: 'FilePondUpload',
|
||||
components: {
|
||||
FilePond,
|
||||
FilePond
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'file',
|
||||
default: 'file'
|
||||
},
|
||||
filed: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
default: ''
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
default: true
|
||||
},
|
||||
accepts: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => {
|
||||
return []
|
||||
},
|
||||
}
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '点击选择文件或将文件拖拽到此处',
|
||||
default: '点击选择文件或将文件拖拽到此处'
|
||||
},
|
||||
uploadHandler: {
|
||||
type: Function,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
loadOptions: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['options']),
|
||||
|
@ -101,7 +101,7 @@ export default {
|
|||
return this.options.attachment_upload_max_files
|
||||
}
|
||||
return 1
|
||||
},
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
|
@ -115,7 +115,7 @@ export default {
|
|||
|
||||
this.uploadHandler(
|
||||
formData,
|
||||
(progressEvent) => {
|
||||
progressEvent => {
|
||||
if (progressEvent.total > 0) {
|
||||
progress(progressEvent.lengthComputable, progressEvent.loaded, progressEvent.total)
|
||||
}
|
||||
|
@ -124,12 +124,12 @@ export default {
|
|||
this.filed,
|
||||
file
|
||||
)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
load(response)
|
||||
this.$log.debug('Uploaded successfully', response)
|
||||
this.$emit('success', response, file)
|
||||
})
|
||||
.catch((failure) => {
|
||||
.catch(failure => {
|
||||
this.$log.debug('Failed to upload file', failure)
|
||||
this.$emit('failure', failure, file)
|
||||
error()
|
||||
|
@ -139,11 +139,11 @@ export default {
|
|||
abort()
|
||||
this.$log.debug('Upload operation aborted by the user')
|
||||
source.cancel('Upload operation canceled by the user.')
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
fileList: [],
|
||||
fileList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -152,7 +152,7 @@ export default {
|
|||
},
|
||||
handleClearFileList() {
|
||||
this.$refs.pond.removeFiles()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -96,7 +96,7 @@ export default {
|
|||
computed: {
|
||||
...mapState({
|
||||
// 动态主路由
|
||||
mainMenu: (state) => state.permission.addRouters
|
||||
mainMenu: state => state.permission.addRouters
|
||||
}),
|
||||
contentPaddingLeft() {
|
||||
if (!this.fixSidebar || this.isMobile()) {
|
||||
|
@ -114,7 +114,7 @@ export default {
|
|||
}
|
||||
},
|
||||
created() {
|
||||
this.menus = asyncRouterMap.find((item) => item.path === '/').children
|
||||
this.menus = asyncRouterMap.find(item => item.path === '/').children
|
||||
// this.menus = this.mainMenu.find((item) => item.path === '/').children
|
||||
this.collapsed = !this.sidebarOpened
|
||||
},
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'BlankLayout'
|
||||
}
|
||||
|
|
|
@ -1,50 +1,20 @@
|
|||
<template>
|
||||
<div :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
|
||||
<a-affix v-if="affix">
|
||||
<div
|
||||
class="page-header"
|
||||
v-if="!$route.meta.hiddenHeaderContent"
|
||||
>
|
||||
<div class="page-header" v-if="!$route.meta.hiddenHeaderContent">
|
||||
<div class="page-header-index-wide">
|
||||
<a-page-header
|
||||
:title="title"
|
||||
:sub-title="subTitle"
|
||||
:breadcrumb="{ props: { routes:breadList } }"
|
||||
>
|
||||
<slot
|
||||
name="extra"
|
||||
slot="extra"
|
||||
>
|
||||
</slot>
|
||||
<slot
|
||||
name="footer"
|
||||
slot="footer"
|
||||
>
|
||||
</slot>
|
||||
<a-page-header :title="title" :sub-title="subTitle" :breadcrumb="{ props: { routes: breadList } }">
|
||||
<slot name="extra" slot="extra"> </slot>
|
||||
<slot name="footer" slot="footer"> </slot>
|
||||
</a-page-header>
|
||||
</div>
|
||||
</div>
|
||||
</a-affix>
|
||||
<div
|
||||
class="page-header"
|
||||
v-if="!$route.meta.hiddenHeaderContent && !affix"
|
||||
>
|
||||
<div class="page-header" v-if="!$route.meta.hiddenHeaderContent && !affix">
|
||||
<div class="page-header-index-wide">
|
||||
<a-page-header
|
||||
:title="title"
|
||||
:sub-title="subTitle"
|
||||
:breadcrumb="{ props: { routes:breadList } }"
|
||||
>
|
||||
<slot
|
||||
name="extra"
|
||||
slot="extra"
|
||||
>
|
||||
</slot>
|
||||
<slot
|
||||
name="footer"
|
||||
slot="footer"
|
||||
>
|
||||
</slot>
|
||||
<a-page-header :title="title" :sub-title="subTitle" :breadcrumb="{ props: { routes: breadList } }">
|
||||
<slot name="extra" slot="extra"> </slot>
|
||||
<slot name="footer" slot="footer"> </slot>
|
||||
</a-page-header>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -64,20 +34,20 @@ export default {
|
|||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
affix: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
breadList: [],
|
||||
breadList: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -86,17 +56,17 @@ export default {
|
|||
watch: {
|
||||
$route() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
this.breadList = []
|
||||
this.$route.matched.forEach((item) => {
|
||||
this.$route.matched.forEach(item => {
|
||||
item.breadcrumbName = item.meta.title
|
||||
this.breadList.push(item)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import '@babel/polyfill'
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
|
|
@ -3,14 +3,14 @@ import router from '@/router'
|
|||
import store from '@/store'
|
||||
import NProgress from 'nprogress'
|
||||
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
|
||||
import adminApi from '@api/admin'
|
||||
import adminApi from '@/api/admin'
|
||||
|
||||
NProgress.configure({ showSpinner: false, speed: 500 })
|
||||
|
||||
const whiteList = ['Login', 'Install', 'NotFound', 'ResetPassword'] // no redirect whitelist
|
||||
|
||||
let progressTimer = null
|
||||
router.beforeEach(async(to, from, next) => {
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
onProgressTimerDone()
|
||||
progressTimer = setTimeout(() => {
|
||||
NProgress.start()
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import {
|
||||
constantRouterMap,
|
||||
asyncRouterMap
|
||||
} from '@/config/router.config'
|
||||
import { constantRouterMap, asyncRouterMap } from '@/config/router.config'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
|
|
|
@ -16,14 +16,8 @@ export default new Vuex.Store({
|
|||
permission,
|
||||
option
|
||||
},
|
||||
state: {
|
||||
|
||||
},
|
||||
mutations: {
|
||||
|
||||
},
|
||||
actions: {
|
||||
|
||||
},
|
||||
state: {},
|
||||
mutations: {},
|
||||
actions: {},
|
||||
getters
|
||||
})
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
import Vue from 'vue'
|
||||
import {
|
||||
ACCESS_TOKEN,
|
||||
USER
|
||||
} from '@/store/mutation-types'
|
||||
import { ACCESS_TOKEN, USER } from '@/store/mutation-types'
|
||||
import adminApi from '@/api/admin'
|
||||
import userApi from '@/api/user'
|
||||
|
||||
|
@ -26,9 +23,7 @@ const user = {
|
|||
}
|
||||
},
|
||||
actions: {
|
||||
installCleanToken({
|
||||
commit
|
||||
}, installData) {
|
||||
installCleanToken({ commit }, installData) {
|
||||
return new Promise((resolve, reject) => {
|
||||
adminApi
|
||||
.install(installData)
|
||||
|
@ -41,9 +36,7 @@ const user = {
|
|||
})
|
||||
})
|
||||
},
|
||||
refreshUserCache({
|
||||
commit
|
||||
}) {
|
||||
refreshUserCache({ commit }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
userApi
|
||||
.getProfile()
|
||||
|
@ -56,13 +49,7 @@ const user = {
|
|||
})
|
||||
})
|
||||
},
|
||||
login({
|
||||
commit
|
||||
}, {
|
||||
username,
|
||||
password,
|
||||
authcode
|
||||
}) {
|
||||
login({ commit }, { username, password, authcode }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
adminApi
|
||||
.login(username, password, authcode)
|
||||
|
@ -78,13 +65,11 @@ const user = {
|
|||
})
|
||||
})
|
||||
},
|
||||
logout({
|
||||
commit
|
||||
}) {
|
||||
logout({ commit }) {
|
||||
return new Promise(resolve => {
|
||||
adminApi
|
||||
.logout()
|
||||
.then(response => {
|
||||
.then(() => {
|
||||
commit('CLEAR_TOKEN')
|
||||
resolve()
|
||||
})
|
||||
|
@ -93,9 +78,7 @@ const user = {
|
|||
})
|
||||
})
|
||||
},
|
||||
refreshToken({
|
||||
commit
|
||||
}, refreshToken) {
|
||||
refreshToken({ commit }, refreshToken) {
|
||||
return new Promise((resolve, reject) => {
|
||||
adminApi
|
||||
.refreshToken(refreshToken)
|
||||
|
|
|
@ -1,36 +1,17 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row
|
||||
:gutter="12"
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-col
|
||||
:span="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-row :gutter="12" type="flex" align="middle">
|
||||
<a-col :span="24" class="pb-3">
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input
|
||||
v-model="queryParam.keyword"
|
||||
@keyup.enter="handleQuery()"
|
||||
/>
|
||||
<a-input v-model="queryParam.keyword" @keyup.enter="handleQuery()" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="存储位置:">
|
||||
<a-select
|
||||
v-model="queryParam.attachmentType"
|
||||
|
@ -38,20 +19,13 @@
|
|||
:loading="typesLoading"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in types"
|
||||
:key="item"
|
||||
:value="item"
|
||||
>{{
|
||||
<a-select-option v-for="item in types" :key="item" :value="item">{{
|
||||
attachmentType[item].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="文件类型:">
|
||||
<a-select
|
||||
v-model="queryParam.mediaType"
|
||||
|
@ -59,26 +33,16 @@
|
|||
:loading="mediaTypesLoading"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(item, index) in mediaTypes"
|
||||
:key="index"
|
||||
:value="item"
|
||||
>{{
|
||||
<a-select-option v-for="(item, index) in mediaTypes" :key="index" :value="item">{{
|
||||
item
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<span class="table-page-search-submitButtons">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleQuery()"
|
||||
>查询</a-button>
|
||||
<a-button type="primary" @click="handleQuery()">查询</a-button>
|
||||
<a-button @click="handleResetParam()">重置</a-button>
|
||||
</a-space>
|
||||
</span>
|
||||
|
@ -86,17 +50,9 @@
|
|||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="table-operator mb-0">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="cloud-upload"
|
||||
@click="() => (uploadVisible = true)"
|
||||
>上传</a-button>
|
||||
<a-button
|
||||
icon="select"
|
||||
v-show="!supportMultipleSelection"
|
||||
@click="handleMultipleSelection"
|
||||
>
|
||||
<div class="mb-0 table-operator">
|
||||
<a-button type="primary" icon="cloud-upload" @click="() => (uploadVisible = true)">上传</a-button>
|
||||
<a-button icon="select" v-show="!supportMultipleSelection" @click="handleMultipleSelection">
|
||||
批量操作
|
||||
</a-button>
|
||||
<a-button
|
||||
|
@ -107,11 +63,7 @@
|
|||
>
|
||||
删除
|
||||
</a-button>
|
||||
<a-button
|
||||
icon="close"
|
||||
v-show="supportMultipleSelection"
|
||||
@click="handleCancelMultipleSelection"
|
||||
>
|
||||
<a-button icon="close" v-show="supportMultipleSelection" @click="handleCancelMultipleSelection">
|
||||
取消
|
||||
</a-button>
|
||||
</div>
|
||||
|
@ -123,11 +75,7 @@
|
|||
:dataSource="formattedDatas"
|
||||
:loading="listLoading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-card
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
hoverable
|
||||
|
@ -136,18 +84,10 @@
|
|||
>
|
||||
<div class="attach-thumb">
|
||||
<span v-show="!handleJudgeMediaType(item)">当前格式不支持预览</span>
|
||||
<img
|
||||
:src="item.thumbPath"
|
||||
v-show="handleJudgeMediaType(item)"
|
||||
loading="lazy"
|
||||
/>
|
||||
<img :src="item.thumbPath" v-show="handleJudgeMediaType(item)" loading="lazy" />
|
||||
</div>
|
||||
<a-card-meta class="p-3">
|
||||
<ellipsis
|
||||
:length="isMobile() ? 12 : 16"
|
||||
tooltip
|
||||
slot="description"
|
||||
>{{ item.name }}</ellipsis>
|
||||
<ellipsis :length="isMobile() ? 12 : 16" tooltip slot="description">{{ item.name }}</ellipsis>
|
||||
</a-card-meta>
|
||||
<a-checkbox
|
||||
class="select-attachment-checkbox"
|
||||
|
@ -174,17 +114,8 @@
|
|||
showLessItems
|
||||
/>
|
||||
</div>
|
||||
<a-modal
|
||||
title="上传附件"
|
||||
v-model="uploadVisible"
|
||||
:footer="null"
|
||||
:afterClose="onUploadClose"
|
||||
destroyOnClose
|
||||
>
|
||||
<FilePondUpload
|
||||
ref="upload"
|
||||
:uploadHandler="uploadHandler"
|
||||
></FilePondUpload>
|
||||
<a-modal title="上传附件" v-model="uploadVisible" :footer="null" :afterClose="onUploadClose" destroyOnClose>
|
||||
<FilePondUpload ref="upload" :uploadHandler="uploadHandler"></FilePondUpload>
|
||||
</a-modal>
|
||||
<AttachmentDetailDrawer
|
||||
v-model="drawerVisible"
|
||||
|
@ -448,7 +379,7 @@ export default {
|
|||
onOk() {
|
||||
attachmentApi
|
||||
.deleteInBatch(that.batchSelectedAttachments)
|
||||
.then(res => {
|
||||
.then(() => {
|
||||
that.handleCancelMultipleSelection()
|
||||
that.$message.success('删除成功')
|
||||
})
|
||||
|
|
|
@ -1,36 +1,20 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="附件详情"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<div class="attach-detail-img">
|
||||
<div v-show="nonsupportPreviewVisible">此文件不支持预览</div>
|
||||
<a
|
||||
:href="attachment.path"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
:src="attachment.path"
|
||||
v-show="photoPreviewVisible"
|
||||
class="w-full"
|
||||
loading="lazy"
|
||||
>
|
||||
<a :href="attachment.path" target="_blank">
|
||||
<img :src="attachment.path" v-show="photoPreviewVisible" class="w-full" loading="lazy" />
|
||||
</a>
|
||||
<d-player
|
||||
ref="player"
|
||||
:options="videoOptions"
|
||||
v-show="videoPreviewVisible"
|
||||
class="video-player-box w-full"
|
||||
>
|
||||
<d-player ref="player" :options="videoOptions" v-show="videoPreviewVisible" class="w-full video-player-box">
|
||||
</d-player>
|
||||
</div>
|
||||
</a-col>
|
||||
|
@ -39,27 +23,14 @@
|
|||
<a-list itemLayout="horizontal">
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<template
|
||||
slot="description"
|
||||
v-if="editable"
|
||||
>
|
||||
<a-input
|
||||
ref="nameInput"
|
||||
v-model="attachment.name"
|
||||
@blur="doUpdateAttachment"
|
||||
/>
|
||||
<template slot="description" v-if="editable">
|
||||
<a-input ref="nameInput" v-model="attachment.name" @blur="doUpdateAttachment" />
|
||||
</template>
|
||||
<template
|
||||
slot="description"
|
||||
v-else
|
||||
>{{ attachment.name }}</template>
|
||||
<template slot="description" v-else>{{ attachment.name }}</template>
|
||||
<span slot="title">
|
||||
附件名:
|
||||
<a href="javascript:void(0);">
|
||||
<a-icon
|
||||
type="edit"
|
||||
@click="handleEditName"
|
||||
/>
|
||||
<a-icon type="edit" @click="handleEditName" />
|
||||
</a>
|
||||
</span>
|
||||
</a-list-item-meta>
|
||||
|
@ -83,7 +54,7 @@
|
|||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item v-if="photoPreviewVisible">
|
||||
<a-list-item-meta :description="attachment.height+'x'+attachment.width">
|
||||
<a-list-item-meta :description="attachment.height + 'x' + attachment.width">
|
||||
<span slot="title">图片尺寸:</span>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
|
@ -99,10 +70,7 @@
|
|||
<a-list-item-meta :description="attachment.path">
|
||||
<span slot="title">
|
||||
普通链接:
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleCopyNormalLink"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="handleCopyNormalLink">
|
||||
<a-icon type="copy" />
|
||||
</a>
|
||||
</span>
|
||||
|
@ -113,10 +81,7 @@
|
|||
<span slot="description">![{{ attachment.name }}]({{ attachment.path }})</span>
|
||||
<span slot="title">
|
||||
Markdown 格式:
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleCopyMarkdownLink"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="handleCopyMarkdownLink">
|
||||
<a-icon type="copy" />
|
||||
</a>
|
||||
</span>
|
||||
|
@ -137,12 +102,7 @@
|
|||
>
|
||||
<a-button type="dashed">添加到图库</a-button>
|
||||
</a-popconfirm>
|
||||
<a-popconfirm
|
||||
title="你确定要删除该附件?"
|
||||
@confirm="handleDeleteAttachment"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
<a-popconfirm title="你确定要删除该附件?" @confirm="handleDeleteAttachment" okText="确定" cancelText="取消">
|
||||
<ReactiveButton
|
||||
type="danger"
|
||||
@callback="handleDeletedCallback"
|
||||
|
@ -171,7 +131,7 @@ export default {
|
|||
name: 'AttachmentDetailDrawer',
|
||||
mixins: [mixin, mixinDevice],
|
||||
components: {
|
||||
'd-player': VueDPlayer,
|
||||
'd-player': VueDPlayer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -187,40 +147,40 @@ export default {
|
|||
lang: 'zh-cn',
|
||||
video: {
|
||||
url: '',
|
||||
type: 'auto',
|
||||
},
|
||||
},
|
||||
type: 'auto'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'visible',
|
||||
event: 'close',
|
||||
event: 'close'
|
||||
},
|
||||
props: {
|
||||
attachment: {
|
||||
type: Object,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
addToPhoto: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.player = this.$refs.player
|
||||
},
|
||||
watch: {
|
||||
attachment: function(newValue, oldValue) {
|
||||
attachment(newValue) {
|
||||
if (newValue) {
|
||||
this.handleJudgeMediaType(newValue)
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleDeleteAttachment() {
|
||||
|
@ -253,11 +213,11 @@ export default {
|
|||
if (!this.attachment.name) {
|
||||
this.$notification['error']({
|
||||
message: '提示',
|
||||
description: '附件名称不能为空!',
|
||||
description: '附件名称不能为空!'
|
||||
})
|
||||
return
|
||||
}
|
||||
attachmentApi.update(this.attachment.id, this.attachment).then((response) => {
|
||||
attachmentApi.update(this.attachment.id, this.attachment).then(response => {
|
||||
this.$log.debug('Updated attachment', response.data.data)
|
||||
})
|
||||
this.editable = false
|
||||
|
@ -265,11 +225,11 @@ export default {
|
|||
handleCopyNormalLink() {
|
||||
const text = `${encodeURI(this.attachment.path)}`
|
||||
this.$copyText(text)
|
||||
.then((message) => {
|
||||
.then(message => {
|
||||
this.$log.debug('copy', message)
|
||||
this.$message.success('复制成功!')
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
this.$log.debug('copy.err', err)
|
||||
this.$message.error('复制失败!')
|
||||
})
|
||||
|
@ -277,11 +237,11 @@ export default {
|
|||
handleCopyMarkdownLink() {
|
||||
const text = `![${this.attachment.name}](${encodeURI(this.attachment.path)})`
|
||||
this.$copyText(text)
|
||||
.then((message) => {
|
||||
.then(message => {
|
||||
this.$log.debug('copy', message)
|
||||
this.$message.success('复制成功!')
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
this.$log.debug('copy.err', err)
|
||||
this.$message.error('复制失败!')
|
||||
})
|
||||
|
@ -291,7 +251,7 @@ export default {
|
|||
this.photo['thumbnail'] = encodeURI(this.attachment.thumbPath)
|
||||
this.photo['url'] = encodeURI(this.attachment.path)
|
||||
this.photo['takeTime'] = new Date().getTime()
|
||||
photoApi.create(this.photo).then((response) => {
|
||||
photoApi.create(this.photo).then(() => {
|
||||
this.$message.success('添加成功!')
|
||||
this.photo = {}
|
||||
})
|
||||
|
@ -328,7 +288,7 @@ export default {
|
|||
this.$set(this, 'photoPreviewVisible', photo)
|
||||
this.$set(this, 'videoPreviewVisible', video)
|
||||
this.$set(this, 'nonsupportPreviewVisible', nonsupport)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,32 +2,21 @@
|
|||
<div>
|
||||
<a-drawer
|
||||
title="附件库"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-input-search
|
||||
placeholder="搜索附件"
|
||||
v-model="queryParam.keyword"
|
||||
@search="handleQuery()"
|
||||
enterButton
|
||||
/>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-input-search placeholder="搜索附件" v-model="queryParam.keyword" @search="handleQuery()" enterButton />
|
||||
</a-row>
|
||||
<a-divider />
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-spin :spinning="loading">
|
||||
<a-empty v-if="formattedDatas.length==0" />
|
||||
<a-empty v-if="formattedDatas.length == 0" />
|
||||
<div
|
||||
v-else
|
||||
class="attach-item"
|
||||
|
@ -37,11 +26,7 @@
|
|||
@contextmenu.prevent="handleContextMenu($event, item)"
|
||||
>
|
||||
<span v-show="!handleJudgeMediaType(item)">当前格式不支持预览</span>
|
||||
<img
|
||||
:src="item.thumbPath"
|
||||
v-show="handleJudgeMediaType(item)"
|
||||
loading="lazy"
|
||||
>
|
||||
<img :src="item.thumbPath" v-show="handleJudgeMediaType(item)" loading="lazy" />
|
||||
</div>
|
||||
</a-spin>
|
||||
</a-col>
|
||||
|
@ -65,24 +50,12 @@
|
|||
/>
|
||||
<a-divider class="divider-transparent" />
|
||||
<div class="bottom-control">
|
||||
<a-button
|
||||
@click="uploadVisible = true"
|
||||
type="primary"
|
||||
>上传附件</a-button>
|
||||
<a-button @click="uploadVisible = true" type="primary">上传附件</a-button>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
||||
<a-modal
|
||||
title="上传附件"
|
||||
v-model="uploadVisible"
|
||||
:footer="null"
|
||||
:afterClose="onUploadClose"
|
||||
destroyOnClose
|
||||
>
|
||||
<FilePondUpload
|
||||
ref="upload"
|
||||
:uploadHandler="uploadHandler"
|
||||
></FilePondUpload>
|
||||
<a-modal title="上传附件" v-model="uploadVisible" :footer="null" :afterClose="onUploadClose" destroyOnClose>
|
||||
<FilePondUpload ref="upload" :uploadHandler="uploadHandler"></FilePondUpload>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -2,16 +2,10 @@
|
|||
<page-view>
|
||||
<div class="card-container">
|
||||
<a-tabs type="card">
|
||||
<a-tab-pane
|
||||
key="1"
|
||||
tab="文章"
|
||||
>
|
||||
<a-tab-pane key="1" tab="文章">
|
||||
<comment-tab type="posts"></comment-tab>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="2"
|
||||
tab="页面"
|
||||
>
|
||||
<a-tab-pane key="2" tab="页面">
|
||||
<comment-tab type="sheets"></comment-tab>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="评论详情"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-list itemLayout="horizontal">
|
||||
<a-list-item>
|
||||
|
@ -30,66 +27,36 @@
|
|||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<a
|
||||
slot="description"
|
||||
target="_blank"
|
||||
:href="comment.authorUrl"
|
||||
>{{ comment.authorUrl }}</a>
|
||||
<a slot="description" target="_blank" :href="comment.authorUrl">{{ comment.authorUrl }}</a>
|
||||
<span slot="title">评论者网址:</span>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<span slot="description">
|
||||
<a-badge
|
||||
:status="comment.statusProperty.status"
|
||||
:text="comment.statusProperty.text"
|
||||
/>
|
||||
<a-badge :status="comment.statusProperty.status" :text="comment.statusProperty.text" />
|
||||
</span>
|
||||
<span slot="title">评论状态:</span>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<a
|
||||
slot="description"
|
||||
target="_blank"
|
||||
:href="comment.post.fullPath"
|
||||
v-if="this.type=='posts'"
|
||||
>{{ comment.post.title }}</a>
|
||||
<a
|
||||
slot="description"
|
||||
target="_blank"
|
||||
:href="comment.sheet.fullPath"
|
||||
v-else-if="this.type=='sheets'"
|
||||
>{{ comment.sheet.title }}</a>
|
||||
<span
|
||||
slot="title"
|
||||
v-if="this.type=='posts'"
|
||||
>评论文章:</span>
|
||||
<span
|
||||
slot="title"
|
||||
v-else-if="this.type=='sheets'"
|
||||
>评论页面:</span>
|
||||
<a slot="description" target="_blank" :href="comment.post.fullPath" v-if="this.type == 'posts'">{{
|
||||
comment.post.title
|
||||
}}</a>
|
||||
<a slot="description" target="_blank" :href="comment.sheet.fullPath" v-else-if="this.type == 'sheets'">{{
|
||||
comment.sheet.title
|
||||
}}</a>
|
||||
<span slot="title" v-if="this.type == 'posts'">评论文章:</span>
|
||||
<span slot="title" v-else-if="this.type == 'sheets'">评论页面:</span>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<template
|
||||
slot="description"
|
||||
v-if="editable"
|
||||
>
|
||||
<a-input
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
v-model="comment.content"
|
||||
/>
|
||||
<template slot="description" v-if="editable">
|
||||
<a-input type="textarea" :autoSize="{ minRows: 5 }" v-model="comment.content" />
|
||||
</template>
|
||||
<span
|
||||
slot="description"
|
||||
v-html="comment.content"
|
||||
v-else
|
||||
></span>
|
||||
<span slot="description" v-html="comment.content" v-else></span>
|
||||
<span slot="title">评论内容:</span>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
|
@ -99,21 +66,9 @@
|
|||
<a-divider class="divider-transparent" />
|
||||
<div class="bottom-control">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="handleEditComment"
|
||||
v-if="!editable"
|
||||
>编辑</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleUpdateComment"
|
||||
v-if="editable"
|
||||
>保存</a-button>
|
||||
<a-popconfirm
|
||||
title="你确定要将此评论者加入黑名单?"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
<a-button type="dashed" @click="handleEditComment" v-if="!editable">编辑</a-button>
|
||||
<a-button type="primary" @click="handleUpdateComment" v-if="editable">保存</a-button>
|
||||
<a-popconfirm title="你确定要将此评论者加入黑名单?" okText="确定" cancelText="取消">
|
||||
<a-button type="danger">加入黑名单</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
|
|
|
@ -1,53 +1,28 @@
|
|||
<template>
|
||||
<div class="comment-tab-wrapper">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: 0 }">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input
|
||||
v-model="queryParam.keyword"
|
||||
@keyup.enter="handleQuery()"
|
||||
/>
|
||||
<a-input v-model="queryParam.keyword" @keyup.enter="handleQuery()" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="评论状态:">
|
||||
<a-select
|
||||
v-model="queryParam.status"
|
||||
placeholder="请选择评论状态"
|
||||
@change="handleQuery()"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option
|
||||
v-for="status in Object.keys(commentStatus)"
|
||||
:key="status"
|
||||
:value="status"
|
||||
>{{ commentStatus[status].text }}</a-select-option>
|
||||
<a-select v-model="queryParam.status" placeholder="请选择评论状态" @change="handleQuery()" allowClear>
|
||||
<a-select-option v-for="status in Object.keys(commentStatus)" :key="status" :value="status">{{
|
||||
commentStatus[status].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col
|
||||
:md="12"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="12" :sm="24">
|
||||
<span class="table-page-search-submitButtons">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleQuery()"
|
||||
>查询</a-button>
|
||||
<a-button type="primary" @click="handleQuery()">查询</a-button>
|
||||
<a-button @click="handleResetParam()">重置</a-button>
|
||||
</a-space>
|
||||
</span>
|
||||
|
@ -57,38 +32,20 @@
|
|||
</div>
|
||||
|
||||
<div class="table-operator">
|
||||
<a-dropdown v-show="queryParam.status!=null && queryParam.status!='' && !isMobile()">
|
||||
<a-dropdown v-show="queryParam.status != null && queryParam.status != '' && !isMobile()">
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item
|
||||
key="1"
|
||||
v-if="queryParam.status ==='AUDITING'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusMore(commentStatus.PUBLISHED.value)"
|
||||
>
|
||||
<a-menu-item key="1" v-if="queryParam.status === 'AUDITING'">
|
||||
<a href="javascript:void(0);" @click="handleEditStatusMore(commentStatus.PUBLISHED.value)">
|
||||
通过
|
||||
</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="2"
|
||||
v-if="queryParam.status === 'PUBLISHED' || queryParam.status ==='AUDITING'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusMore(commentStatus.RECYCLE.value)"
|
||||
>
|
||||
<a-menu-item key="2" v-if="queryParam.status === 'PUBLISHED' || queryParam.status === 'AUDITING'">
|
||||
<a href="javascript:void(0);" @click="handleEditStatusMore(commentStatus.RECYCLE.value)">
|
||||
移到回收站
|
||||
</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="3"
|
||||
v-if="queryParam.status === 'RECYCLE'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleDeleteMore"
|
||||
>
|
||||
<a-menu-item key="3" v-if="queryParam.status === 'RECYCLE'">
|
||||
<a href="javascript:void(0);" @click="handleDeleteMore">
|
||||
永久删除
|
||||
</a>
|
||||
</a-menu-item>
|
||||
|
@ -109,42 +66,26 @@
|
|||
:dataSource="formattedComments"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<a-dropdown
|
||||
placement="topLeft"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a-dropdown placement="topLeft" :trigger="['click']">
|
||||
<span>
|
||||
<a-icon type="bars" />
|
||||
</span>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item v-if="item.status === 'AUDITING'">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleEditStatusClick(item.id,'PUBLISHED')"
|
||||
>通过</a>
|
||||
<a href="javascript:;" @click="handleEditStatusClick(item.id, 'PUBLISHED')">通过</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="item.status === 'AUDITING'">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleReplyAndPassClick(item)"
|
||||
>通过并回复</a>
|
||||
<a href="javascript:;" @click="handleReplyAndPassClick(item)">通过并回复</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-else-if="item.status === 'PUBLISHED'">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleReplyClick(item)"
|
||||
>回复</a>
|
||||
<a href="javascript:;" @click="handleReplyClick(item)">回复</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-else-if="item.status === 'RECYCLE'">
|
||||
<a-popconfirm
|
||||
:title="'你确定要还原该评论?'"
|
||||
@confirm="handleEditStatusClick(item.id,'PUBLISHED')"
|
||||
@confirm="handleEditStatusClick(item.id, 'PUBLISHED')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
|
@ -154,7 +95,7 @@
|
|||
<a-menu-item v-if="item.status === 'PUBLISHED' || item.status === 'AUDITING'">
|
||||
<a-popconfirm
|
||||
:title="'你确定要将该评论移到回收站?'"
|
||||
@confirm="handleEditStatusClick(item.id,'RECYCLE')"
|
||||
@confirm="handleEditStatusClick(item.id, 'RECYCLE')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
|
@ -176,45 +117,23 @@
|
|||
</template>
|
||||
<template slot="extra">
|
||||
<span>
|
||||
<a-badge
|
||||
:status="item.statusProperty.status"
|
||||
:text="item.statusProperty.text"
|
||||
/>
|
||||
<a-badge :status="item.statusProperty.status" :text="item.statusProperty.text" />
|
||||
</span>
|
||||
</template>
|
||||
<a-list-item-meta>
|
||||
<template slot="description">
|
||||
发表在
|
||||
<a
|
||||
v-if="type==='posts'"
|
||||
:href="item.post.fullPath"
|
||||
target="_blank"
|
||||
>《{{ item.post.title }}》</a>
|
||||
<a
|
||||
v-if="type === 'sheets'"
|
||||
:href="item.sheet.fullPath"
|
||||
target="_blank"
|
||||
>《{{ item.sheet.title }}》</a>
|
||||
<a v-if="type === 'posts'" :href="item.post.fullPath" target="_blank">《{{ item.post.title }}》</a>
|
||||
<a v-if="type === 'sheets'" :href="item.sheet.fullPath" target="_blank">《{{ item.sheet.title }}》</a>
|
||||
</template>
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
size="large"
|
||||
:src="'//cn.gravatar.com/avatar/' + item.gravatarMd5 + '&d=mm'"
|
||||
/>
|
||||
<a-avatar slot="avatar" size="large" :src="'//cn.gravatar.com/avatar/' + item.gravatarMd5 + '&d=mm'" />
|
||||
<span
|
||||
slot="title"
|
||||
style="max-width: 300px;display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
v-if="item.authorUrl"
|
||||
>
|
||||
<a-icon
|
||||
type="user"
|
||||
v-if="item.isAdmin"
|
||||
style="margin-right: 3px;"
|
||||
/>
|
||||
<a
|
||||
:href="item.authorUrl"
|
||||
target="_blank"
|
||||
>{{ item.author }}</a>
|
||||
<a-icon type="user" v-if="item.isAdmin" style="margin-right: 3px;" />
|
||||
<a :href="item.authorUrl" target="_blank">{{ item.author }}</a>
|
||||
<small style="color:rgba(0, 0, 0, 0.45)">{{ item.createTime | timeAgo }}</small>
|
||||
</span>
|
||||
<span
|
||||
|
@ -222,11 +141,10 @@
|
|||
style="max-width: 300px;display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
v-else
|
||||
>
|
||||
<a-icon
|
||||
type="user"
|
||||
v-if="item.isAdmin"
|
||||
style="margin-right: 3px;"
|
||||
/> {{ item.author }} <small style="color:rgba(0, 0, 0, 0.45)">{{ item.createTime | timeAgo }}</small>
|
||||
<a-icon type="user" v-if="item.isAdmin" style="margin-right: 3px;" /> {{ item.author }} <small
|
||||
style="color:rgba(0, 0, 0, 0.45)"
|
||||
>{{ item.createTime | timeAgo }}</small
|
||||
>
|
||||
</span>
|
||||
</a-list-item-meta>
|
||||
<p v-html="item.content"></p>
|
||||
|
@ -247,56 +165,22 @@
|
|||
:pagination="false"
|
||||
scrollToFirstRowOnChange
|
||||
>
|
||||
<template
|
||||
slot="author"
|
||||
slot-scope="text,record"
|
||||
>
|
||||
<a-icon
|
||||
type="user"
|
||||
v-if="record.isAdmin"
|
||||
style="margin-right: 3px;"
|
||||
/>
|
||||
<a
|
||||
:href="record.authorUrl"
|
||||
target="_blank"
|
||||
v-if="record.authorUrl"
|
||||
>{{ text }}</a>
|
||||
<template slot="author" slot-scope="text, record">
|
||||
<a-icon type="user" v-if="record.isAdmin" style="margin-right: 3px;" />
|
||||
<a :href="record.authorUrl" target="_blank" v-if="record.authorUrl">{{ text }}</a>
|
||||
<span v-else>{{ text }}</span>
|
||||
</template>
|
||||
<p
|
||||
class="comment-content-wrapper"
|
||||
slot="content"
|
||||
slot-scope="content"
|
||||
v-html="content"
|
||||
>
|
||||
</p>
|
||||
<span
|
||||
slot="status"
|
||||
slot-scope="statusProperty"
|
||||
>
|
||||
<a-badge
|
||||
:status="statusProperty.status"
|
||||
:text="statusProperty.text"
|
||||
/>
|
||||
<p class="comment-content-wrapper" slot="content" slot-scope="content" v-html="content"></p>
|
||||
<span slot="status" slot-scope="statusProperty">
|
||||
<a-badge :status="statusProperty.status" :text="statusProperty.text" />
|
||||
</span>
|
||||
<a
|
||||
v-if="type==='posts'"
|
||||
slot="post"
|
||||
slot-scope="post"
|
||||
:href="post.fullPath"
|
||||
target="_blank"
|
||||
>{{ post.title }}</a>
|
||||
<a
|
||||
v-if="type === 'sheets'"
|
||||
slot="sheet"
|
||||
slot-scope="sheet"
|
||||
:href="sheet.fullPath"
|
||||
target="_blank"
|
||||
>{{ sheet.title }}</a>
|
||||
<span
|
||||
slot="createTime"
|
||||
slot-scope="createTime"
|
||||
>
|
||||
<a v-if="type === 'posts'" slot="post" slot-scope="post" :href="post.fullPath" target="_blank">{{
|
||||
post.title
|
||||
}}</a>
|
||||
<a v-if="type === 'sheets'" slot="sheet" slot-scope="sheet" :href="sheet.fullPath" target="_blank">{{
|
||||
sheet.title
|
||||
}}</a>
|
||||
<span slot="createTime" slot-scope="createTime">
|
||||
<a-tooltip placement="top">
|
||||
<template slot="title">
|
||||
{{ createTime | moment }}
|
||||
|
@ -304,44 +188,26 @@
|
|||
{{ createTime | timeAgo }}
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
|
||||
<a-dropdown
|
||||
:trigger="['click']"
|
||||
v-if="record.status === 'AUDITING'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="ant-dropdown-link"
|
||||
>通过</a>
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<a-dropdown :trigger="['click']" v-if="record.status === 'AUDITING'">
|
||||
<a href="javascript:void(0);" class="ant-dropdown-link">通过</a>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusClick(record.id,'PUBLISHED')"
|
||||
>通过</a>
|
||||
<a href="javascript:void(0);" @click="handleEditStatusClick(record.id, 'PUBLISHED')">通过</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleReplyAndPassClick(record)"
|
||||
>通过并回复</a>
|
||||
<a href="javascript:void(0);" @click="handleReplyAndPassClick(record)">通过并回复</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
v-else-if="record.status === 'PUBLISHED'"
|
||||
@click="handleReplyClick(record)"
|
||||
>回复</a>
|
||||
<a href="javascript:void(0);" v-else-if="record.status === 'PUBLISHED'" @click="handleReplyClick(record)"
|
||||
>回复</a
|
||||
>
|
||||
|
||||
<a-popconfirm
|
||||
:title="'你确定要还原该评论?'"
|
||||
@confirm="handleEditStatusClick(record.id,'PUBLISHED')"
|
||||
@confirm="handleEditStatusClick(record.id, 'PUBLISHED')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
v-else-if="record.status === 'RECYCLE'"
|
||||
|
@ -353,7 +219,7 @@
|
|||
|
||||
<a-popconfirm
|
||||
:title="'你确定要将该评论移到回收站?'"
|
||||
@confirm="handleEditStatusClick(record.id,'RECYCLE')"
|
||||
@confirm="handleEditStatusClick(record.id, 'RECYCLE')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
v-if="record.status === 'PUBLISHED' || record.status === 'AUDITING'"
|
||||
|
@ -370,13 +236,6 @@
|
|||
>
|
||||
<a href="javascript:;">删除</a>
|
||||
</a-popconfirm>
|
||||
|
||||
<!-- <a-divider type="vertical" />
|
||||
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleShowDetailDrawer(record)"
|
||||
>详情</a> -->
|
||||
</span>
|
||||
</a-table>
|
||||
<div class="page-wrapper">
|
||||
|
@ -397,7 +256,7 @@
|
|||
|
||||
<a-modal
|
||||
v-if="selectedComment"
|
||||
:title="'回复给:'+selectedComment.author"
|
||||
:title="'回复给:' + selectedComment.author"
|
||||
v-model="replyCommentVisible"
|
||||
@close="onReplyClose"
|
||||
destroyOnClose
|
||||
|
@ -414,33 +273,16 @@
|
|||
erroredText="回复失败"
|
||||
></ReactiveButton>
|
||||
</template>
|
||||
<a-form-model
|
||||
ref="replyCommentForm"
|
||||
:model="replyComment"
|
||||
:rules="replyCommentRules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model ref="replyCommentForm" :model="replyComment" :rules="replyCommentRules" layout="vertical">
|
||||
<a-form-model-item prop="content">
|
||||
<a-input
|
||||
ref="contentInput"
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 8 }"
|
||||
v-model.trim="replyComment.content"
|
||||
/>
|
||||
<a-input ref="contentInput" type="textarea" :autoSize="{ minRows: 8 }" v-model.trim="replyComment.content" />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
<!-- <CommentDetail
|
||||
v-model="commentDetailVisible"
|
||||
v-if="selectedComment"
|
||||
:comment="selectedComment"
|
||||
:type="this.type"
|
||||
/> -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mixin, mixinDevice } from '@/mixins/mixin.js'
|
||||
import CommentDetail from './CommentDetail'
|
||||
import marked from 'marked'
|
||||
import commentApi from '@/api/comment'
|
||||
import { decodeHTML } from '@/utils/util'
|
||||
|
@ -451,39 +293,39 @@ const postColumns = [
|
|||
dataIndex: 'author',
|
||||
width: '150px',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'author' },
|
||||
scopedSlots: { customRender: 'author' }
|
||||
},
|
||||
{
|
||||
title: '内容',
|
||||
dataIndex: 'content',
|
||||
scopedSlots: { customRender: 'content' },
|
||||
scopedSlots: { customRender: 'content' }
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
className: 'status',
|
||||
dataIndex: 'statusProperty',
|
||||
width: '100px',
|
||||
scopedSlots: { customRender: 'status' },
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
{
|
||||
title: '评论文章',
|
||||
dataIndex: 'post',
|
||||
width: '200px',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'post' },
|
||||
scopedSlots: { customRender: 'post' }
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'createTime',
|
||||
width: '170px',
|
||||
scopedSlots: { customRender: 'createTime' },
|
||||
scopedSlots: { customRender: 'createTime' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: '180px',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
const sheetColumns = [
|
||||
{
|
||||
|
@ -491,46 +333,43 @@ const sheetColumns = [
|
|||
dataIndex: 'author',
|
||||
width: '150px',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'author' },
|
||||
scopedSlots: { customRender: 'author' }
|
||||
},
|
||||
{
|
||||
title: '内容',
|
||||
dataIndex: 'content',
|
||||
scopedSlots: { customRender: 'content' },
|
||||
scopedSlots: { customRender: 'content' }
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
className: 'status',
|
||||
dataIndex: 'statusProperty',
|
||||
width: '100px',
|
||||
scopedSlots: { customRender: 'status' },
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
{
|
||||
title: '评论页面',
|
||||
dataIndex: 'sheet',
|
||||
width: '200px',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'sheet' },
|
||||
scopedSlots: { customRender: 'sheet' }
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'createTime',
|
||||
width: '170px',
|
||||
scopedSlots: { customRender: 'createTime' },
|
||||
scopedSlots: { customRender: 'createTime' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: '180px',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: 'CommentTab',
|
||||
mixins: [mixin, mixinDevice],
|
||||
components: {
|
||||
CommentDetail,
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
|
@ -538,8 +377,8 @@ export default {
|
|||
default: 'posts',
|
||||
validator: function(value) {
|
||||
return ['posts', 'sheets', 'journals'].indexOf(value) !== -1
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -549,14 +388,14 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
size: 10,
|
||||
sort: null,
|
||||
keyword: null,
|
||||
status: null,
|
||||
status: null
|
||||
},
|
||||
selectedRowKeys: [],
|
||||
selectedRows: [],
|
||||
|
@ -564,13 +403,12 @@ export default {
|
|||
selectedComment: {},
|
||||
replyComment: {},
|
||||
replyCommentRules: {
|
||||
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }],
|
||||
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }]
|
||||
},
|
||||
loading: false,
|
||||
commentStatus: commentApi.commentStatus,
|
||||
commentDetailVisible: false,
|
||||
replying: false,
|
||||
replyErrored: false,
|
||||
replyErrored: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -578,12 +416,12 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
formattedComments() {
|
||||
return this.comments.map((comment) => {
|
||||
return this.comments.map(comment => {
|
||||
comment.statusProperty = this.commentStatus[comment.status]
|
||||
comment.content = marked(decodeHTML(comment.content))
|
||||
return comment
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleListComments() {
|
||||
|
@ -593,7 +431,7 @@ export default {
|
|||
this.queryParam.sort = this.pagination.sort
|
||||
commentApi
|
||||
.queryComment(this.type, this.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.comments = response.data.data.content
|
||||
this.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -610,7 +448,7 @@ export default {
|
|||
handleEditStatusClick(commentId, status) {
|
||||
commentApi
|
||||
.updateStatus(this.type, commentId, status)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('操作成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -620,7 +458,7 @@ export default {
|
|||
handleDeleteClick(commentId) {
|
||||
commentApi
|
||||
.delete(this.type, commentId)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -646,7 +484,7 @@ export default {
|
|||
},
|
||||
handleCreateClick() {
|
||||
const _this = this
|
||||
_this.$refs.replyCommentForm.validate((valid) => {
|
||||
_this.$refs.replyCommentForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.replying = true
|
||||
commentApi
|
||||
|
@ -691,7 +529,7 @@ export default {
|
|||
}
|
||||
commentApi
|
||||
.updateStatusInBatch(this.type, this.selectedRowKeys, status)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$log.debug(`commentIds: ${this.selectedRowKeys}, status: ${status}`)
|
||||
this.selectedRowKeys = []
|
||||
})
|
||||
|
@ -706,7 +544,7 @@ export default {
|
|||
}
|
||||
commentApi
|
||||
.deleteInBatch(this.type, this.selectedRowKeys)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$log.debug(`delete: ${this.selectedRowKeys}`)
|
||||
this.selectedRowKeys = []
|
||||
})
|
||||
|
@ -730,14 +568,10 @@ export default {
|
|||
return {
|
||||
props: {
|
||||
disabled: this.queryParam.status == null || this.queryParam.status === '',
|
||||
name: comment.author,
|
||||
},
|
||||
name: comment.author
|
||||
}
|
||||
}
|
||||
},
|
||||
handleShowDetailDrawer(comment) {
|
||||
this.selectedComment = comment
|
||||
this.commentDetailVisible = true
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -8,19 +8,13 @@
|
|||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-list itemLayout="horizontal">
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<template slot="description">
|
||||
<p
|
||||
v-html="description"
|
||||
class="comment-drawer-content"
|
||||
></p>
|
||||
<p v-html="description" class="comment-drawer-content"></p>
|
||||
</template>
|
||||
<h3 slot="title">{{ title }}</h3>
|
||||
</a-list-item-meta>
|
||||
|
@ -55,17 +49,9 @@
|
|||
</div>
|
||||
<a-divider class="divider-transparent" />
|
||||
<div class="bottom-control">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleCommentReply({})"
|
||||
>评论</a-button>
|
||||
<a-button type="primary" @click="handleCommentReply({})">评论</a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
:title="replyModalTitle"
|
||||
v-model="replyModal.visible"
|
||||
@close="onReplyModalClose"
|
||||
destroyOnClose
|
||||
>
|
||||
<a-modal :title="replyModalTitle" v-model="replyModal.visible" @close="onReplyModalClose" destroyOnClose>
|
||||
<template slot="footer">
|
||||
<ReactiveButton
|
||||
type="primary"
|
||||
|
@ -78,19 +64,9 @@
|
|||
erroredText="回复失败"
|
||||
></ReactiveButton>
|
||||
</template>
|
||||
<a-form-model
|
||||
ref="replyCommentForm"
|
||||
:model="replyModal.model"
|
||||
:rules="replyModal.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model ref="replyCommentForm" :model="replyModal.model" :rules="replyModal.rules" layout="vertical">
|
||||
<a-form-model-item prop="content">
|
||||
<a-input
|
||||
ref="contentInput"
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 8 }"
|
||||
v-model="replyModal.model.content"
|
||||
/>
|
||||
<a-input ref="contentInput" type="textarea" :autoSize="{ minRows: 8 }" v-model="replyModal.model.content" />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
|
@ -114,14 +90,14 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
size: 10,
|
||||
sort: null,
|
||||
keyword: null,
|
||||
},
|
||||
keyword: null
|
||||
}
|
||||
},
|
||||
replyModal: {
|
||||
model: {},
|
||||
|
@ -129,42 +105,42 @@ export default {
|
|||
saving: false,
|
||||
saveErrored: false,
|
||||
rules: {
|
||||
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }],
|
||||
},
|
||||
},
|
||||
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
default: ''
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
default: ''
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
default: ''
|
||||
},
|
||||
id: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
replyModalTitle() {
|
||||
return this.list.selected.id ? `回复给:${this.list.selected.author}` : '评论'
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleListComments() {
|
||||
|
@ -174,7 +150,7 @@ export default {
|
|||
this.list.queryParam.sort = this.list.pagination.sort
|
||||
commentApi
|
||||
.commentTree(this.target, this.id, this.list.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.list.data = response.data.data.content
|
||||
this.list.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -200,7 +176,7 @@ export default {
|
|||
},
|
||||
handleReplyClick() {
|
||||
const _this = this
|
||||
_this.$refs.replyCommentForm.validate((valid) => {
|
||||
_this.$refs.replyCommentForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.replyModal.saving = true
|
||||
commentApi
|
||||
|
@ -229,7 +205,7 @@ export default {
|
|||
handleEditStatusClick(comment, status) {
|
||||
commentApi
|
||||
.updateStatus(this.target, comment.id, status)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('操作成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -239,7 +215,7 @@ export default {
|
|||
handleCommentDelete(comment) {
|
||||
commentApi
|
||||
.delete(this.target, comment.id)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -256,7 +232,7 @@ export default {
|
|||
this.list.pagination = {
|
||||
page: 1,
|
||||
size: 10,
|
||||
sort: '',
|
||||
sort: ''
|
||||
}
|
||||
this.$emit('close', false)
|
||||
},
|
||||
|
@ -264,7 +240,7 @@ export default {
|
|||
if (visible) {
|
||||
this.handleListComments()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,17 +2,11 @@
|
|||
<div>
|
||||
<a-comment>
|
||||
<template slot="actions">
|
||||
<a-dropdown
|
||||
:trigger="['click']"
|
||||
v-if="comment.status === 'AUDITING'"
|
||||
>
|
||||
<a-dropdown :trigger="['click']" v-if="comment.status === 'AUDITING'">
|
||||
<span href="javascript:void(0);">通过</span>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
<span
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusClick('PUBLISHED')"
|
||||
>通过</span>
|
||||
<span href="javascript:void(0);" @click="handleEditStatusClick('PUBLISHED')">通过</span>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
<span href="javascript:void(0);">通过并回复</span>
|
||||
|
@ -20,10 +14,7 @@
|
|||
</a-menu>
|
||||
</a-dropdown>
|
||||
|
||||
<span
|
||||
v-else-if="comment.status === 'PUBLISHED'"
|
||||
@click="handleReplyClick"
|
||||
>回复</span>
|
||||
<span v-else-if="comment.status === 'PUBLISHED'" @click="handleReplyClick">回复</span>
|
||||
|
||||
<a-popconfirm
|
||||
v-else-if="comment.status === 'RECYCLE'"
|
||||
|
@ -45,37 +36,16 @@
|
|||
<span>回收站</span>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-popconfirm
|
||||
:title="'你确定要永久删除该评论?'"
|
||||
@confirm="handleDeleteClick"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
<a-popconfirm :title="'你确定要永久删除该评论?'" @confirm="handleDeleteClick" okText="确定" cancelText="取消">
|
||||
<span>删除</span>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
<a
|
||||
slot="author"
|
||||
:href="comment.authorUrl"
|
||||
target="_blank"
|
||||
>
|
||||
<a-icon
|
||||
type="user"
|
||||
v-if="comment.isAdmin"
|
||||
style="margin-right: 3px;"
|
||||
/>
|
||||
<a slot="author" :href="comment.authorUrl" target="_blank">
|
||||
<a-icon type="user" v-if="comment.isAdmin" style="margin-right: 3px;" />
|
||||
{{ comment.author }}
|
||||
</a>
|
||||
<a-avatar
|
||||
size="large"
|
||||
slot="avatar"
|
||||
:src="avatar"
|
||||
:alt="comment.author"
|
||||
/>
|
||||
<p
|
||||
slot="content"
|
||||
v-html="content"
|
||||
></p>
|
||||
<a-avatar size="large" slot="avatar" :src="avatar" :alt="comment.author" />
|
||||
<p slot="content" v-html="content"></p>
|
||||
<a-tooltip slot="datetime">
|
||||
<span slot="title">{{ comment.createTime | moment }}</span>
|
||||
<span>{{ comment.createTime | timeAgo }}</span>
|
||||
|
|
|
@ -1,165 +1,69 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
class="mb-3"
|
||||
>
|
||||
<analysis-card
|
||||
title="文章"
|
||||
:number="statisticsData.postCount"
|
||||
>
|
||||
<router-link
|
||||
:to="{ name:'PostWrite' }"
|
||||
slot="action"
|
||||
>
|
||||
<a-icon
|
||||
v-if="statisticsLoading"
|
||||
type="loading"
|
||||
/>
|
||||
<a-icon
|
||||
v-else
|
||||
type="plus"
|
||||
/>
|
||||
<a-col :xl="6" :lg="6" :md="12" :sm="12" :xs="12" class="mb-3">
|
||||
<analysis-card title="文章" :number="statisticsData.postCount">
|
||||
<router-link :to="{ name: 'PostWrite' }" slot="action">
|
||||
<a-icon v-if="statisticsLoading" type="loading" />
|
||||
<a-icon v-else type="plus" />
|
||||
</router-link>
|
||||
</analysis-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
class="mb-3"
|
||||
>
|
||||
<analysis-card
|
||||
title="评论"
|
||||
:number="statisticsData.commentCount"
|
||||
>
|
||||
<router-link
|
||||
:to="{ name:'Comments' }"
|
||||
slot="action"
|
||||
>
|
||||
<a-icon
|
||||
v-if="statisticsLoading"
|
||||
type="loading"
|
||||
/>
|
||||
<a-icon
|
||||
v-else
|
||||
type="unordered-list"
|
||||
/>
|
||||
<a-col :xl="6" :lg="6" :md="12" :sm="12" :xs="12" class="mb-3">
|
||||
<analysis-card title="评论" :number="statisticsData.commentCount">
|
||||
<router-link :to="{ name: 'Comments' }" slot="action">
|
||||
<a-icon v-if="statisticsLoading" type="loading" />
|
||||
<a-icon v-else type="unordered-list" />
|
||||
</router-link>
|
||||
</analysis-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
class="mb-3"
|
||||
>
|
||||
<analysis-card
|
||||
title="阅读量"
|
||||
:number="statisticsData.visitCount"
|
||||
>
|
||||
<a-col :xl="6" :lg="6" :md="12" :sm="12" :xs="12" class="mb-3">
|
||||
<analysis-card title="阅读量" :number="statisticsData.visitCount">
|
||||
<a-tooltip slot="action">
|
||||
<template slot="title">
|
||||
文章阅读共 {{ statisticsData.visitCount }} 次
|
||||
</template>
|
||||
<template slot="title"> 文章阅读共 {{ statisticsData.visitCount }} 次 </template>
|
||||
<a href="javascript:void(0);">
|
||||
<a-icon
|
||||
v-if="statisticsLoading"
|
||||
type="loading"
|
||||
/>
|
||||
<a-icon
|
||||
v-else
|
||||
type="info-circle-o"
|
||||
/>
|
||||
<a-icon v-if="statisticsLoading" type="loading" />
|
||||
<a-icon v-else type="info-circle-o" />
|
||||
</a>
|
||||
</a-tooltip>
|
||||
</analysis-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
class="mb-3"
|
||||
>
|
||||
<analysis-card
|
||||
title="建立天数"
|
||||
:number="statisticsData.establishDays"
|
||||
>
|
||||
<a-col :xl="6" :lg="6" :md="12" :sm="12" :xs="12" class="mb-3">
|
||||
<analysis-card title="建立天数" :number="statisticsData.establishDays">
|
||||
<a-tooltip slot="action">
|
||||
<template slot="title">博客建立于 {{ statisticsData.birthday | moment }}</template>
|
||||
<a href="javascript:void(0);">
|
||||
<a-icon
|
||||
v-if="statisticsLoading"
|
||||
type="loading"
|
||||
/>
|
||||
<a-icon
|
||||
v-else
|
||||
type="info-circle-o"
|
||||
/>
|
||||
<a-icon v-if="statisticsLoading" type="loading" />
|
||||
<a-icon v-else type="info-circle-o" />
|
||||
</a>
|
||||
</a-tooltip>
|
||||
</analysis-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
title="新动态"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card :bordered="false" title="新动态" :bodyStyle="{ padding: 0 }">
|
||||
<div class="card-container">
|
||||
<a-tabs type="card">
|
||||
<a-tab-pane
|
||||
key="1"
|
||||
tab="最近文章"
|
||||
>
|
||||
<a-list
|
||||
:loading="activityLoading"
|
||||
:dataSource="latestPosts"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-tab-pane key="1" tab="最近文章">
|
||||
<a-list :loading="activityLoading" :dataSource="latestPosts">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-list-item-meta>
|
||||
<a
|
||||
v-if="item.status=='PUBLISHED' || item.status == 'INTIMATE'"
|
||||
v-if="item.status == 'PUBLISHED' || item.status == 'INTIMATE'"
|
||||
slot="title"
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
>{{ item.title }}</a>
|
||||
>{{ item.title }}</a
|
||||
>
|
||||
<a
|
||||
v-else-if="item.status=='DRAFT'"
|
||||
v-else-if="item.status == 'DRAFT'"
|
||||
slot="title"
|
||||
href="javascript:void(0)"
|
||||
@click="handlePostPreview(item.id)"
|
||||
>{{ item.title }}</a>
|
||||
<a
|
||||
v-else-if="item.status=='RECYCLE'"
|
||||
slot="title"
|
||||
href="javascript:void(0);"
|
||||
disabled
|
||||
>{{ item.title }}</a
|
||||
>
|
||||
<a v-else-if="item.status == 'RECYCLE'" slot="title" href="javascript:void(0);" disabled>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
</a-list-item-meta>
|
||||
|
@ -167,22 +71,13 @@
|
|||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="2"
|
||||
tab="最近评论"
|
||||
>
|
||||
<a-tab-pane key="2" tab="最近评论">
|
||||
<div class="custom-tab-wrapper">
|
||||
<a-tabs>
|
||||
<a-tab-pane
|
||||
tab="文章"
|
||||
key="1"
|
||||
>
|
||||
<a-tab-pane tab="文章" key="1">
|
||||
<recent-comment-tab type="posts"></recent-comment-tab>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
tab="页面"
|
||||
key="2"
|
||||
>
|
||||
<a-tab-pane tab="页面" key="2">
|
||||
<recent-comment-tab type="sheets"></recent-comment-tab>
|
||||
</a-tab-pane>
|
||||
<!-- <a-tab-pane
|
||||
|
@ -198,68 +93,32 @@
|
|||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="24" :xs="24" class="mb-3">
|
||||
<JournalPublishCard />
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<template slot="title">
|
||||
操作记录
|
||||
<a-tooltip
|
||||
slot="action"
|
||||
title="更多"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="logListDrawerVisible = true"
|
||||
>
|
||||
<a-tooltip slot="action" title="更多">
|
||||
<a href="javascript:void(0);" @click="logListDrawerVisible = true">
|
||||
<a-icon type="ellipsis" />
|
||||
</a>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-list
|
||||
:dataSource="formattedLogDatas"
|
||||
:loading="logLoading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list :dataSource="formattedLogDatas" :loading="logLoading">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-list-item-meta :description="item.createTime | timeAgo">
|
||||
<span slot="title">{{ item.type }}</span>
|
||||
</a-list-item-meta>
|
||||
<ellipsis
|
||||
:length="35"
|
||||
tooltip
|
||||
>{{ item.content }}</ellipsis>
|
||||
<ellipsis :length="35" tooltip>{{ item.content }}</ellipsis>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<LogListDrawer
|
||||
:visible="logListDrawerVisible"
|
||||
@close="handleLogListClose"
|
||||
/>
|
||||
<LogListDrawer :visible="logListDrawerVisible" @close="handleLogListClose" />
|
||||
</page-view>
|
||||
</template>
|
||||
|
||||
|
@ -269,7 +128,6 @@ import AnalysisCard from './components/AnalysisCard'
|
|||
import JournalPublishCard from './components/JournalPublishCard'
|
||||
import RecentCommentTab from './components/RecentCommentTab'
|
||||
import LogListDrawer from './components/LogListDrawer'
|
||||
import countTo from 'vue-count-to'
|
||||
|
||||
import postApi from '@/api/post'
|
||||
import logApi from '@/api/log'
|
||||
|
@ -281,7 +139,6 @@ export default {
|
|||
AnalysisCard,
|
||||
JournalPublishCard,
|
||||
RecentCommentTab,
|
||||
countTo,
|
||||
LogListDrawer
|
||||
},
|
||||
data() {
|
||||
|
@ -307,7 +164,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
formattedLogDatas() {
|
||||
return this.latestLogs.map((log) => {
|
||||
return this.latestLogs.map(log => {
|
||||
log.type = this.logTypes[log.type].text
|
||||
return log
|
||||
})
|
||||
|
@ -319,7 +176,7 @@ export default {
|
|||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
next((vm) => {
|
||||
next(vm => {
|
||||
vm.interval = setInterval(() => {
|
||||
vm.handleLoadStatistics()
|
||||
}, 5000)
|
||||
|
@ -341,7 +198,7 @@ export default {
|
|||
this.activityLoading = true
|
||||
postApi
|
||||
.listLatest(5)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.latestPosts = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -354,7 +211,7 @@ export default {
|
|||
this.logLoading = true
|
||||
logApi
|
||||
.listLatest(5)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.latestLogs = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -366,7 +223,7 @@ export default {
|
|||
handleLoadStatistics() {
|
||||
statisticsApi
|
||||
.statistics()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.statisticsData = response.data.data
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -379,7 +236,7 @@ export default {
|
|||
})
|
||||
},
|
||||
handlePostPreview(postId) {
|
||||
postApi.preview(postId).then((response) => {
|
||||
postApi.preview(postId).then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
})
|
||||
},
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<a-card
|
||||
:body-style="{ padding: '24px' }"
|
||||
:bordered="false"
|
||||
>
|
||||
<a-card :body-style="{ padding: '24px' }" :bordered="false">
|
||||
<div class="analysis-card-container">
|
||||
<div class="meta">
|
||||
<span class="analysis-card-title">
|
||||
|
@ -16,7 +13,7 @@
|
|||
<slot name="number">
|
||||
<countTo
|
||||
:startVal="startNumber"
|
||||
:endVal="typeof number === 'function' && number() || number"
|
||||
:endVal="(typeof number === 'function' && number()) || number"
|
||||
:duration="3000"
|
||||
:autoplay="true"
|
||||
></countTo>
|
||||
|
|
|
@ -1,23 +1,12 @@
|
|||
<template>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<template slot="title">
|
||||
速记
|
||||
<a-tooltip
|
||||
slot="action"
|
||||
title="内容将保存到页面/所有页面/日志页面"
|
||||
>
|
||||
<a-icon type="info-circle-o" class="cursor-pointer"/>
|
||||
<a-tooltip slot="action" title="内容将保存到页面/所有页面/日志页面">
|
||||
<a-icon type="info-circle-o" class="cursor-pointer" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-form-model
|
||||
ref="journalForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model ref="journalForm" :model="form.model" :rules="form.rules" layout="vertical">
|
||||
<a-form-model-item prop="sourceContent">
|
||||
<a-input
|
||||
type="textarea"
|
||||
|
@ -29,10 +18,12 @@
|
|||
<a-form-model-item>
|
||||
<ReactiveButton
|
||||
@click="handleCreateJournalClick"
|
||||
@callback="() => {
|
||||
if(!form.errored) form.model = {}
|
||||
form.errored = false
|
||||
}"
|
||||
@callback="
|
||||
() => {
|
||||
if (!form.errored) form.model = {}
|
||||
form.errored = false
|
||||
}
|
||||
"
|
||||
:loading="form.saving"
|
||||
:errored="form.errored"
|
||||
text="发布"
|
||||
|
|
|
@ -2,34 +2,21 @@
|
|||
<div>
|
||||
<a-drawer
|
||||
title="操作日志"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-list
|
||||
:loading="loading"
|
||||
:dataSource="formattedLogsDatas"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list :loading="loading" :dataSource="formattedLogsDatas">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-list-item-meta :description="item.createTime | timeAgo">
|
||||
<span slot="title">{{ item.type }}</span>
|
||||
</a-list-item-meta>
|
||||
<ellipsis
|
||||
:length="35"
|
||||
tooltip
|
||||
>{{ item.content }}</ellipsis>
|
||||
<ellipsis :length="35" tooltip>{{ item.content }}</ellipsis>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
||||
|
@ -39,7 +26,7 @@
|
|||
:current="pagination.page"
|
||||
:total="pagination.total"
|
||||
:defaultPageSize="pagination.size"
|
||||
:pageSizeOptions="['50', '100','150','200']"
|
||||
:pageSizeOptions="['50', '100', '150', '200']"
|
||||
showSizeChanger
|
||||
@showSizeChange="handlePaginationChange"
|
||||
@change="handlePaginationChange"
|
||||
|
@ -50,12 +37,7 @@
|
|||
</a-row>
|
||||
<a-divider class="divider-transparent" />
|
||||
<div class="bottom-control">
|
||||
<a-popconfirm
|
||||
title="你确定要清空所有操作日志?"
|
||||
okText="确定"
|
||||
@confirm="handleClearLogs"
|
||||
cancelText="取消"
|
||||
>
|
||||
<a-popconfirm title="你确定要清空所有操作日志?" okText="确定" @confirm="handleClearLogs" cancelText="取消">
|
||||
<a-button type="danger">清空操作日志</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
|
@ -123,7 +105,7 @@ export default {
|
|||
handleClearLogs() {
|
||||
logApi
|
||||
.clear()
|
||||
.then(response => {
|
||||
.then(() => {
|
||||
this.$message.success('清除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
|
|
@ -1,68 +1,40 @@
|
|||
<template>
|
||||
<a-list
|
||||
itemLayout="horizontal"
|
||||
:dataSource="formmatedCommentData"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-comment :avatar="'//cn.gravatar.com/avatar/'+item.gravatarMd5+'/?s=256&d=mp'">
|
||||
<template
|
||||
slot="author"
|
||||
v-if="type==='posts'"
|
||||
>
|
||||
<a
|
||||
:href="item.authorUrl"
|
||||
target="_blank"
|
||||
>{{ item.author }}</a> 发表在 《<a
|
||||
v-if="item.post.status=='PUBLISHED' || item.post.status=='INTIMATE'"
|
||||
<a-list itemLayout="horizontal" :dataSource="formmatedCommentData" :loading="loading">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-comment :avatar="'//cn.gravatar.com/avatar/' + item.gravatarMd5 + '/?s=256&d=mp'">
|
||||
<template slot="author" v-if="type === 'posts'">
|
||||
<a :href="item.authorUrl" target="_blank">{{ item.author }}</a> 发表在 《<a
|
||||
v-if="item.post.status == 'PUBLISHED' || item.post.status == 'INTIMATE'"
|
||||
:href="item.post.fullPath"
|
||||
target="_blank"
|
||||
>{{ item.post.title }}</a><a
|
||||
v-else-if="item.post.status=='DRAFT'"
|
||||
>{{ item.post.title }}</a
|
||||
><a
|
||||
v-else-if="item.post.status == 'DRAFT'"
|
||||
href="javascript:void(0)"
|
||||
@click="handlePostPreview(item.post.id)"
|
||||
>{{ item.post.title }}</a><a
|
||||
v-else
|
||||
href="javascript:void(0)"
|
||||
>{{ item.post.title }}</a>
|
||||
>{{ item.post.title }}</a
|
||||
><a v-else href="javascript:void(0)">{{ item.post.title }}</a>
|
||||
》
|
||||
</template>
|
||||
<template
|
||||
slot="author"
|
||||
v-else-if="type==='sheets'"
|
||||
>
|
||||
<a
|
||||
:href="item.authorUrl"
|
||||
target="_blank"
|
||||
>{{ item.author }}</a> 发表在 《<a
|
||||
v-if="item.sheet.status=='PUBLISHED'"
|
||||
<template slot="author" v-else-if="type === 'sheets'">
|
||||
<a :href="item.authorUrl" target="_blank">{{ item.author }}</a> 发表在 《<a
|
||||
v-if="item.sheet.status == 'PUBLISHED'"
|
||||
:href="item.sheet.fullPath"
|
||||
target="_blank"
|
||||
>{{ item.sheet.title }}</a><a
|
||||
v-else-if="item.sheet.status=='DRAFT'"
|
||||
>{{ item.sheet.title }}</a
|
||||
><a
|
||||
v-else-if="item.sheet.status == 'DRAFT'"
|
||||
href="javascript:void(0)"
|
||||
@click="handleSheetPreview(item.sheet.id)"
|
||||
>{{ item.sheet.title }}</a><a
|
||||
v-else
|
||||
href="javascript:void(0)"
|
||||
>{{ item.sheet.title }}</a>》
|
||||
>{{ item.sheet.title }}</a
|
||||
><a v-else href="javascript:void(0)">{{ item.sheet.title }}</a
|
||||
>》
|
||||
</template>
|
||||
<!-- <template slot="actions">
|
||||
<span>回复</span>
|
||||
</template> -->
|
||||
<p
|
||||
class="comment-content-wrapper"
|
||||
slot="content"
|
||||
v-html="item.content"
|
||||
></p>
|
||||
<a-tooltip
|
||||
slot="datetime"
|
||||
:title="item.createTime | moment"
|
||||
>
|
||||
<p class="comment-content-wrapper" slot="content" v-html="item.content"></p>
|
||||
<a-tooltip slot="datetime" :title="item.createTime | moment">
|
||||
<span>{{ item.createTime | timeAgo }}</span>
|
||||
</a-tooltip>
|
||||
</a-comment>
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
<template>
|
||||
<div class="exception">
|
||||
<a-result
|
||||
:status="type"
|
||||
:title="type"
|
||||
:subTitle="config[type].desc"
|
||||
>
|
||||
<a-result :status="type" :title="type" :subTitle="config[type].desc">
|
||||
<template v-slot:extra>
|
||||
<a-button type="primary" @click="handleToHome">返回仪表盘</a-button>
|
||||
</template>
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="6"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
title="分组"
|
||||
>
|
||||
<a-col :xl="6" :lg="6" :md="6" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card :bodyStyle="{ padding: '16px' }" title="分组">
|
||||
<template slot="extra">
|
||||
<ReactiveButton
|
||||
type="default"
|
||||
|
@ -27,19 +17,16 @@
|
|||
</template>
|
||||
<div class="menu-teams">
|
||||
<a-spin :spinning="teams.loading">
|
||||
<a-empty v-if="teams.data.length===0 && !teams.loading" />
|
||||
<a-empty v-if="teams.data.length === 0 && !teams.loading" />
|
||||
<a-menu
|
||||
class="w-full"
|
||||
mode="inline"
|
||||
v-model="selectedTeam"
|
||||
v-if="teams.data.length>0"
|
||||
v-if="teams.data.length > 0"
|
||||
@select="handleSelectedTeam"
|
||||
>
|
||||
<a-menu-item
|
||||
v-for="(team) in teams.data"
|
||||
:key="team"
|
||||
>
|
||||
{{ team===''?'未分组':team }}{{ defaultMenuTeam===team?'(默认)':'' }}
|
||||
<a-menu-item v-for="team in teams.data" :key="team">
|
||||
{{ team === '' ? '未分组' : team }}{{ defaultMenuTeam === team ? '(默认)' : '' }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-spin>
|
||||
|
@ -60,39 +47,22 @@
|
|||
@keyup.enter.native="handleCreateTeam"
|
||||
>
|
||||
<a-form-model-item prop="team">
|
||||
<a-input
|
||||
v-model="teams.form.model.team"
|
||||
autoFocus
|
||||
/>
|
||||
<a-input v-model="teams.form.model.team" autoFocus />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item style="margin-bottom:0">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleCreateTeam"
|
||||
>
|
||||
<a-button type="primary" @click="handleCreateTeam">
|
||||
新增
|
||||
</a-button>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</template>
|
||||
<a-button
|
||||
type="primary"
|
||||
block
|
||||
class="mt-3"
|
||||
>
|
||||
<a-button type="primary" block class="mt-3">
|
||||
新增分组
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="18"
|
||||
:lg="18"
|
||||
:md="18"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-col :xl="18" :lg="18" :md="18" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :bodyStyle="{ padding: '16px' }">
|
||||
<template slot="title">
|
||||
<span>
|
||||
|
@ -103,37 +73,25 @@
|
|||
title="分组下的菜单为空时,该分组也不会保存"
|
||||
v-if="list.data.length <= 0 && !list.loading"
|
||||
>
|
||||
<a-icon
|
||||
type="info-circle-o"
|
||||
class="cursor-pointer"
|
||||
/>
|
||||
<a-icon type="info-circle-o" class="cursor-pointer" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template slot="extra">
|
||||
<a-space>
|
||||
<ReactiveButton
|
||||
@click="handleUpdateBatch"
|
||||
@callback="formBatch.errored=false"
|
||||
@callback="formBatch.errored = false"
|
||||
:loading="formBatch.saving"
|
||||
:errored="formBatch.errored"
|
||||
text="保存"
|
||||
loadedText="保存成功"
|
||||
erroredText="保存失败"
|
||||
:disabled="list.data.length<=0"
|
||||
:disabled="list.data.length <= 0"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
v-if="!form.visible"
|
||||
@click="handleOpenCreateMenuForm()"
|
||||
type="primary"
|
||||
ghost
|
||||
>
|
||||
<a-button v-if="!form.visible" @click="handleOpenCreateMenuForm()" type="primary" ghost>
|
||||
新增
|
||||
</a-button>
|
||||
<a-button
|
||||
v-else
|
||||
@click="handleCloseCreateMenuForm()"
|
||||
type="default"
|
||||
>
|
||||
<a-button v-else @click="handleCloseCreateMenuForm()" type="default">
|
||||
取消新增
|
||||
</a-button>
|
||||
<a-dropdown :trigger="['click']">
|
||||
|
@ -145,7 +103,8 @@
|
|||
删除当前组
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<a-button> 其他
|
||||
<a-button>
|
||||
其他
|
||||
<a-icon type="down" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
|
@ -158,12 +117,8 @@
|
|||
@succeed="handleCreateMenuSucceed()"
|
||||
@cancel="handleCloseCreateMenuForm()"
|
||||
/>
|
||||
<a-empty v-if="list.data.length===0 && !list.loading && !form.visible" />
|
||||
<MenuTreeNode
|
||||
v-model="list.data"
|
||||
:excludedTeams="excludedTeams"
|
||||
@reload="handleListMenus"
|
||||
/>
|
||||
<a-empty v-if="list.data.length === 0 && !list.loading && !form.visible" />
|
||||
<MenuTreeNode v-model="list.data" :excludedTeams="excludedTeams" @reload="handleListMenus" />
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
@ -179,7 +134,6 @@
|
|||
<script>
|
||||
// components
|
||||
import { PageView } from '@/layouts'
|
||||
import draggable from 'vuedraggable'
|
||||
import MenuTreeNode from './components/MenuTreeNode'
|
||||
import MenuForm from './components/MenuForm'
|
||||
import MenuInternalLinkSelector from './components/MenuInternalLinkSelector'
|
||||
|
@ -191,20 +145,20 @@ import { mapActions, mapGetters } from 'vuex'
|
|||
import menuApi from '@/api/menu'
|
||||
import optionApi from '@/api/option'
|
||||
export default {
|
||||
components: { PageView, draggable, MenuTreeNode, MenuForm, MenuInternalLinkSelector },
|
||||
components: { PageView, MenuTreeNode, MenuForm, MenuInternalLinkSelector },
|
||||
data() {
|
||||
return {
|
||||
list: {
|
||||
data: [],
|
||||
loading: false,
|
||||
loading: false
|
||||
},
|
||||
form: {
|
||||
visible: false,
|
||||
model: {},
|
||||
model: {}
|
||||
},
|
||||
formBatch: {
|
||||
saving: false,
|
||||
errored: false,
|
||||
errored: false
|
||||
},
|
||||
teams: {
|
||||
data: [],
|
||||
|
@ -213,20 +167,20 @@ export default {
|
|||
form: {
|
||||
visible: false,
|
||||
model: {
|
||||
team: null,
|
||||
team: null
|
||||
},
|
||||
rules: {
|
||||
team: [{ required: true, message: '分组名称不能为空', trigger: ['change'] }],
|
||||
},
|
||||
team: [{ required: true, message: '分组名称不能为空', trigger: ['change'] }]
|
||||
}
|
||||
},
|
||||
default: {
|
||||
saving: false,
|
||||
errored: false,
|
||||
},
|
||||
errored: false
|
||||
}
|
||||
},
|
||||
menuInternalLinkSelector: {
|
||||
visible: false,
|
||||
},
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -239,7 +193,7 @@ export default {
|
|||
return this.handleGetMenusWithoutLevel(this.computedMenusMoved, [])
|
||||
},
|
||||
computedMenuIds() {
|
||||
return this.computedMenusWithoutLevel.map((menu) => {
|
||||
return this.computedMenusWithoutLevel.map(menu => {
|
||||
return menu.id
|
||||
})
|
||||
},
|
||||
|
@ -249,19 +203,19 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.teams.selected = value[0]
|
||||
},
|
||||
}
|
||||
},
|
||||
menuListTitle() {
|
||||
return this.teams.selected === '' ? '未分组' : this.teams.selected
|
||||
},
|
||||
excludedTeams() {
|
||||
return this.teams.data.filter((item) => {
|
||||
return this.teams.data.filter(item => {
|
||||
return item !== this.teams.selected
|
||||
})
|
||||
},
|
||||
defaultMenuTeam() {
|
||||
return this.options.default_menu_team ? this.options.default_menu_team : ''
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.handleListTeams()
|
||||
|
@ -272,7 +226,7 @@ export default {
|
|||
this.teams.loading = true
|
||||
menuApi
|
||||
.listTeams()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.teams.data = response.data.data
|
||||
if (!this.teams.selected || autoSelectTeam) {
|
||||
this.teams.selected = this.teams.data[0]
|
||||
|
@ -290,7 +244,7 @@ export default {
|
|||
this.list.loading = true
|
||||
menuApi
|
||||
.listTreeByTeam(this.teams.selected)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.list.data = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -320,7 +274,7 @@ export default {
|
|||
}
|
||||
return result
|
||||
},
|
||||
handleSelectedTeam({ item, key, selectedKeys }) {
|
||||
handleSelectedTeam({ key }) {
|
||||
this.teams.selected = key
|
||||
this.handleCloseCreateMenuForm()
|
||||
this.handleListMenus()
|
||||
|
@ -348,7 +302,7 @@ export default {
|
|||
menuApi.deleteBatch(_this.computedMenuIds).finally(() => {
|
||||
_this.handleListTeams(true)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
handleTeamFormVisibleChange(visible) {
|
||||
|
@ -358,7 +312,7 @@ export default {
|
|||
},
|
||||
handleCreateTeam() {
|
||||
const _this = this
|
||||
_this.$refs.teamForm.validate((valid) => {
|
||||
_this.$refs.teamForm.validate(valid => {
|
||||
if (valid) {
|
||||
if (!_this.teams.data.includes(_this.teams.form.model.team)) {
|
||||
_this.teams.data.push(_this.teams.form.model.team)
|
||||
|
@ -373,7 +327,7 @@ export default {
|
|||
this.form.visible = true
|
||||
this.form.model = {
|
||||
team: this.teams.selected,
|
||||
target: '_self',
|
||||
target: '_self'
|
||||
}
|
||||
},
|
||||
handleCloseCreateMenuForm() {
|
||||
|
@ -388,7 +342,7 @@ export default {
|
|||
this.teams.default.saving = true
|
||||
optionApi
|
||||
.save({
|
||||
default_menu_team: this.teams.selected,
|
||||
default_menu_team: this.teams.selected
|
||||
})
|
||||
.catch(() => {
|
||||
this.teams.default.errored = true
|
||||
|
@ -405,7 +359,7 @@ export default {
|
|||
} else {
|
||||
this.refreshOptionsCache()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,63 +1,31 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="6"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-col :xl="6" :lg="6" :md="6" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :bodyStyle="{ padding: '16px' }">
|
||||
<template slot="title">
|
||||
<a-select
|
||||
class="w-full"
|
||||
@change="onSelectTheme"
|
||||
v-model="selectedTheme.id"
|
||||
:loading="themesLoading"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(theme,index) in themes"
|
||||
:key="index"
|
||||
:value="theme.id"
|
||||
>{{ theme.name }}
|
||||
<a-icon
|
||||
v-if="theme.activated"
|
||||
type="check"
|
||||
/>
|
||||
<a-select class="w-full" @change="onSelectTheme" v-model="selectedTheme.id" :loading="themesLoading">
|
||||
<a-select-option v-for="(theme, index) in themes" :key="index" :value="theme.id"
|
||||
>{{ theme.name }}
|
||||
<a-icon v-if="theme.activated" type="check" />
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
<a-spin :spinning="filesLoading">
|
||||
<theme-file
|
||||
v-if="files"
|
||||
:files="files"
|
||||
@listenToSelect="handleSelectFile"
|
||||
/>
|
||||
<theme-file v-if="files" :files="files" @listenToSelect="handleSelectFile" />
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="18"
|
||||
:lg="18"
|
||||
:md="18"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-col :xl="18" :lg="18" :md="18" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :bodyStyle="{ padding: '16px' }">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item>
|
||||
<codemirror
|
||||
v-model="content"
|
||||
:options="codemirrorOptions"
|
||||
></codemirror>
|
||||
<codemirror v-model="content" :options="codemirrorOptions"></codemirror>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<ReactiveButton
|
||||
@click="handlerSaveContent"
|
||||
@callback="saveErrored=false"
|
||||
@callback="saveErrored = false"
|
||||
:loading="saving"
|
||||
:errored="saveErrored"
|
||||
:disabled="buttonDisabled"
|
||||
|
@ -83,7 +51,7 @@ export default {
|
|||
components: {
|
||||
codemirror,
|
||||
ThemeFile,
|
||||
PageView,
|
||||
PageView
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -92,7 +60,7 @@ export default {
|
|||
tabSize: 4,
|
||||
mode: 'text/html',
|
||||
lineNumbers: true,
|
||||
line: true,
|
||||
line: true
|
||||
},
|
||||
files: [],
|
||||
filesLoading: false,
|
||||
|
@ -102,7 +70,7 @@ export default {
|
|||
themesLoading: false,
|
||||
selectedTheme: {},
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
saveErrored: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -112,7 +80,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
handleGetActivatedTheme() {
|
||||
themeApi.getActivatedTheme().then((response) => {
|
||||
themeApi.getActivatedTheme().then(response => {
|
||||
this.selectedTheme = response.data.data
|
||||
})
|
||||
},
|
||||
|
@ -120,7 +88,7 @@ export default {
|
|||
this.filesLoading = true
|
||||
themeApi
|
||||
.listFilesActivated()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.files = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -133,7 +101,7 @@ export default {
|
|||
this.themesLoading = true
|
||||
themeApi
|
||||
.list()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.themes = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -147,7 +115,7 @@ export default {
|
|||
this.filesLoading = true
|
||||
themeApi
|
||||
.listFiles(themeId)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.files = response.data.data
|
||||
this.content = ''
|
||||
this.file = {}
|
||||
|
@ -180,10 +148,10 @@ export default {
|
|||
_this.content = ''
|
||||
_this.file = {}
|
||||
_this.buttonDisabled = true
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
themeApi.getContent(this.selectedTheme.id, file.path).then((response) => {
|
||||
themeApi.getContent(this.selectedTheme.id, file.path).then(response => {
|
||||
this.content = response.data.data
|
||||
this.file = file
|
||||
this.buttonDisabled = false
|
||||
|
@ -201,7 +169,7 @@ export default {
|
|||
this.saving = false
|
||||
}, 400)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,121 +1,42 @@
|
|||
<template>
|
||||
<page-view
|
||||
affix
|
||||
:title="activatedTheme ? activatedTheme.name : '无'"
|
||||
subTitle="当前启用"
|
||||
>
|
||||
<page-view affix :title="activatedTheme ? activatedTheme.name : '无'" subTitle="当前启用">
|
||||
<template slot="extra">
|
||||
<a-button
|
||||
icon="reload"
|
||||
:loading="list.loading"
|
||||
@click="handleRefreshThemesCache"
|
||||
>
|
||||
<a-button icon="reload" :loading="list.loading" @click="handleRefreshThemesCache">
|
||||
刷新
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="installModal.visible = true"
|
||||
>
|
||||
<a-button type="primary" icon="plus" @click="installModal.visible = true">
|
||||
安装
|
||||
</a-button>
|
||||
</template>
|
||||
<a-row
|
||||
:gutter="12"
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row :gutter="12" type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-list
|
||||
:grid="{ gutter: 12, xs: 1, sm: 1, md: 2, lg: 4, xl: 4, xxl: 4 }"
|
||||
:dataSource="sortedThemes"
|
||||
:loading="list.loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-card
|
||||
hoverable
|
||||
:title="item.name"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-card hoverable :title="item.name" :bodyStyle="{ padding: 0 }">
|
||||
<div class="theme-screenshot">
|
||||
<img
|
||||
:alt="item.name"
|
||||
:src="item.screenshots || '/images/placeholder.jpg'"
|
||||
loading="lazy"
|
||||
/>
|
||||
<img :alt="item.name" :src="item.screenshots || '/images/placeholder.jpg'" loading="lazy" />
|
||||
</div>
|
||||
<template
|
||||
class="ant-card-actions"
|
||||
slot="actions"
|
||||
>
|
||||
<div v-if="item.activated">
|
||||
<a-icon
|
||||
type="unlock"
|
||||
theme="twoTone"
|
||||
style="margin-right:3px"
|
||||
/>已启用
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
@click="handleActiveTheme(item)"
|
||||
>
|
||||
<a-icon
|
||||
type="lock"
|
||||
style="margin-right:3px"
|
||||
/>启用
|
||||
</div>
|
||||
<template class="ant-card-actions" slot="actions">
|
||||
<div v-if="item.activated"><a-icon type="unlock" theme="twoTone" style="margin-right:3px" />已启用</div>
|
||||
<div v-else @click="handleActiveTheme(item)"><a-icon type="lock" style="margin-right:3px" />启用</div>
|
||||
<div @click="handleOpenThemeSettingDrawer(item)">
|
||||
<a-icon
|
||||
type="setting"
|
||||
style="margin-right:3px"
|
||||
/>设置
|
||||
<a-icon type="setting" style="margin-right:3px" />设置
|
||||
</div>
|
||||
<a-dropdown
|
||||
placement="topCenter"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
href="#"
|
||||
>
|
||||
<a-icon
|
||||
type="ellipsis"
|
||||
style="margin-right:3px"
|
||||
/>更多
|
||||
</a>
|
||||
<a-dropdown placement="topCenter" :trigger="['click']">
|
||||
<a class="ant-dropdown-link" href="#"> <a-icon type="ellipsis" style="margin-right:3px" />更多 </a>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item
|
||||
:key="1"
|
||||
:disabled="item.activated"
|
||||
@click="handleOpenThemeDeleteModal(item)"
|
||||
>
|
||||
<a-icon
|
||||
type="delete"
|
||||
style="margin-right:3px"
|
||||
/>删除
|
||||
<a-menu-item :key="1" :disabled="item.activated" @click="handleOpenThemeDeleteModal(item)">
|
||||
<a-icon type="delete" style="margin-right:3px" />删除
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
:key="2"
|
||||
v-if="item.repo"
|
||||
@click="handleConfirmRemoteUpdate(item)"
|
||||
>
|
||||
<a-icon
|
||||
type="cloud"
|
||||
style="margin-right:3px"
|
||||
/>在线更新
|
||||
<a-menu-item :key="2" v-if="item.repo" @click="handleConfirmRemoteUpdate(item)">
|
||||
<a-icon type="cloud" style="margin-right:3px" />在线更新
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
:key="3"
|
||||
@click="handleOpenLocalUpdateModal(item)"
|
||||
>
|
||||
<a-icon
|
||||
type="file"
|
||||
style="margin-right:3px"
|
||||
/>从主题包更新
|
||||
<a-menu-item :key="3" @click="handleOpenLocalUpdateModal(item)">
|
||||
<a-icon type="file" style="margin-right:3px" />从主题包更新
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
|
@ -142,10 +63,7 @@
|
|||
>
|
||||
<div class="custom-tab-wrapper">
|
||||
<a-tabs>
|
||||
<a-tab-pane
|
||||
tab="本地上传"
|
||||
key="1"
|
||||
>
|
||||
<a-tab-pane tab="本地上传" key="1">
|
||||
<FilePondUpload
|
||||
ref="upload"
|
||||
name="file"
|
||||
|
@ -154,34 +72,21 @@
|
|||
:uploadHandler="installModal.local.uploadHandler"
|
||||
@success="handleUploadSucceed"
|
||||
></FilePondUpload>
|
||||
<a-alert
|
||||
type="info"
|
||||
closable
|
||||
>
|
||||
<a-alert type="info" closable>
|
||||
<template slot="message">
|
||||
更多主题请访问:
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://halo.run/themes.html"
|
||||
>https://halo.run/themes</a>
|
||||
<a target="_blank" href="https://halo.run/themes.html">https://halo.run/themes</a>
|
||||
</template>
|
||||
</a-alert>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
tab="远程下载"
|
||||
key="2"
|
||||
>
|
||||
<a-tab-pane tab="远程下载" key="2">
|
||||
<a-form-model
|
||||
ref="remoteInstallForm"
|
||||
:model="installModal.remote"
|
||||
:rules="installModal.remote.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model-item
|
||||
prop="url"
|
||||
label="远程地址:"
|
||||
help="* 支持 Git 仓库地址,ZIP 链接。"
|
||||
>
|
||||
<a-form-model-item prop="url" label="远程地址:" help="* 支持 Git 仓库地址,ZIP 链接。">
|
||||
<a-input v-model="installModal.remote.url" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
|
@ -197,16 +102,10 @@
|
|||
></ReactiveButton>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
<a-alert
|
||||
type="info"
|
||||
closable
|
||||
>
|
||||
<a-alert type="info" closable>
|
||||
<template slot="message">
|
||||
目前仅支持远程 Git 仓库和 ZIP 下载链接。更多主题请访问:
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://halo.run/themes.html"
|
||||
>https://halo.run/themes</a>
|
||||
<a target="_blank" href="https://halo.run/themes.html">https://halo.run/themes</a>
|
||||
</template>
|
||||
</a-alert>
|
||||
</a-tab-pane>
|
||||
|
@ -269,19 +168,19 @@ import themeApi from '@/api/theme'
|
|||
export default {
|
||||
components: {
|
||||
PageView,
|
||||
ThemeSettingDrawer,
|
||||
ThemeSettingDrawer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: {
|
||||
loading: false,
|
||||
data: [],
|
||||
data: []
|
||||
},
|
||||
|
||||
installModal: {
|
||||
visible: false,
|
||||
local: {
|
||||
uploadHandler: themeApi.upload,
|
||||
uploadHandler: themeApi.upload
|
||||
},
|
||||
|
||||
remote: {
|
||||
|
@ -291,15 +190,15 @@ export default {
|
|||
fetchErrored: false,
|
||||
|
||||
rules: {
|
||||
url: [{ required: true, message: '* 远程地址不能为空', trigger: ['change'] }],
|
||||
},
|
||||
},
|
||||
url: [{ required: true, message: '* 远程地址不能为空', trigger: ['change'] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
localUpdateModel: {
|
||||
visible: false,
|
||||
uploadHandler: themeApi.updateByUpload,
|
||||
selected: {},
|
||||
selected: {}
|
||||
},
|
||||
|
||||
themeDeleteModal: {
|
||||
|
@ -307,13 +206,13 @@ export default {
|
|||
deleteSettings: false,
|
||||
selected: {},
|
||||
deleting: false,
|
||||
deleteErrored: false,
|
||||
deleteErrored: false
|
||||
},
|
||||
|
||||
themeSettingDrawer: {
|
||||
visible: false,
|
||||
selected: {},
|
||||
},
|
||||
selected: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -328,7 +227,7 @@ export default {
|
|||
return this.sortedThemes[0]
|
||||
}
|
||||
return null
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.handleListThemes()
|
||||
|
@ -352,7 +251,7 @@ export default {
|
|||
this.list.loading = true
|
||||
themeApi
|
||||
.list()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.list.data = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -398,7 +297,7 @@ export default {
|
|||
this.handleListThemes()
|
||||
},
|
||||
handleRemoteFetching() {
|
||||
this.$refs.remoteInstallForm.validate((valid) => {
|
||||
this.$refs.remoteInstallForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.installModal.remote.fetching = true
|
||||
themeApi
|
||||
|
@ -444,7 +343,7 @@ export default {
|
|||
const hide = _this.$message.loading('更新中...', 0)
|
||||
themeApi
|
||||
.update(item.id)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
_this.$message.success('更新成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -452,7 +351,7 @@ export default {
|
|||
_this.handleListThemes()
|
||||
})
|
||||
},
|
||||
onCancel() {},
|
||||
onCancel() {}
|
||||
})
|
||||
},
|
||||
onThemeInstallModalClose() {
|
||||
|
@ -473,7 +372,7 @@ export default {
|
|||
this.themeDeleteModal.visible = false
|
||||
this.themeDeleteModal.deleteSettings = false
|
||||
this.themeDeleteModal.selected = {}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
|
||||
<a-form-model
|
||||
labelAlign="left"
|
||||
ref="menuForm"
|
||||
|
@ -9,82 +8,28 @@
|
|||
@keyup.enter.native="handleCreateOrUpdateMenu"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="名称"
|
||||
prop="name"
|
||||
help="* 页面上所显示的名称"
|
||||
>
|
||||
<a-input
|
||||
v-model="menuModel.name"
|
||||
autoFocus
|
||||
/>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="12" :xs="12">
|
||||
<a-form-model-item label="名称" prop="name" help="* 页面上所显示的名称">
|
||||
<a-input v-model="menuModel.name" autoFocus />
|
||||
</a-form-model-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="地址"
|
||||
prop="url"
|
||||
help="* 菜单的地址"
|
||||
>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="12" :xs="12">
|
||||
<a-form-model-item label="地址" prop="url" help="* 菜单的地址">
|
||||
<a-input v-model="menuModel.url" />
|
||||
</a-form-model-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="图标"
|
||||
prop="icon"
|
||||
help="* 请根据主题的支持情况选填"
|
||||
>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="12" :xs="12">
|
||||
<a-form-model-item label="图标" prop="icon" help="* 请根据主题的支持情况选填">
|
||||
<a-input v-model="menuModel.icon" />
|
||||
</a-form-model-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="打开方式"
|
||||
prop="target"
|
||||
>
|
||||
<a-radio-group
|
||||
v-model="menuModel.target"
|
||||
:options="targets"
|
||||
/>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="12" :xs="12">
|
||||
<a-form-model-item label="打开方式" prop="target">
|
||||
<a-radio-group v-model="menuModel.target" :options="targets" />
|
||||
</a-form-model-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="12"
|
||||
>
|
||||
<a-form-model-item
|
||||
label=" "
|
||||
:colon="false"
|
||||
>
|
||||
<a-col :xl="8" :lg="8" :md="12" :sm="12" :xs="12">
|
||||
<a-form-model-item label=" " :colon="false">
|
||||
<a-space>
|
||||
<ReactiveButton
|
||||
type="primary"
|
||||
|
@ -109,27 +54,27 @@ import menuApi from '@/api/menu'
|
|||
const targets = [
|
||||
{
|
||||
value: '_self',
|
||||
label: '当前窗口',
|
||||
label: '当前窗口'
|
||||
},
|
||||
{
|
||||
value: '_blank',
|
||||
label: '新窗口',
|
||||
},
|
||||
label: '新窗口'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'MenuForm',
|
||||
model: {
|
||||
prop: 'menu',
|
||||
event: 'input',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
menu: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
menuModel: {
|
||||
|
@ -138,11 +83,11 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
},
|
||||
}
|
||||
},
|
||||
isUpdateMode() {
|
||||
return !!this.menuModel.id
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -151,23 +96,23 @@ export default {
|
|||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '* 菜单名称不能为空', trigger: ['change'] },
|
||||
{ max: 50, message: '* 菜单名称的字符长度不能超过 50', trigger: ['change'] },
|
||||
{ max: 50, message: '* 菜单名称的字符长度不能超过 50', trigger: ['change'] }
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: '* 菜单地址不能为空', trigger: ['change'] },
|
||||
{ max: 1023, message: '* 菜单地址的字符长度不能超过 1023', trigger: ['change'] },
|
||||
{ max: 1023, message: '* 菜单地址的字符长度不能超过 1023', trigger: ['change'] }
|
||||
],
|
||||
icon: [{ max: 50, message: '* 菜单图标的字符长度不能超过 50', trigger: ['change'] }],
|
||||
icon: [{ max: 50, message: '* 菜单图标的字符长度不能超过 50', trigger: ['change'] }]
|
||||
},
|
||||
saving: false,
|
||||
errored: false,
|
||||
},
|
||||
errored: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCreateOrUpdateMenu() {
|
||||
const _this = this
|
||||
_this.$refs.menuForm.validate((valid) => {
|
||||
_this.$refs.menuForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.saving = true
|
||||
if (_this.isUpdateMode) {
|
||||
|
@ -207,7 +152,7 @@ export default {
|
|||
},
|
||||
handleCancel() {
|
||||
this.$emit('cancel')
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model="visible"
|
||||
title="从系统预设链接添加菜单"
|
||||
:width="1024"
|
||||
:bodyStyle="{ padding: '0 24px 24px' }"
|
||||
>
|
||||
<a-modal v-model="visible" title="从系统预设链接添加菜单" :width="1024" :bodyStyle="{ padding: '0 24px 24px' }">
|
||||
<template slot="footer">
|
||||
<a-button @click="handleCancel">
|
||||
取消
|
||||
|
@ -25,110 +20,61 @@
|
|||
<a-spin :spinning="loading">
|
||||
<div class="custom-tab-wrapper">
|
||||
<a-tabs default-active-key="1">
|
||||
<a-tab-pane
|
||||
key="1"
|
||||
tab="分类目录"
|
||||
force-render
|
||||
>
|
||||
<a-tab-pane key="1" tab="分类目录" force-render>
|
||||
<a-list item-layout="horizontal">
|
||||
<a-list-item
|
||||
v-for="(category,index) in categories"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item v-for="(category, index) in categories" :key="index">
|
||||
<a-list-item-meta>
|
||||
<span slot="title">{{ category.name }}</span>
|
||||
<span slot="description">{{ category.fullPath }}</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="text-base"
|
||||
>
|
||||
<a-icon
|
||||
type="plus-circle"
|
||||
@click="handleInsertPre(category.name,category.fullPath)"
|
||||
/>
|
||||
<a href="javascript:void(0);" class="text-base">
|
||||
<a-icon type="plus-circle" @click="handleInsertPre(category.name, category.fullPath)" />
|
||||
</a>
|
||||
</template>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="2"
|
||||
tab="标签"
|
||||
>
|
||||
<a-tab-pane key="2" tab="标签">
|
||||
<a-list item-layout="horizontal">
|
||||
<a-list-item
|
||||
v-for="(tag,index) in tags"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item v-for="(tag, index) in tags" :key="index">
|
||||
<a-list-item-meta>
|
||||
<span slot="title">{{ tag.name }}</span>
|
||||
<span slot="description">{{ tag.fullPath }}</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="text-base"
|
||||
>
|
||||
<a-icon
|
||||
type="plus-circle"
|
||||
@click="handleInsertPre(tag.name,tag.fullPath)"
|
||||
/>
|
||||
<a href="javascript:void(0);" class="text-base">
|
||||
<a-icon type="plus-circle" @click="handleInsertPre(tag.name, tag.fullPath)" />
|
||||
</a>
|
||||
</template>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="3"
|
||||
tab="独立页面"
|
||||
>
|
||||
<a-tab-pane key="3" tab="独立页面">
|
||||
<a-list item-layout="horizontal">
|
||||
<a-list-item
|
||||
v-for="(item,index) in sheet.independents"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item v-for="(item, index) in sheet.independents" :key="index">
|
||||
<a-list-item-meta>
|
||||
<span slot="title">{{ item.title }}</span>
|
||||
<span slot="description">{{ item.fullPath }}</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="text-base"
|
||||
>
|
||||
<a-icon
|
||||
type="plus-circle"
|
||||
@click="handleInsertPre(item.title,item.fullPath)"
|
||||
/>
|
||||
<a href="javascript:void(0);" class="text-base">
|
||||
<a-icon type="plus-circle" @click="handleInsertPre(item.title, item.fullPath)" />
|
||||
</a>
|
||||
</template>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="4"
|
||||
tab="自定义页面"
|
||||
>
|
||||
<a-tab-pane key="4" tab="自定义页面">
|
||||
<a-list item-layout="horizontal">
|
||||
<a-list-item
|
||||
v-for="(item,index) in sheet.customs.data"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item v-for="(item, index) in sheet.customs.data" :key="index">
|
||||
<a-list-item-meta>
|
||||
<span slot="title">{{ item.title }}</span>
|
||||
<span slot="description">{{ item.fullPath }}</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="text-base"
|
||||
>
|
||||
<a-icon
|
||||
type="plus-circle"
|
||||
@click="handleInsertPre(item.title,item.fullPath)"
|
||||
/>
|
||||
<a href="javascript:void(0);" class="text-base">
|
||||
<a-icon type="plus-circle" @click="handleInsertPre(item.title, item.fullPath)" />
|
||||
</a>
|
||||
</template>
|
||||
</a-list-item>
|
||||
|
@ -147,28 +93,16 @@
|
|||
/>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="5"
|
||||
tab="其他"
|
||||
>
|
||||
<a-tab-pane key="5" tab="其他">
|
||||
<a-list item-layout="horizontal">
|
||||
<a-list-item
|
||||
v-for="(item,index) in otherInternalLinks"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item v-for="(item, index) in otherInternalLinks" :key="index">
|
||||
<a-list-item-meta>
|
||||
<span slot="title">{{ item.name }}</span>
|
||||
<span slot="description">{{ item.url }}</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="text-base"
|
||||
>
|
||||
<a-icon
|
||||
type="plus-circle"
|
||||
@click="handleInsertPre(item.name,item.url)"
|
||||
/>
|
||||
<a href="javascript:void(0);" class="text-base">
|
||||
<a-icon type="plus-circle" @click="handleInsertPre(item.name, item.url)" />
|
||||
</a>
|
||||
</template>
|
||||
</a-list-item>
|
||||
|
@ -181,26 +115,15 @@
|
|||
<a-col :span="12">
|
||||
<div class="custom-tab-wrapper">
|
||||
<a-tabs default-active-key="1">
|
||||
<a-tab-pane
|
||||
key="1"
|
||||
tab="备选"
|
||||
force-render
|
||||
>
|
||||
<a-tab-pane key="1" tab="备选" force-render>
|
||||
<a-list item-layout="horizontal">
|
||||
<a-list-item
|
||||
v-for="(menu,index) in menus"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item v-for="(menu, index) in menus" :key="index">
|
||||
<a-list-item-meta>
|
||||
<span slot="title">{{ menu.name }}</span>
|
||||
<span slot="description">{{ menu.url }}</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="text-base"
|
||||
@click="handleRemovePre(index)"
|
||||
>
|
||||
<a href="javascript:void(0);" class="text-base" @click="handleRemovePre(index)">
|
||||
<a-icon type="close-circle" />
|
||||
</a>
|
||||
</template>
|
||||
|
@ -225,12 +148,12 @@ export default {
|
|||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
team: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -246,18 +169,18 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
size: 10,
|
||||
sort: null,
|
||||
},
|
||||
},
|
||||
sort: null
|
||||
}
|
||||
}
|
||||
},
|
||||
loading: false,
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
saveErrored: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -267,7 +190,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
},
|
||||
}
|
||||
},
|
||||
otherInternalLinks() {
|
||||
const options = this.options
|
||||
|
@ -275,30 +198,30 @@ export default {
|
|||
return [
|
||||
{
|
||||
name: '分类目录',
|
||||
url: `${options.blog_url}/${options.categories_prefix}${pathSuffix}`,
|
||||
url: `${options.blog_url}/${options.categories_prefix}${pathSuffix}`
|
||||
},
|
||||
{
|
||||
name: '标签',
|
||||
url: `${options.blog_url}/${options.tags_prefix}${pathSuffix}`,
|
||||
url: `${options.blog_url}/${options.tags_prefix}${pathSuffix}`
|
||||
},
|
||||
{
|
||||
name: '文章归档',
|
||||
url: `${options.blog_url}/${options.archives_prefix}${pathSuffix}`,
|
||||
url: `${options.blog_url}/${options.archives_prefix}${pathSuffix}`
|
||||
},
|
||||
{
|
||||
name: 'RSS',
|
||||
url: `${options.blog_url}/atom.xml`,
|
||||
url: `${options.blog_url}/atom.xml`
|
||||
},
|
||||
{
|
||||
name: '网站地图',
|
||||
url: `${options.blog_url}/sitemap.xml`,
|
||||
url: `${options.blog_url}/sitemap.xml`
|
||||
},
|
||||
{
|
||||
name: '网站地图',
|
||||
url: `${options.blog_url}/sitemap.html`,
|
||||
},
|
||||
url: `${options.blog_url}/sitemap.html`
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(value) {
|
||||
|
@ -306,13 +229,13 @@ export default {
|
|||
this.handleFetchAll()
|
||||
this.handleListSheets()
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleFetchAll() {
|
||||
this.loading = true
|
||||
Promise.all([optionApi.listAll(), categoryApi.listAll(true), tagApi.listAll(true), sheetApi.listIndependent()])
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.options = response[0].data.data
|
||||
this.categories = response[1].data.data
|
||||
this.tags = response[2].data.data
|
||||
|
@ -328,7 +251,7 @@ export default {
|
|||
this.sheet.customs.queryParam.page = this.sheet.customs.pagination.page - 1
|
||||
this.sheet.customs.queryParam.size = this.sheet.customs.pagination.size
|
||||
this.sheet.customs.queryParam.sort = this.sheet.customs.pagination.sort
|
||||
sheetApi.list(this.sheet.customs.queryParam).then((response) => {
|
||||
sheetApi.list(this.sheet.customs.queryParam).then(response => {
|
||||
this.sheet.customs.data = response.data.data.content
|
||||
this.sheet.customs.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -342,7 +265,7 @@ export default {
|
|||
this.menus.push({
|
||||
name: name,
|
||||
url: url,
|
||||
team: this.team,
|
||||
team: this.team
|
||||
})
|
||||
},
|
||||
handleRemovePre(index) {
|
||||
|
@ -372,7 +295,7 @@ export default {
|
|||
} else {
|
||||
this.handleCancel()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -12,83 +12,53 @@
|
|||
handle=".title"
|
||||
>
|
||||
<transition-group>
|
||||
<div
|
||||
:key="item.id"
|
||||
v-for="(item) in realValue"
|
||||
>
|
||||
<div :key="item.id" v-for="item in realValue">
|
||||
<a-list-item class="cursor-pointer menu-item">
|
||||
<a-list-item-meta>
|
||||
<span
|
||||
slot="title"
|
||||
class="title cursor-move inline-block font-bold"
|
||||
>{{ item.name }}
|
||||
<a-tooltip
|
||||
title="外部链接"
|
||||
v-if="item.target==='_blank'"
|
||||
>
|
||||
<span slot="title" class="inline-block font-bold cursor-move title"
|
||||
>{{ item.name }}
|
||||
<a-tooltip title="外部链接" v-if="item.target === '_blank'">
|
||||
<a-icon type="link" />
|
||||
</a-tooltip>
|
||||
{{ item.formVisible?'(正在编辑)':'' }}
|
||||
{{ item.formVisible ? '(正在编辑)' : '' }}
|
||||
</span>
|
||||
<span
|
||||
slot="description"
|
||||
class="inline-block"
|
||||
>
|
||||
<a
|
||||
:href="item.url"
|
||||
target="_blank"
|
||||
class="ant-anchor-link-title"
|
||||
> {{ item.url }} </a>
|
||||
<span slot="description" class="inline-block">
|
||||
<a :href="item.url" target="_blank" class="ant-anchor-link-title"> {{ item.url }} </a>
|
||||
</span>
|
||||
</a-list-item-meta>
|
||||
<template slot="actions">
|
||||
<a
|
||||
v-if="!item.formVisible"
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenEditForm(item)"
|
||||
>
|
||||
<a v-if="!item.formVisible" href="javascript:void(0);" @click="handleOpenEditForm(item)">
|
||||
编辑
|
||||
</a>
|
||||
<a
|
||||
v-else
|
||||
href="javascript:void(0);"
|
||||
@click="handleCloseCreateMenuForm(item)"
|
||||
>
|
||||
<a v-else href="javascript:void(0);" @click="handleCloseCreateMenuForm(item)">
|
||||
取消编辑
|
||||
</a>
|
||||
</template>
|
||||
<template slot="actions">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleDelete(item.id)"
|
||||
>删除</a>
|
||||
<a href="javascript:void(0);" @click="handleDelete(item.id)">删除</a>
|
||||
</template>
|
||||
<template
|
||||
slot="actions"
|
||||
v-if="excludedTeams && excludedTeams.length>0"
|
||||
>
|
||||
<template slot="actions" v-if="excludedTeams && excludedTeams.length > 0">
|
||||
<a-dropdown :trigger="['click']">
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@click="e => e.preventDefault()"
|
||||
>
|
||||
<a class="ant-dropdown-link" @click="e => e.preventDefault()">
|
||||
更多
|
||||
<a-icon type="down" />
|
||||
</a>
|
||||
<a-menu slot="overlay">
|
||||
<a-sub-menu title="移动到分组">
|
||||
<a-menu-item
|
||||
v-for="(team,index) in excludedTeams"
|
||||
v-for="(team, index) in excludedTeams"
|
||||
:key="index"
|
||||
@click="handleMoveMenu(item,team)"
|
||||
>{{ team===''?'未分组':team }}</a-menu-item>
|
||||
@click="handleMoveMenu(item, team)"
|
||||
>{{ team === '' ? '未分组' : team }}</a-menu-item
|
||||
>
|
||||
</a-sub-menu>
|
||||
<a-sub-menu title="复制到分组">
|
||||
<a-menu-item
|
||||
v-for="(team,index) in excludedTeams"
|
||||
v-for="(team, index) in excludedTeams"
|
||||
:key="index"
|
||||
@click="handleCopyMenu(item,team)"
|
||||
>{{ team===''?'未分组':team }}</a-menu-item>
|
||||
@click="handleCopyMenu(item, team)"
|
||||
>{{ team === '' ? '未分组' : team }}</a-menu-item
|
||||
>
|
||||
</a-sub-menu>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
|
@ -100,15 +70,8 @@
|
|||
@succeed="handleUpdateMenuSucceed(item)"
|
||||
@cancel="handleCloseCreateMenuForm(item)"
|
||||
/>
|
||||
<div
|
||||
class="a-list-nested"
|
||||
style="margin-left: 44px;"
|
||||
>
|
||||
<MenuTreeNode
|
||||
:list="item.children"
|
||||
:excludedTeams="excludedTeams"
|
||||
@reload="onReloadEmit"
|
||||
/>
|
||||
<div class="a-list-nested" style="margin-left: 44px;">
|
||||
<MenuTreeNode :list="item.children" :excludedTeams="excludedTeams" @reload="onReloadEmit" />
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
|
@ -127,28 +90,28 @@ export default {
|
|||
name: 'MenuTreeNode',
|
||||
components: {
|
||||
draggable,
|
||||
MenuForm,
|
||||
MenuForm
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
required: false,
|
||||
type: Array,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
list: {
|
||||
required: false,
|
||||
type: Array,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
excludedTeams: {
|
||||
required: false,
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isDragging: false,
|
||||
isDragging: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -159,12 +122,12 @@ export default {
|
|||
ghostClass: 'ghost',
|
||||
chosenClass: 'chosen',
|
||||
dragClass: 'drag',
|
||||
emptyInsertThreshold: 20,
|
||||
emptyInsertThreshold: 20
|
||||
}
|
||||
},
|
||||
realValue() {
|
||||
return this.value ? this.value : this.list
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
emitter(value) {
|
||||
|
@ -179,7 +142,7 @@ export default {
|
|||
menuApi.delete(id).finally(() => {
|
||||
_this.onReloadEmit()
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
handleOpenEditForm(item) {
|
||||
|
@ -198,7 +161,7 @@ export default {
|
|||
menu.parentId = 0
|
||||
menu.priority = 0
|
||||
menu.id = null
|
||||
menuApi.create(menu).then((response) => {
|
||||
menuApi.create(menu).then(() => {
|
||||
this.$emit('reload')
|
||||
})
|
||||
},
|
||||
|
@ -207,14 +170,14 @@ export default {
|
|||
menu.team = team
|
||||
menu.parentId = 0
|
||||
menu.priority = 0
|
||||
menuApi.update(menu.id, menu).then((response) => {
|
||||
menuApi.update(menu.id, menu).then(() => {
|
||||
this.$emit('reload')
|
||||
})
|
||||
},
|
||||
onReloadEmit() {
|
||||
this.$emit('reload')
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
|
|
|
@ -9,81 +9,27 @@
|
|||
:visible="visible"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
:gutter="12"
|
||||
type="flex"
|
||||
>
|
||||
<a-col
|
||||
:xl="12"
|
||||
:lg="12"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
v-if="!viewMode"
|
||||
>
|
||||
<a-row :gutter="12" type="flex">
|
||||
<a-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24" v-if="!viewMode">
|
||||
<a-card :bordered="false">
|
||||
<img
|
||||
:alt="theme.name"
|
||||
:src="theme.screenshots"
|
||||
slot="cover"
|
||||
>
|
||||
<img :alt="theme.name" :src="theme.screenshots" slot="cover" />
|
||||
<a-card-meta :description="theme.description">
|
||||
<template slot="title">
|
||||
<a
|
||||
:href="author.website"
|
||||
target="_blank"
|
||||
>{{ author.name }}</a>
|
||||
<a :href="author.website" target="_blank">{{ author.name }}</a>
|
||||
</template>
|
||||
<a-avatar
|
||||
v-if="theme.logo"
|
||||
:src="theme.logo"
|
||||
size="large"
|
||||
slot="avatar"
|
||||
/>
|
||||
<a-avatar
|
||||
v-else
|
||||
size="large"
|
||||
slot="avatar"
|
||||
>{{ author.name }}</a-avatar>
|
||||
<a-avatar v-if="theme.logo" :src="theme.logo" size="large" slot="avatar" />
|
||||
<a-avatar v-else size="large" slot="avatar">{{ author.name }}</a-avatar>
|
||||
</a-card-meta>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="formColValue"
|
||||
:lg="formColValue"
|
||||
:md="formColValue"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
style="padding-bottom: 50px;"
|
||||
>
|
||||
<a-col :xl="formColValue" :lg="formColValue" :md="formColValue" :sm="24" :xs="24" style="padding-bottom: 50px;">
|
||||
<a-spin :spinning="settingLoading">
|
||||
<div
|
||||
class="card-container"
|
||||
v-if="themeConfigurations.length>0"
|
||||
>
|
||||
<a-tabs
|
||||
type="card"
|
||||
defaultActiveKey="0"
|
||||
>
|
||||
<a-tab-pane
|
||||
v-for="(group, index) in themeConfigurations"
|
||||
:key="index.toString()"
|
||||
:tab="group.label"
|
||||
>
|
||||
<a-form
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-item
|
||||
v-for="(item, index1) in group.items"
|
||||
:label="item.label + ':'"
|
||||
:key="index1"
|
||||
>
|
||||
<p
|
||||
v-if="item.description && item.description!=''"
|
||||
slot="help"
|
||||
v-html="item.description"
|
||||
></p>
|
||||
<div class="card-container" v-if="themeConfigurations.length > 0">
|
||||
<a-tabs type="card" defaultActiveKey="0">
|
||||
<a-tab-pane v-for="(group, index) in themeConfigurations" :key="index.toString()" :tab="group.label">
|
||||
<a-form layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-item v-for="(item, index1) in group.items" :label="item.label + ':'" :key="index1">
|
||||
<p v-if="item.description && item.description != ''" slot="help" v-html="item.description"></p>
|
||||
<a-input
|
||||
v-model="themeSettings[item.name]"
|
||||
:defaultValue="item.defaultValue"
|
||||
|
@ -103,22 +49,18 @@
|
|||
v-model="themeSettings[item.name]"
|
||||
v-else-if="item.type == 'RADIO'"
|
||||
>
|
||||
<a-radio
|
||||
v-for="(option, index2) in item.options"
|
||||
:key="index2"
|
||||
:value="option.value"
|
||||
>{{ option.label }}</a-radio>
|
||||
<a-radio v-for="(option, index2) in item.options" :key="index2" :value="option.value">{{
|
||||
option.label
|
||||
}}</a-radio>
|
||||
</a-radio-group>
|
||||
<a-select
|
||||
v-model="themeSettings[item.name]"
|
||||
:defaultValue="item.defaultValue"
|
||||
v-else-if="item.type == 'SELECT'"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="option in item.options"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>{{ option.label }}</a-select-option>
|
||||
<a-select-option v-for="option in item.options" :key="option.value" :value="option.value">{{
|
||||
option.label
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
<verte
|
||||
picker="square"
|
||||
|
@ -133,11 +75,7 @@
|
|||
:defaultValue="item.defaultValue"
|
||||
v-else-if="item.type == 'ATTACHMENT'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="handleShowSelectAttachment(item.name)"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click="handleShowSelectAttachment(item.name)">
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
|
@ -163,26 +101,12 @@
|
|||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<a-empty
|
||||
v-if="themeConfigurations.length <=0 && !settingLoading"
|
||||
description="当前主题暂无设置选项"
|
||||
/>
|
||||
<a-empty v-if="themeConfigurations.length <= 0 && !settingLoading" description="当前主题暂无设置选项" />
|
||||
</a-spin>
|
||||
</a-col>
|
||||
|
||||
<a-col
|
||||
:xl="20"
|
||||
:lg="20"
|
||||
:md="20"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
v-if="viewMode"
|
||||
style="padding-bottom: 50px;"
|
||||
>
|
||||
<a-card
|
||||
:bordered="true"
|
||||
:bodyStyle="{ padding: 0}"
|
||||
>
|
||||
<a-col :xl="20" :lg="20" :md="20" :sm="24" :xs="24" v-if="viewMode" style="padding-bottom: 50px;">
|
||||
<a-card :bordered="true" :bodyStyle="{ padding: 0 }">
|
||||
<iframe
|
||||
id="themeViewIframe"
|
||||
title="主题预览"
|
||||
|
@ -191,8 +115,9 @@
|
|||
border="0"
|
||||
:src="options.blog_url"
|
||||
width="100%"
|
||||
:height="clientHeight-165"
|
||||
> </iframe>
|
||||
:height="clientHeight - 165"
|
||||
>
|
||||
</iframe>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -203,26 +128,18 @@
|
|||
title="选择附件"
|
||||
/>
|
||||
|
||||
<footer-tool-bar
|
||||
v-if="themeConfigurations.length>0"
|
||||
class="w-full"
|
||||
>
|
||||
<footer-tool-bar v-if="themeConfigurations.length > 0" class="w-full">
|
||||
<a-space>
|
||||
<a-button
|
||||
v-if="!this.isMobile() && theme.activated && viewMode"
|
||||
type="primary"
|
||||
@click="toggleViewMode"
|
||||
ghost
|
||||
>普通模式</a-button>
|
||||
<a-button
|
||||
v-else-if="!this.isMobile() && theme.activated && !viewMode"
|
||||
type="dashed"
|
||||
@click="toggleViewMode"
|
||||
>预览模式</a-button>
|
||||
<a-button v-if="!this.isMobile() && theme.activated && viewMode" type="primary" @click="toggleViewMode" ghost
|
||||
>普通模式</a-button
|
||||
>
|
||||
<a-button v-else-if="!this.isMobile() && theme.activated && !viewMode" type="dashed" @click="toggleViewMode"
|
||||
>预览模式</a-button
|
||||
>
|
||||
<ReactiveButton
|
||||
type="primary"
|
||||
@click="handleSaveSettings"
|
||||
@callback="saveErrored=false"
|
||||
@callback="saveErrored = false"
|
||||
:loading="saving"
|
||||
:errored="saveErrored"
|
||||
text="保存"
|
||||
|
@ -316,7 +233,7 @@ export default {
|
|||
this.saving = true
|
||||
themeApi
|
||||
.saveSettings(this.theme.id, this.themeSettings)
|
||||
.then(response => {
|
||||
.then(() => {
|
||||
if (this.viewMode) {
|
||||
document.getElementById('themeViewIframe').contentWindow.location.reload(true)
|
||||
}
|
||||
|
|
|
@ -1,82 +1,30 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="10"
|
||||
:lg="10"
|
||||
:md="10"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:title="title"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-form-model
|
||||
ref="categoryForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="horizontal"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="名称:"
|
||||
help="* 页面上所显示的名称"
|
||||
prop="name"
|
||||
>
|
||||
<a-col :xl="10" :lg="10" :md="10" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :title="title" :bodyStyle="{ padding: '16px' }">
|
||||
<a-form-model ref="categoryForm" :model="form.model" :rules="form.rules" layout="horizontal">
|
||||
<a-form-model-item label="名称:" help="* 页面上所显示的名称" prop="name">
|
||||
<a-input v-model="form.model.name" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="别名:"
|
||||
help="* 一般为单个分类页面的标识,最好为英文"
|
||||
prop="slug"
|
||||
>
|
||||
<a-form-model-item label="别名:" help="* 一般为单个分类页面的标识,最好为英文" prop="slug">
|
||||
<a-input v-model="form.model.slug" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="上级目录:"
|
||||
prop="parentId"
|
||||
>
|
||||
<category-select-tree
|
||||
:categories="table.data"
|
||||
v-model="form.model.parentId"
|
||||
/>
|
||||
<a-form-model-item label="上级目录:" prop="parentId">
|
||||
<category-select-tree :categories="table.data" v-model="form.model.parentId" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="封面图:"
|
||||
help="* 在分类页面可展示,需要主题支持"
|
||||
prop="thumbnail"
|
||||
>
|
||||
<a-form-model-item label="封面图:" help="* 在分类页面可展示,需要主题支持" prop="thumbnail">
|
||||
<a-input v-model="form.model.thumbnail">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="thumbnailDrawer.visible = true"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click="thumbnailDrawer.visible = true">
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="密码:"
|
||||
help="* 分类密码"
|
||||
prop="password"
|
||||
>
|
||||
<a-input-password
|
||||
v-model="form.model.password"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-form-model-item label="密码:" help="* 分类密码" prop="password">
|
||||
<a-input-password v-model="form.model.password" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="描述:"
|
||||
help="* 分类描述,需要主题支持"
|
||||
prop="description"
|
||||
>
|
||||
<a-input
|
||||
type="textarea"
|
||||
v-model="form.model.description"
|
||||
:autoSize="{ minRows: 3 }"
|
||||
/>
|
||||
<a-form-model-item label="描述:" help="* 分类描述,需要主题支持" prop="description">
|
||||
<a-input type="textarea" v-model="form.model.description" :autoSize="{ minRows: 3 }" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
<ReactiveButton
|
||||
|
@ -101,27 +49,14 @@
|
|||
loadedText="更新成功"
|
||||
erroredText="更新失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="form.model = {}"
|
||||
>返回添加</a-button>
|
||||
<a-button type="dashed" @click="form.model = {}">返回添加</a-button>
|
||||
</a-button-group>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="14"
|
||||
:lg="14"
|
||||
:md="14"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
title="分类列表"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-col :xl="14" :lg="14" :md="14" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card title="分类列表" :bodyStyle="{ padding: '16px' }">
|
||||
<!-- Mobile -->
|
||||
<a-list
|
||||
v-if="isMobile()"
|
||||
|
@ -131,29 +66,19 @@
|
|||
:dataSource="table.data"
|
||||
:loading="table.loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<span>
|
||||
<a-icon type="form" />
|
||||
{{ item.postCount }}
|
||||
</span>
|
||||
<a-dropdown
|
||||
placement="topLeft"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a-dropdown placement="topLeft" :trigger="['click']">
|
||||
<span>
|
||||
<a-icon type="bars" />
|
||||
</span>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="form.model = item"
|
||||
>编辑</a>
|
||||
<a href="javascript:void(0);" @click="form.model = item">编辑</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
|
@ -176,9 +101,8 @@
|
|||
slot="title"
|
||||
style="max-width: 300px;display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
>
|
||||
{{ item.name }}{{ item.password?'(加密)':'' }}
|
||||
{{ item.name }}{{ item.password ? '(加密)' : '' }}
|
||||
</span>
|
||||
|
||||
</a-list-item-meta>
|
||||
<span>
|
||||
{{ item.description }}
|
||||
|
@ -194,34 +118,24 @@
|
|||
:loading="table.loading"
|
||||
:scrollToFirstRowOnChange="true"
|
||||
>
|
||||
<span
|
||||
slot="name"
|
||||
slot-scope="text,record"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
{{ record.name }}{{ record.password?'(加密)':'' }}
|
||||
<span slot="name" slot-scope="text, record" class="cursor-pointer">
|
||||
{{ record.name }}{{ record.password ? '(加密)' : '' }}
|
||||
</span>
|
||||
<span
|
||||
slot="postCount"
|
||||
slot-scope="text,record"
|
||||
slot-scope="text, record"
|
||||
class="cursor-pointer"
|
||||
@click="handleQueryCategoryPosts(record)"
|
||||
>
|
||||
<a-badge
|
||||
:count="record.postCount"
|
||||
:numberStyle="{backgroundColor: '#00e0ff'} "
|
||||
:numberStyle="{ backgroundColor: '#00e0ff' }"
|
||||
:showZero="true"
|
||||
:overflowCount="9999"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="form.model = record"
|
||||
>编辑</a>
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<a href="javascript:void(0);" @click="form.model = record">编辑</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
:title="'你确定要删除【' + record.name + '】分类?'"
|
||||
|
@ -256,23 +170,23 @@ const columns = [
|
|||
title: '名称',
|
||||
ellipsis: true,
|
||||
dataIndex: 'name',
|
||||
scopedSlots: { customRender: 'name' },
|
||||
scopedSlots: { customRender: 'name' }
|
||||
},
|
||||
{
|
||||
title: '别名',
|
||||
ellipsis: true,
|
||||
dataIndex: 'slug',
|
||||
dataIndex: 'slug'
|
||||
},
|
||||
{
|
||||
title: '文章数',
|
||||
dataIndex: 'postCount',
|
||||
scopedSlots: { customRender: 'postCount' },
|
||||
scopedSlots: { customRender: 'postCount' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
|
@ -283,7 +197,7 @@ export default {
|
|||
table: {
|
||||
columns,
|
||||
data: [],
|
||||
loading: false,
|
||||
loading: false
|
||||
},
|
||||
form: {
|
||||
model: {},
|
||||
|
@ -292,16 +206,16 @@ export default {
|
|||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '* 分类名称不能为空', trigger: ['change'] },
|
||||
{ max: 255, message: '* 分类名称的字符长度不能超过 255', trigger: ['change'] },
|
||||
{ max: 255, message: '* 分类名称的字符长度不能超过 255', trigger: ['change'] }
|
||||
],
|
||||
slug: [{ max: 255, message: '* 分类别名的字符长度不能超过 255', trigger: ['change'] }],
|
||||
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change'] }],
|
||||
description: [{ max: 100, message: '* 分类描述的字符长度不能超过 100', trigger: ['change'] }],
|
||||
},
|
||||
description: [{ max: 100, message: '* 分类描述的字符长度不能超过 100', trigger: ['change'] }]
|
||||
}
|
||||
},
|
||||
thumbnailDrawer: {
|
||||
visible: false,
|
||||
},
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -313,7 +227,7 @@ export default {
|
|||
},
|
||||
isUpdateMode() {
|
||||
return !!this.form.model.id
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.handleListCategories()
|
||||
|
@ -323,7 +237,7 @@ export default {
|
|||
this.table.loading = true
|
||||
categoryApi
|
||||
.listAll(true)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.table.data = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -335,7 +249,7 @@ export default {
|
|||
handleDeleteCategory(id) {
|
||||
categoryApi
|
||||
.delete(id)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
this.form.model = {}
|
||||
})
|
||||
|
@ -349,7 +263,7 @@ export default {
|
|||
*/
|
||||
handleCreateOrUpdateCategory() {
|
||||
const _this = this
|
||||
_this.$refs.categoryForm.validate((valid) => {
|
||||
_this.$refs.categoryForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.saving = true
|
||||
if (_this.isUpdateMode) {
|
||||
|
@ -393,7 +307,7 @@ export default {
|
|||
},
|
||||
handleQueryCategoryPosts(category) {
|
||||
this.$router.push({ name: 'PostList', query: { categoryId: category.id } })
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<page-view
|
||||
affix
|
||||
:title="postToStage.title?postToStage.title:'新文章'"
|
||||
>
|
||||
<page-view affix :title="postToStage.title ? postToStage.title : '新文章'">
|
||||
<template slot="extra">
|
||||
<a-space>
|
||||
<ReactiveButton
|
||||
|
@ -15,28 +12,15 @@
|
|||
loadedText="保存成功"
|
||||
erroredText="保存失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
@click="handlePreview"
|
||||
:loading="previewSaving"
|
||||
>预览</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="postSettingVisible = true"
|
||||
>发布</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="attachmentDrawerVisible = true"
|
||||
>附件库</a-button>
|
||||
<a-button @click="handlePreview" :loading="previewSaving">预览</a-button>
|
||||
<a-button type="primary" @click="postSettingVisible = true">发布</a-button>
|
||||
<a-button type="dashed" @click="attachmentDrawerVisible = true">附件库</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="24">
|
||||
<div class="mb-4">
|
||||
<a-input
|
||||
v-model="postToStage.title"
|
||||
size="large"
|
||||
placeholder="请输入文章标题"
|
||||
/>
|
||||
<a-input v-model="postToStage.title" size="large" placeholder="请输入文章标题" />
|
||||
</div>
|
||||
|
||||
<div id="editor">
|
||||
|
@ -91,7 +75,7 @@ export default {
|
|||
PostSettingDrawer,
|
||||
AttachmentDrawer,
|
||||
MarkdownEditor,
|
||||
PageView,
|
||||
PageView
|
||||
// RichTextEditor
|
||||
},
|
||||
data() {
|
||||
|
@ -105,15 +89,15 @@ export default {
|
|||
contentChanges: 0,
|
||||
draftSaving: false,
|
||||
previewSaving: false,
|
||||
draftSavederrored: false,
|
||||
draftSavederrored: false
|
||||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
// Get post id from query
|
||||
const postId = to.query.postId
|
||||
next((vm) => {
|
||||
next(vm => {
|
||||
if (postId) {
|
||||
postApi.get(postId).then((response) => {
|
||||
postApi.get(postId).then(response => {
|
||||
const post = response.data.data
|
||||
vm.postToStage = post
|
||||
vm.selectedTagIds = post.tagIds
|
||||
|
@ -147,13 +131,13 @@ export default {
|
|||
} else {
|
||||
this.$confirm({
|
||||
title: '当前页面数据未保存,确定要离开吗?',
|
||||
content: (h) => <div style="color:red;">如果离开当面页面,你的数据很可能会丢失!</div>,
|
||||
content: () => <div style="color:red;">如果离开当面页面,你的数据很可能会丢失!</div>,
|
||||
onOk() {
|
||||
next()
|
||||
},
|
||||
onCancel() {
|
||||
next(false)
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -170,16 +154,16 @@ export default {
|
|||
// }
|
||||
},
|
||||
watch: {
|
||||
temporaryContent: function(newValue, oldValue) {
|
||||
temporaryContent(newValue) {
|
||||
if (newValue) {
|
||||
this.contentChanges++
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
temporaryContent() {
|
||||
return this.postToStage.originalContent
|
||||
},
|
||||
}
|
||||
// ...mapGetters(['options'])
|
||||
},
|
||||
methods: {
|
||||
|
@ -195,7 +179,7 @@ export default {
|
|||
if (draftOnly) {
|
||||
postApi
|
||||
.updateDraft(this.postToStage.id, this.postToStage.originalContent)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -209,7 +193,7 @@ export default {
|
|||
} else {
|
||||
postApi
|
||||
.update(this.postToStage.id, this.postToStage, false)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.postToStage = response.data.data
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -226,7 +210,7 @@ export default {
|
|||
// Create the post
|
||||
postApi
|
||||
.create(this.postToStage, false)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.postToStage = response.data.data
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -248,11 +232,11 @@ export default {
|
|||
this.previewSaving = true
|
||||
if (this.postToStage.id) {
|
||||
// Update the post
|
||||
postApi.update(this.postToStage.id, this.postToStage, false).then((response) => {
|
||||
postApi.update(this.postToStage.id, this.postToStage, false).then(response => {
|
||||
this.$log.debug('Updated post', response.data.data)
|
||||
postApi
|
||||
.preview(this.postToStage.id)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -264,12 +248,12 @@ export default {
|
|||
})
|
||||
} else {
|
||||
// Create the post
|
||||
postApi.create(this.postToStage, false).then((response) => {
|
||||
postApi.create(this.postToStage, false).then(response => {
|
||||
this.$log.debug('Created post', response.data.data)
|
||||
this.postToStage = response.data.data
|
||||
postApi
|
||||
.preview(this.postToStage.id)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -298,7 +282,7 @@ export default {
|
|||
},
|
||||
onRefreshPostMetasFromSetting(metas) {
|
||||
this.selectedMetas = metas
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,48 +1,24 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input
|
||||
v-model="queryParam.keyword"
|
||||
@keyup.enter="handleQuery()"
|
||||
/>
|
||||
<a-input v-model="queryParam.keyword" @keyup.enter="handleQuery()" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="文章状态:">
|
||||
<a-select
|
||||
v-model="queryParam.status"
|
||||
placeholder="请选择文章状态"
|
||||
@change="handleQuery()"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option
|
||||
v-for="status in Object.keys(postStatus)"
|
||||
:key="status"
|
||||
:value="status"
|
||||
>{{
|
||||
<a-select v-model="queryParam.status" placeholder="请选择文章状态" @change="handleQuery()" allowClear>
|
||||
<a-select-option v-for="status in Object.keys(postStatus)" :key="status" :value="status">{{
|
||||
postStatus[status].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="分类目录:">
|
||||
<a-select
|
||||
v-model="queryParam.categoryId"
|
||||
|
@ -51,24 +27,17 @@
|
|||
:loading="categoriesLoading"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option
|
||||
v-for="category in categories"
|
||||
:key="category.id"
|
||||
>{{ category.name }}({{ category.postCount }})</a-select-option>
|
||||
<a-select-option v-for="category in categories" :key="category.id"
|
||||
>{{ category.name }}({{ category.postCount }})</a-select-option
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<span class="table-page-search-submitButtons">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleQuery()"
|
||||
>查询</a-button>
|
||||
<a-button type="primary" @click="handleQuery()">查询</a-button>
|
||||
<a-button @click="handleResetParam()">重置</a-button>
|
||||
</a-space>
|
||||
</span>
|
||||
|
@ -79,21 +48,12 @@
|
|||
|
||||
<div class="table-operator">
|
||||
<router-link :to="{ name: 'PostWrite' }">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
>写文章</a-button>
|
||||
<a-button type="primary" icon="plus">写文章</a-button>
|
||||
</router-link>
|
||||
<a-dropdown v-show="queryParam.status != null && queryParam.status != '' && !isMobile()">
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item
|
||||
key="1"
|
||||
v-if="queryParam.status === 'DRAFT' || queryParam.status === 'RECYCLE'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusMore(postStatus.PUBLISHED.value)"
|
||||
>
|
||||
<a-menu-item key="1" v-if="queryParam.status === 'DRAFT' || queryParam.status === 'RECYCLE'">
|
||||
<a href="javascript:void(0);" @click="handleEditStatusMore(postStatus.PUBLISHED.value)">
|
||||
<span>发布</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
|
@ -103,10 +63,7 @@
|
|||
queryParam.status === 'PUBLISHED' || queryParam.status === 'DRAFT' || queryParam.status === 'INTIMATE'
|
||||
"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusMore(postStatus.RECYCLE.value)"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="handleEditStatusMore(postStatus.RECYCLE.value)">
|
||||
<span>移到回收站</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
|
@ -116,21 +73,12 @@
|
|||
queryParam.status === 'RECYCLE' || queryParam.status === 'PUBLISHED' || queryParam.status === 'INTIMATE'
|
||||
"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleEditStatusMore(postStatus.DRAFT.value)"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="handleEditStatusMore(postStatus.DRAFT.value)">
|
||||
<span>草稿</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="4"
|
||||
v-if="queryParam.status === 'RECYCLE' || queryParam.status === 'DRAFT'"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleDeleteMore"
|
||||
>
|
||||
<a-menu-item key="4" v-if="queryParam.status === 'RECYCLE' || queryParam.status === 'DRAFT'">
|
||||
<a href="javascript:void(0);" @click="handleDeleteMore">
|
||||
<span>永久删除</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
|
@ -151,11 +99,7 @@
|
|||
:dataSource="formattedPosts"
|
||||
:loading="postsLoading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<span>
|
||||
<a-icon type="eye" />
|
||||
|
@ -165,19 +109,15 @@
|
|||
<a-icon type="message" />
|
||||
{{ item.commentCount }}
|
||||
</span>
|
||||
<a-dropdown
|
||||
placement="topLeft"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a-dropdown placement="topLeft" :trigger="['click']">
|
||||
<span>
|
||||
<a-icon type="bars" />
|
||||
</span>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item v-if="item.status === 'PUBLISHED' || item.status === 'DRAFT' || item.status === 'INTIMATE'">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleEditClick(item)"
|
||||
>编辑</a>
|
||||
<a-menu-item
|
||||
v-if="item.status === 'PUBLISHED' || item.status === 'DRAFT' || item.status === 'INTIMATE'"
|
||||
>
|
||||
<a href="javascript:;" @click="handleEditClick(item)">编辑</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-else-if="item.status === 'RECYCLE'">
|
||||
<a-popconfirm
|
||||
|
@ -189,7 +129,9 @@
|
|||
<a href="javascript:;">还原</a>
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="item.status === 'PUBLISHED' || item.status === 'DRAFT' || item.status === 'INTIMATE'">
|
||||
<a-menu-item
|
||||
v-if="item.status === 'PUBLISHED' || item.status === 'DRAFT' || item.status === 'INTIMATE'"
|
||||
>
|
||||
<a-popconfirm
|
||||
:title="'你确定要将【' + item.title + '】文章移到回收站?'"
|
||||
@confirm="handleEditStatusClick(item.id, 'RECYCLE')"
|
||||
|
@ -210,21 +152,16 @@
|
|||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="javascript:void(0);"
|
||||
@click="handleShowPostSettings(item)"
|
||||
>设置</a>
|
||||
<a rel="noopener noreferrer" href="javascript:void(0);" @click="handleShowPostSettings(item)"
|
||||
>设置</a
|
||||
>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template slot="extra">
|
||||
<span>
|
||||
<a-badge
|
||||
:status="item.statusProperty.status"
|
||||
:text="item.statusProperty.text"
|
||||
/>
|
||||
<a-badge :status="item.statusProperty.status" :text="item.statusProperty.text" />
|
||||
</span>
|
||||
</template>
|
||||
<a-list-item-meta>
|
||||
|
@ -248,10 +185,7 @@
|
|||
target="_blank"
|
||||
class="no-underline"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="'点击访问【' + item.title + '】'"
|
||||
>{{ item.title }}</a-tooltip>
|
||||
<a-tooltip placement="top" :title="'点击访问【' + item.title + '】'">{{ item.title }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="item.status == 'DRAFT'"
|
||||
|
@ -259,17 +193,9 @@
|
|||
class="no-underline"
|
||||
@click="handlePreview(item.id)"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
:title="'点击预览【' + item.title + '】'"
|
||||
>{{ item.title }}</a-tooltip>
|
||||
<a-tooltip placement="topLeft" :title="'点击预览【' + item.title + '】'">{{ item.title }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else
|
||||
href="javascript:void(0);"
|
||||
class="no-underline"
|
||||
disabled
|
||||
>
|
||||
<a v-else href="javascript:void(0);" class="no-underline" disabled>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
</span>
|
||||
|
@ -283,14 +209,16 @@
|
|||
color="blue"
|
||||
@click="handleSelectCategory(category)"
|
||||
style="margin-bottom: 8px"
|
||||
>{{ category.name }}</a-tag>
|
||||
>{{ category.name }}</a-tag
|
||||
>
|
||||
<br />
|
||||
<a-tag
|
||||
v-for="(tag, tagIndex) in item.tags"
|
||||
:key="'tag_' + tagIndex"
|
||||
color="green"
|
||||
style="margin-bottom: 8px"
|
||||
>{{ tag.name }}</a-tag>
|
||||
>{{ tag.name }}</a-tag
|
||||
>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
||||
|
@ -309,10 +237,7 @@
|
|||
:pagination="false"
|
||||
:scrollToFirstRowOnChange="true"
|
||||
>
|
||||
<span
|
||||
slot="postTitle"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
<span slot="postTitle" slot-scope="text, record">
|
||||
<a-icon
|
||||
type="pushpin"
|
||||
v-if="record.topPriority != 0"
|
||||
|
@ -326,10 +251,7 @@
|
|||
target="_blank"
|
||||
class="no-underline"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="'点击访问【' + text + '】'"
|
||||
>{{ text }}</a-tooltip>
|
||||
<a-tooltip placement="top" :title="'点击访问【' + text + '】'">{{ text }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="record.status == 'DRAFT'"
|
||||
|
@ -337,55 +259,29 @@
|
|||
class="no-underline"
|
||||
@click="handlePreview(record.id)"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
:title="'点击预览【' + text + '】'"
|
||||
>{{ text }}</a-tooltip>
|
||||
<a-tooltip placement="topLeft" :title="'点击预览【' + text + '】'">{{ text }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else
|
||||
href="javascript:void(0);"
|
||||
class="no-underline"
|
||||
disabled
|
||||
>
|
||||
<a v-else href="javascript:void(0);" class="no-underline" disabled>
|
||||
{{ text }}
|
||||
</a>
|
||||
</span>
|
||||
<span
|
||||
slot="status"
|
||||
slot-scope="statusProperty"
|
||||
>
|
||||
<a-badge
|
||||
:status="statusProperty.status"
|
||||
:text="statusProperty.text"
|
||||
/>
|
||||
<span slot="status" slot-scope="statusProperty">
|
||||
<a-badge :status="statusProperty.status" :text="statusProperty.text" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="categories"
|
||||
slot-scope="categoriesOfPost"
|
||||
>
|
||||
<span slot="categories" slot-scope="categoriesOfPost">
|
||||
<a-tag
|
||||
v-for="(category, index) in categoriesOfPost"
|
||||
:key="index"
|
||||
color="blue"
|
||||
@click="handleSelectCategory(category)"
|
||||
style="margin-bottom: 8px;cursor:pointer"
|
||||
>{{
|
||||
category.name
|
||||
}}</a-tag>
|
||||
>{{ category.name }}</a-tag
|
||||
>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="tags"
|
||||
slot-scope="tags"
|
||||
>
|
||||
<a-tag
|
||||
v-for="(tag, index) in tags"
|
||||
:key="index"
|
||||
color="green"
|
||||
style="margin-bottom: 8px"
|
||||
>{{
|
||||
<span slot="tags" slot-scope="tags">
|
||||
<a-tag v-for="(tag, index) in tags" :key="index" color="green" style="margin-bottom: 8px">{{
|
||||
tag.name
|
||||
}}</a-tag>
|
||||
</span>
|
||||
|
@ -404,10 +300,7 @@
|
|||
/>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="visits"
|
||||
slot-scope="visits"
|
||||
>
|
||||
<span slot="visits" slot-scope="visits">
|
||||
<a-badge
|
||||
:count="visits"
|
||||
:numberStyle="{ backgroundColor: '#00e0ff' }"
|
||||
|
@ -416,10 +309,7 @@
|
|||
/>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="createTime"
|
||||
slot-scope="createTime"
|
||||
>
|
||||
<span slot="createTime" slot-scope="createTime">
|
||||
<a-tooltip placement="top">
|
||||
<template slot="title">
|
||||
{{ createTime | moment }}
|
||||
|
@ -428,15 +318,13 @@
|
|||
</a-tooltip>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, post"
|
||||
>
|
||||
<span slot="action" slot-scope="text, post">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleEditClick(post)"
|
||||
v-if="post.status === 'PUBLISHED' || post.status === 'DRAFT' || post.status === 'INTIMATE'"
|
||||
>编辑</a>
|
||||
>编辑</a
|
||||
>
|
||||
<a-popconfirm
|
||||
:title="'你确定要发布【' + post.title + '】文章?'"
|
||||
@confirm="handleEditStatusClick(post.id, 'PUBLISHED')"
|
||||
|
@ -471,10 +359,7 @@
|
|||
|
||||
<a-divider type="vertical" />
|
||||
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleShowPostSettings(post)"
|
||||
>设置</a>
|
||||
<a href="javascript:;" @click="handleShowPostSettings(post)">设置</a>
|
||||
</span>
|
||||
</a-table>
|
||||
<div class="page-wrapper">
|
||||
|
@ -525,8 +410,6 @@ import { mixin, mixinDevice } from '@/mixins/mixin.js'
|
|||
import { PageView } from '@/layouts'
|
||||
import PostSettingDrawer from './components/PostSettingDrawer'
|
||||
import TargetCommentDrawer from '../comment/components/TargetCommentDrawer'
|
||||
import TagSelect from './components/TagSelect'
|
||||
import CategoryTree from './components/CategoryTree'
|
||||
import categoryApi from '@/api/category'
|
||||
import postApi from '@/api/post'
|
||||
|
||||
|
@ -536,57 +419,55 @@ const columns = [
|
|||
dataIndex: 'title',
|
||||
width: '150px',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'postTitle' },
|
||||
scopedSlots: { customRender: 'postTitle' }
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
className: 'status',
|
||||
dataIndex: 'statusProperty',
|
||||
width: '100px',
|
||||
scopedSlots: { customRender: 'status' },
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'categories',
|
||||
scopedSlots: { customRender: 'categories' },
|
||||
scopedSlots: { customRender: 'categories' }
|
||||
},
|
||||
{
|
||||
title: '标签',
|
||||
dataIndex: 'tags',
|
||||
scopedSlots: { customRender: 'tags' },
|
||||
scopedSlots: { customRender: 'tags' }
|
||||
},
|
||||
{
|
||||
title: '评论',
|
||||
width: '70px',
|
||||
dataIndex: 'commentCount',
|
||||
scopedSlots: { customRender: 'commentCount' },
|
||||
scopedSlots: { customRender: 'commentCount' }
|
||||
},
|
||||
{
|
||||
title: '访问',
|
||||
width: '70px',
|
||||
dataIndex: 'visits',
|
||||
scopedSlots: { customRender: 'visits' },
|
||||
scopedSlots: { customRender: 'visits' }
|
||||
},
|
||||
{
|
||||
title: '发布时间',
|
||||
dataIndex: 'createTime',
|
||||
width: '170px',
|
||||
scopedSlots: { customRender: 'createTime' },
|
||||
scopedSlots: { customRender: 'createTime' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: '180px',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: 'PostList',
|
||||
components: {
|
||||
PageView,
|
||||
TagSelect,
|
||||
CategoryTree,
|
||||
PostSettingDrawer,
|
||||
TargetCommentDrawer,
|
||||
TargetCommentDrawer
|
||||
},
|
||||
mixins: [mixin, mixinDevice],
|
||||
data() {
|
||||
|
@ -596,7 +477,7 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
|
@ -604,7 +485,7 @@ export default {
|
|||
sort: null,
|
||||
keyword: null,
|
||||
categoryId: null,
|
||||
status: null,
|
||||
status: null
|
||||
},
|
||||
// 表头
|
||||
columns,
|
||||
|
@ -613,8 +494,8 @@ export default {
|
|||
selectedMetas: [
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
},
|
||||
value: ''
|
||||
}
|
||||
],
|
||||
posts: [],
|
||||
postsLoading: false,
|
||||
|
@ -623,16 +504,16 @@ export default {
|
|||
postCommentVisible: false,
|
||||
selectedPost: {},
|
||||
selectedTagIds: [],
|
||||
selectedCategoryIds: [],
|
||||
selectedCategoryIds: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formattedPosts() {
|
||||
return this.posts.map((post) => {
|
||||
return this.posts.map(post => {
|
||||
post.statusProperty = this.postStatus[post.status]
|
||||
return post
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.handleListCategories()
|
||||
|
@ -643,7 +524,7 @@ export default {
|
|||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
next((vm) => {
|
||||
next(vm => {
|
||||
if (to.query.page) {
|
||||
vm.pagination.page = Number(to.query.page) + 1
|
||||
}
|
||||
|
@ -668,14 +549,14 @@ export default {
|
|||
watch: {
|
||||
queryParam: {
|
||||
deep: true,
|
||||
handler: function(newVal, oldVal) {
|
||||
handler: function(newVal) {
|
||||
if (newVal) {
|
||||
const params = JSON.parse(JSON.stringify(this.queryParam))
|
||||
const path = this.$router.history.current.path
|
||||
this.$router.push({ path, query: params }).catch((err) => err)
|
||||
this.$router.push({ path, query: params }).catch(err => err)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleListPosts(enableLoading = true) {
|
||||
|
@ -688,7 +569,7 @@ export default {
|
|||
this.queryParam.sort = this.pagination.sort
|
||||
postApi
|
||||
.query(this.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.posts = response.data.data.content
|
||||
this.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -702,7 +583,7 @@ export default {
|
|||
this.categoriesLoading = true
|
||||
categoryApi
|
||||
.listAll(true)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.categories = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -722,8 +603,8 @@ export default {
|
|||
return {
|
||||
props: {
|
||||
disabled: this.queryParam.status == null || this.queryParam.status === '',
|
||||
name: post.title,
|
||||
},
|
||||
name: post.title
|
||||
}
|
||||
}
|
||||
},
|
||||
handlePaginationChange(page, pageSize) {
|
||||
|
@ -751,7 +632,7 @@ export default {
|
|||
handleEditStatusClick(postId, status) {
|
||||
postApi
|
||||
.updateStatus(postId, status)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('操作成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -761,7 +642,7 @@ export default {
|
|||
handleDeleteClick(postId) {
|
||||
postApi
|
||||
.delete(postId)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -775,7 +656,7 @@ export default {
|
|||
}
|
||||
postApi
|
||||
.updateStatusInBatch(this.selectedRowKeys, status)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$log.debug(`postId: ${this.selectedRowKeys}, status: ${status}`)
|
||||
this.selectedRowKeys = []
|
||||
})
|
||||
|
@ -790,7 +671,7 @@ export default {
|
|||
}
|
||||
postApi
|
||||
.deleteInBatch(this.selectedRowKeys)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$log.debug(`delete: ${this.selectedRowKeys}`)
|
||||
this.selectedRowKeys = []
|
||||
})
|
||||
|
@ -799,7 +680,7 @@ export default {
|
|||
})
|
||||
},
|
||||
handleShowPostSettings(post) {
|
||||
postApi.get(post.id).then((response) => {
|
||||
postApi.get(post.id).then(response => {
|
||||
this.selectedPost = response.data.data
|
||||
this.selectedTagIds = this.selectedPost.tagIds
|
||||
this.selectedCategoryIds = this.selectedPost.categoryIds
|
||||
|
@ -808,13 +689,13 @@ export default {
|
|||
})
|
||||
},
|
||||
handleShowPostComments(post) {
|
||||
postApi.get(post.id).then((response) => {
|
||||
postApi.get(post.id).then(response => {
|
||||
this.selectedPost = response.data.data
|
||||
this.postCommentVisible = true
|
||||
})
|
||||
},
|
||||
handlePreview(postId) {
|
||||
postApi.preview(postId).then((response) => {
|
||||
postApi.preview(postId).then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
})
|
||||
},
|
||||
|
@ -847,7 +728,7 @@ export default {
|
|||
},
|
||||
onRefreshPostMetasFromSetting(metas) {
|
||||
this.selectedMetas = metas
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,49 +1,18 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="10"
|
||||
:lg="10"
|
||||
:md="10"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:title="title"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-form-model
|
||||
ref="tagForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="horizontal"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="名称:"
|
||||
help="* 页面上所显示的名称"
|
||||
prop="name"
|
||||
>
|
||||
<a-col :xl="10" :lg="10" :md="10" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :title="title" :bodyStyle="{ padding: '16px' }">
|
||||
<a-form-model ref="tagForm" :model="form.model" :rules="form.rules" layout="horizontal">
|
||||
<a-form-model-item label="名称:" help="* 页面上所显示的名称" prop="name">
|
||||
<a-input v-model="form.model.name" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="别名:"
|
||||
help="* 一般为单个标签页面的标识,最好为英文"
|
||||
prop="slug"
|
||||
>
|
||||
<a-form-model-item label="别名:" help="* 一般为单个标签页面的标识,最好为英文" prop="slug">
|
||||
<a-input v-model="form.model.slug" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="封面图:"
|
||||
help="* 在标签页面可展示,需要主题支持"
|
||||
prop="thumbnail"
|
||||
>
|
||||
<a-form-model-item label="封面图:" help="* 在标签页面可展示,需要主题支持" prop="thumbnail">
|
||||
<a-input v-model="form.model.thumbnail">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="thumbnailDrawer.visible = true"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click="thumbnailDrawer.visible = true">
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
|
@ -71,10 +40,7 @@
|
|||
loadedText="更新成功"
|
||||
erroredText="更新失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="form.model = {}"
|
||||
>返回添加</a-button>
|
||||
<a-button type="dashed" @click="form.model = {}">返回添加</a-button>
|
||||
</a-button-group>
|
||||
<a-popconfirm
|
||||
:title="'你确定要删除【' + form.model.name + '】标签?'"
|
||||
|
@ -83,43 +49,23 @@
|
|||
cancelText="取消"
|
||||
v-if="isUpdateMode"
|
||||
>
|
||||
<a-button
|
||||
type="danger"
|
||||
class="float-right"
|
||||
>删除</a-button>
|
||||
<a-button type="danger" class="float-right">删除</a-button>
|
||||
</a-popconfirm>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="14"
|
||||
:lg="14"
|
||||
:md="14"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
title="所有标签"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-col :xl="14" :lg="14" :md="14" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card title="所有标签" :bodyStyle="{ padding: '16px' }">
|
||||
<a-spin :spinning="list.loading">
|
||||
<a-empty v-if="list.data.length==0" />
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
v-for="tag in list.data"
|
||||
:key="tag.id"
|
||||
v-else
|
||||
>
|
||||
<a-empty v-if="list.data.length == 0" />
|
||||
<a-tooltip placement="topLeft" v-for="tag in list.data" :key="tag.id" v-else>
|
||||
<template slot="title">
|
||||
<span>{{ tag.postCount }} 篇文章</span>
|
||||
</template>
|
||||
<a-tag
|
||||
color="blue"
|
||||
style="margin-bottom: 8px;cursor:pointer;"
|
||||
@click="form.model = tag"
|
||||
>{{ tag.name }}</a-tag>
|
||||
<a-tag color="blue" style="margin-bottom: 8px;cursor:pointer;" @click="form.model = tag">{{
|
||||
tag.name
|
||||
}}</a-tag>
|
||||
</a-tooltip>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
<template>
|
||||
<a-tree
|
||||
checkable
|
||||
:treeData="categoryTree"
|
||||
:defaultExpandAll="true"
|
||||
:checkedKeys="categoryIds"
|
||||
@check="onCheck"
|
||||
>
|
||||
<a-tree checkable :treeData="categoryTree" :defaultExpandAll="true" :checkedKeys="categoryIds" @check="onCheck">
|
||||
</a-tree>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="文章设置"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
placement="right"
|
||||
closable
|
||||
destroyOnClose
|
||||
|
@ -14,16 +14,10 @@
|
|||
<h3 class="post-setting-drawer-title">基本设置</h3>
|
||||
<div class="post-setting-drawer-item">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
label="文章标题:"
|
||||
v-if="needTitle"
|
||||
>
|
||||
<a-form-item label="文章标题:" v-if="needTitle">
|
||||
<a-input v-model="selectedPost.title" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="文章别名:"
|
||||
:help="fullPath"
|
||||
>
|
||||
<a-form-item label="文章别名:" :help="fullPath">
|
||||
<a-input v-model="selectedPost.slug" />
|
||||
</a-form-item>
|
||||
|
||||
|
@ -38,37 +32,21 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="开启评论:">
|
||||
<a-radio-group
|
||||
v-model="selectedPost.disallowComment"
|
||||
:defaultValue="false"
|
||||
>
|
||||
<a-radio-group v-model="selectedPost.disallowComment" :defaultValue="false">
|
||||
<a-radio :value="false">开启</a-radio>
|
||||
<a-radio :value="true">关闭</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否置顶:">
|
||||
<a-radio-group
|
||||
v-model="selectedPost.topPriority"
|
||||
:defaultValue="0"
|
||||
>
|
||||
<a-radio-group v-model="selectedPost.topPriority" :defaultValue="0">
|
||||
<a-radio :value="1">是</a-radio>
|
||||
<a-radio :value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="自定义模板:"
|
||||
v-if="customTpls.length > 0"
|
||||
>
|
||||
<a-form-item label="自定义模板:" v-if="customTpls.length > 0">
|
||||
<a-select v-model="selectedPost.template">
|
||||
<a-select-option
|
||||
key=""
|
||||
value=""
|
||||
>无</a-select-option>
|
||||
<a-select-option
|
||||
v-for="tpl in customTpls"
|
||||
:key="tpl"
|
||||
:value="tpl"
|
||||
>{{ tpl }}</a-select-option>
|
||||
<a-select-option key="" value="">无</a-select-option>
|
||||
<a-select-option v-for="tpl in customTpls" :key="tpl" :value="tpl">{{ tpl }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -81,45 +59,22 @@
|
|||
<div class="post-setting-drawer-item">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item>
|
||||
<category-tree
|
||||
v-model="selectedCategoryIds"
|
||||
:categories="categories"
|
||||
/>
|
||||
<category-tree v-model="selectedCategoryIds" :categories="categories" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="categoryFormVisible">
|
||||
<category-select-tree
|
||||
:categories="categories"
|
||||
v-model="categoryToCreate.parentId"
|
||||
/>
|
||||
<category-select-tree :categories="categories" v-model="categoryToCreate.parentId" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="categoryFormVisible">
|
||||
<a-input
|
||||
placeholder="分类名称"
|
||||
v-model="categoryToCreate.name"
|
||||
/>
|
||||
<a-input placeholder="分类名称" v-model="categoryToCreate.name" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="categoryFormVisible">
|
||||
<a-input
|
||||
placeholder="分类路径"
|
||||
v-model="categoryToCreate.slug"
|
||||
/>
|
||||
<a-input placeholder="分类路径" v-model="categoryToCreate.slug" />
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
v-if="categoryFormVisible"
|
||||
@click="handlerCreateCategory"
|
||||
>保存</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
v-if="!categoryFormVisible"
|
||||
@click="categoryFormVisible = true"
|
||||
>新增</a-button>
|
||||
<a-button
|
||||
v-if="categoryFormVisible"
|
||||
@click="categoryFormVisible = false"
|
||||
>取消</a-button>
|
||||
<a-button type="primary" v-if="categoryFormVisible" @click="handlerCreateCategory">保存</a-button>
|
||||
<a-button type="dashed" v-if="!categoryFormVisible" @click="categoryFormVisible = true">新增</a-button>
|
||||
<a-button v-if="categoryFormVisible" @click="categoryFormVisible = false">取消</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -163,37 +118,26 @@
|
|||
<img
|
||||
class="img"
|
||||
:src="selectedPost.thumbnail || '/images/placeholder.jpg'"
|
||||
@click="thumbDrawerVisible=true"
|
||||
>
|
||||
@click="thumbDrawerVisible = true"
|
||||
/>
|
||||
|
||||
<a-form layout="vertial">
|
||||
<a-form-item>
|
||||
<a-input
|
||||
v-model="selectedPost.thumbnail"
|
||||
placeholder="点击封面图选择图片,或者输入外部链接"
|
||||
></a-input>
|
||||
<a-input v-model="selectedPost.thumbnail" placeholder="点击封面图选择图片,或者输入外部链接"></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<a-button
|
||||
class="post-thumb-remove"
|
||||
type="dashed"
|
||||
@click="selectedPost.thumbnail = null"
|
||||
>移除</a-button>
|
||||
<a-button class="post-thumb-remove" type="dashed" @click="selectedPost.thumbnail = null">移除</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider class="divider-transparent" />
|
||||
</div>
|
||||
<AttachmentSelectDrawer
|
||||
v-model="thumbDrawerVisible"
|
||||
@listenToSelect="handleSelectPostThumb"
|
||||
:drawerWidth="480"
|
||||
/>
|
||||
<AttachmentSelectDrawer v-model="thumbDrawerVisible" @listenToSelect="handleSelectPostThumb" :drawerWidth="480" />
|
||||
|
||||
<a-drawer
|
||||
title="高级设置"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
placement="right"
|
||||
closable
|
||||
destroyOnClose
|
||||
|
@ -206,10 +150,7 @@
|
|||
<div class="post-setting-drawer-item">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="访问密码:">
|
||||
<a-input-password
|
||||
v-model="selectedPost.password"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="selectedPost.password" autocomplete="new-password" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
|
@ -240,11 +181,7 @@
|
|||
<div class="mb-4">
|
||||
<h3 class="post-setting-drawer-title">元数据</h3>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
v-for="(meta, index) in selectedMetas"
|
||||
:key="index"
|
||||
:prop="'metas.' + index + '.value'"
|
||||
>
|
||||
<a-form-item v-for="(meta, index) in selectedMetas" :key="index" :prop="'metas.' + index + '.value'">
|
||||
<a-row :gutter="5">
|
||||
<a-col :span="12">
|
||||
<a-input v-model="meta.key"><i slot="addonBefore">K</i></a-input>
|
||||
|
@ -252,11 +189,7 @@
|
|||
<a-col :span="12">
|
||||
<a-input v-model="meta.value">
|
||||
<i slot="addonBefore">V</i>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click.prevent="handleRemovePostMeta(meta)"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click.prevent="handleRemovePostMeta(meta)">
|
||||
<a-icon type="close" />
|
||||
</a>
|
||||
</a-input>
|
||||
|
@ -264,10 +197,7 @@
|
|||
</a-row>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="handleInsertPostMeta"
|
||||
>新增</a-button>
|
||||
<a-button type="dashed" @click="handleInsertPostMeta">新增</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
|
@ -282,10 +212,7 @@
|
|||
|
||||
<div class="bottom-control">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="advancedVisible = true"
|
||||
>高级</a-button>
|
||||
<a-button type="dashed" @click="advancedVisible = true">高级</a-button>
|
||||
<ReactiveButton
|
||||
type="danger"
|
||||
v-if="saveDraftButton"
|
||||
|
@ -302,9 +229,9 @@
|
|||
@callback="handleSavedCallback"
|
||||
:loading="saving"
|
||||
:errored="savedErrored"
|
||||
:text="`${selectedPost.id?'保存':'发布'}`"
|
||||
:loadedText="`${selectedPost.id?'保存':'发布'}成功`"
|
||||
:erroredText="`${selectedPost.id?'保存':'发布'}失败`"
|
||||
:text="`${selectedPost.id ? '保存' : '发布'}`"
|
||||
:loadedText="`${selectedPost.id ? '保存' : '发布'}成功`"
|
||||
:erroredText="`${selectedPost.id ? '保存' : '发布'}失败`"
|
||||
></ReactiveButton>
|
||||
</a-space>
|
||||
</div>
|
||||
|
@ -333,7 +260,7 @@ export default {
|
|||
components: {
|
||||
CategoryTree,
|
||||
CategorySelectTree,
|
||||
TagSelect,
|
||||
TagSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -349,41 +276,41 @@ export default {
|
|||
saving: false,
|
||||
savedErrored: false,
|
||||
draftSaving: false,
|
||||
draftSavedErrored: false,
|
||||
draftSavedErrored: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
post: {
|
||||
type: Object,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
tagIds: {
|
||||
type: Array,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
categoryIds: {
|
||||
type: Array,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
metas: {
|
||||
type: Array,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
needTitle: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
saveDraftButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
default: true
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
post(val) {
|
||||
|
@ -406,7 +333,7 @@ export default {
|
|||
},
|
||||
selectedMetas(val) {
|
||||
this.$emit('onRefreshPostMetas', val)
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['options']),
|
||||
|
@ -452,7 +379,7 @@ export default {
|
|||
default:
|
||||
return ''
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAfterVisibleChanged(visible) {
|
||||
|
@ -464,19 +391,19 @@ export default {
|
|||
}
|
||||
},
|
||||
handleListCategories() {
|
||||
categoryApi.listAll().then((response) => {
|
||||
categoryApi.listAll().then(response => {
|
||||
this.categories = response.data.data
|
||||
})
|
||||
},
|
||||
handleListPresetMetasField() {
|
||||
if (this.metas.length <= 0) {
|
||||
themeApi.getActivatedTheme().then((response) => {
|
||||
themeApi.getActivatedTheme().then(response => {
|
||||
const fields = response.data.data.postMetaField
|
||||
if (fields && fields.length > 0) {
|
||||
for (let i = 0, len = fields.length; i < len; i++) {
|
||||
this.selectedMetas.push({
|
||||
value: '',
|
||||
key: fields[i],
|
||||
key: fields[i]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -484,7 +411,7 @@ export default {
|
|||
}
|
||||
},
|
||||
handleListCustomTpls() {
|
||||
themeApi.customPostTpls().then((response) => {
|
||||
themeApi.customPostTpls().then(response => {
|
||||
this.customTpls = response.data.data
|
||||
})
|
||||
},
|
||||
|
@ -496,13 +423,13 @@ export default {
|
|||
if (!this.categoryToCreate.name) {
|
||||
this.$notification['error']({
|
||||
message: '提示',
|
||||
description: '分类名称不能为空!',
|
||||
description: '分类名称不能为空!'
|
||||
})
|
||||
return
|
||||
}
|
||||
categoryApi
|
||||
.create(this.categoryToCreate)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.categoryToCreate = {}
|
||||
this.categoryFormVisible = false
|
||||
})
|
||||
|
@ -522,7 +449,7 @@ export default {
|
|||
if (!this.selectedPost.title) {
|
||||
this.$notification['error']({
|
||||
message: '提示',
|
||||
description: '文章标题不能为空!',
|
||||
description: '文章标题不能为空!'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -565,7 +492,7 @@ export default {
|
|||
this.savedErrored = true
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.selectedPost = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -588,7 +515,7 @@ export default {
|
|||
onClose() {
|
||||
this.$emit('close', false)
|
||||
},
|
||||
onPostDateChange(value, dateString) {
|
||||
onPostDateChange(value) {
|
||||
this.selectedPost.createTime = value.valueOf()
|
||||
},
|
||||
onPostDateOk(value) {
|
||||
|
@ -603,7 +530,7 @@ export default {
|
|||
handleInsertPostMeta() {
|
||||
this.selectedMetas.push({
|
||||
value: '',
|
||||
key: '',
|
||||
key: ''
|
||||
})
|
||||
},
|
||||
handleSetPinyinSlug() {
|
||||
|
@ -612,7 +539,7 @@ export default {
|
|||
let result = ''
|
||||
const tokens = pinyin.parse(this.selectedPost.title)
|
||||
let lastToken
|
||||
tokens.forEach((token, i) => {
|
||||
tokens.forEach(token => {
|
||||
if (token.type === 2) {
|
||||
const target = token.target ? token.target.toLowerCase() : ''
|
||||
result += result && !/\n|\s/.test(lastToken.target) ? '-' + target : target
|
||||
|
@ -624,7 +551,7 @@ export default {
|
|||
this.$set(this.selectedPost, 'slug', result)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -8,11 +8,7 @@
|
|||
placeholder="选择或输入标签"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="tag in tags"
|
||||
:key="tag.id"
|
||||
:value="tag.name"
|
||||
>{{ tag.name }}</a-select-option>
|
||||
<a-select-option v-for="tag in tags" :key="tag.id" :value="tag.name">{{ tag.name }}</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -44,8 +40,7 @@ export default {
|
|||
this.handleListTags()
|
||||
},
|
||||
watch: {
|
||||
tags(newValue, oldValue) {
|
||||
// 解决tags未赋上值就使用导致的取值报错问题
|
||||
tags(newValue) {
|
||||
if (newValue) {
|
||||
this.selectedTagNames = this.tagIds.map(tagId => this.tagIdMap[tagId].name)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<page-view
|
||||
affix
|
||||
:title="sheetToStage.title?sheetToStage.title:'新页面'"
|
||||
>
|
||||
<page-view affix :title="sheetToStage.title ? sheetToStage.title : '新页面'">
|
||||
<template slot="extra">
|
||||
<a-space>
|
||||
<ReactiveButton
|
||||
|
@ -15,28 +12,15 @@
|
|||
loadedText="保存成功"
|
||||
erroredText="保存失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
@click="handlePreview"
|
||||
:loading="previewSaving"
|
||||
>预览</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="sheetSettingVisible = true"
|
||||
>发布</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="attachmentDrawerVisible = true"
|
||||
>附件库</a-button>
|
||||
<a-button @click="handlePreview" :loading="previewSaving">预览</a-button>
|
||||
<a-button type="primary" @click="sheetSettingVisible = true">发布</a-button>
|
||||
<a-button type="dashed" @click="attachmentDrawerVisible = true">附件库</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="24">
|
||||
<div class="mb-4">
|
||||
<a-input
|
||||
v-model="sheetToStage.title"
|
||||
size="large"
|
||||
placeholder="请输入页面标题"
|
||||
/>
|
||||
<a-input v-model="sheetToStage.title" size="large" placeholder="请输入页面标题" />
|
||||
</div>
|
||||
|
||||
<div id="editor">
|
||||
|
@ -76,7 +60,6 @@ import { datetimeFormat } from '@/utils/datetime'
|
|||
import { PageView } from '@/layouts'
|
||||
import SheetSettingDrawer from './components/SheetSettingDrawer'
|
||||
import AttachmentDrawer from '../attachment/components/AttachmentDrawer'
|
||||
import FooterToolBar from '@/components/FooterToolbar'
|
||||
import MarkdownEditor from '@/components/Editor/MarkdownEditor'
|
||||
// import RichTextEditor from '@/components/editor/RichTextEditor'
|
||||
|
||||
|
@ -84,10 +67,9 @@ import sheetApi from '@/api/sheet'
|
|||
export default {
|
||||
components: {
|
||||
PageView,
|
||||
FooterToolBar,
|
||||
AttachmentDrawer,
|
||||
SheetSettingDrawer,
|
||||
MarkdownEditor,
|
||||
MarkdownEditor
|
||||
// RichTextEditor
|
||||
},
|
||||
mixins: [mixin, mixinDevice],
|
||||
|
@ -100,16 +82,16 @@ export default {
|
|||
contentChanges: 0,
|
||||
draftSaving: false,
|
||||
draftSavederrored: false,
|
||||
previewSaving: false,
|
||||
previewSaving: false
|
||||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
// Get sheetId id from query
|
||||
const sheetId = to.query.sheetId
|
||||
|
||||
next((vm) => {
|
||||
next(vm => {
|
||||
if (sheetId) {
|
||||
sheetApi.get(sheetId).then((response) => {
|
||||
sheetApi.get(sheetId).then(response => {
|
||||
const sheet = response.data.data
|
||||
vm.sheetToStage = sheet
|
||||
vm.selectedMetas = sheet.metas
|
||||
|
@ -140,13 +122,13 @@ export default {
|
|||
} else {
|
||||
this.$confirm({
|
||||
title: '当前页面数据未保存,确定要离开吗?',
|
||||
content: (h) => <div style="color:red;">如果离开当面页面,你的数据很可能会丢失!</div>,
|
||||
content: () => <div style="color:red;">如果离开当面页面,你的数据很可能会丢失!</div>,
|
||||
onOk() {
|
||||
next()
|
||||
},
|
||||
onCancel() {
|
||||
next(false)
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -163,16 +145,16 @@ export default {
|
|||
// }
|
||||
},
|
||||
watch: {
|
||||
temporaryContent: function(newValue, oldValue) {
|
||||
temporaryContent(newValue) {
|
||||
if (newValue) {
|
||||
this.contentChanges++
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
temporaryContent() {
|
||||
return this.sheetToStage.originalContent
|
||||
},
|
||||
}
|
||||
// ...mapGetters(['options'])
|
||||
},
|
||||
methods: {
|
||||
|
@ -187,7 +169,7 @@ export default {
|
|||
if (draftOnly) {
|
||||
sheetApi
|
||||
.updateDraft(this.sheetToStage.id, this.sheetToStage.originalContent)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -201,7 +183,7 @@ export default {
|
|||
} else {
|
||||
sheetApi
|
||||
.update(this.sheetToStage.id, this.sheetToStage, false)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.sheetToStage = response.data.data
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -217,7 +199,7 @@ export default {
|
|||
} else {
|
||||
sheetApi
|
||||
.create(this.sheetToStage, false)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.sheetToStage = response.data.data
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -238,11 +220,11 @@ export default {
|
|||
}
|
||||
this.previewSaving = true
|
||||
if (this.sheetToStage.id) {
|
||||
sheetApi.update(this.sheetToStage.id, this.sheetToStage, false).then((response) => {
|
||||
sheetApi.update(this.sheetToStage.id, this.sheetToStage, false).then(response => {
|
||||
this.$log.debug('Updated sheet', response.data.data)
|
||||
sheetApi
|
||||
.preview(this.sheetToStage.id)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -253,12 +235,12 @@ export default {
|
|||
})
|
||||
})
|
||||
} else {
|
||||
sheetApi.create(this.sheetToStage, false).then((response) => {
|
||||
sheetApi.create(this.sheetToStage, false).then(response => {
|
||||
this.$log.debug('Created sheet', response.data.data)
|
||||
this.sheetToStage = response.data.data
|
||||
sheetApi
|
||||
.preview(this.sheetToStage.id)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
this.handleRestoreSavedStatus()
|
||||
})
|
||||
|
@ -281,7 +263,7 @@ export default {
|
|||
},
|
||||
onRefreshSheetMetasFromSetting(metas) {
|
||||
this.selectedMetas = metas
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -3,17 +3,9 @@
|
|||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div class="card-container">
|
||||
<a-tabs
|
||||
v-model="activeKey"
|
||||
type="card"
|
||||
>
|
||||
<a-tab-pane
|
||||
v-for="pane in panes"
|
||||
:key="pane.key"
|
||||
>
|
||||
<span slot="tab">
|
||||
<a-icon :type="pane.icon" />{{ pane.title }}
|
||||
</span>
|
||||
<a-tabs v-model="activeKey" type="card">
|
||||
<a-tab-pane v-for="pane in panes" :key="pane.key">
|
||||
<span slot="tab"> <a-icon :type="pane.icon" />{{ pane.title }} </span>
|
||||
<component :is="pane.component"></component>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
@ -32,36 +24,34 @@ export default {
|
|||
components: {
|
||||
PageView,
|
||||
IndependentSheetList,
|
||||
CustomSheetList,
|
||||
CustomSheetList
|
||||
},
|
||||
data() {
|
||||
const panes = [
|
||||
{ title: '独立页面', icon: 'paper-clip', component: 'IndependentSheetList', key: 'independent' },
|
||||
{ title: '自定义页面', icon: 'fork', component: 'CustomSheetList', key: 'custom' },
|
||||
{ title: '自定义页面', icon: 'fork', component: 'CustomSheetList', key: 'custom' }
|
||||
]
|
||||
return {
|
||||
activeKey: panes[0].key,
|
||||
panes,
|
||||
panes
|
||||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
// Get post id from query
|
||||
const activeKey = to.query.activeKey
|
||||
next((vm) => {
|
||||
next(vm => {
|
||||
if (activeKey) {
|
||||
vm.activeKey = activeKey
|
||||
}
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
activeKey: {
|
||||
handler: function(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
const path = this.$router.history.current.path
|
||||
this.$router.push({ path, query: { activeKey: newVal } }).catch((err) => err)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
activeKey(newVal) {
|
||||
if (newVal) {
|
||||
const path = this.$router.history.current.path
|
||||
this.$router.push({ path, query: { activeKey: newVal } }).catch(err => err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -9,11 +9,7 @@
|
|||
:dataSource="formattedSheets"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<span>
|
||||
<a-icon type="eye" />
|
||||
|
@ -23,24 +19,18 @@
|
|||
<a-icon type="message" />
|
||||
{{ item.commentCount }}
|
||||
</span>
|
||||
<a-dropdown
|
||||
placement="topLeft"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a-dropdown placement="topLeft" :trigger="['click']">
|
||||
<span>
|
||||
<a-icon type="bars" />
|
||||
</span>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item v-if="item.status === 'PUBLISHED' || item.status === 'DRAFT'">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleEditClick(item)"
|
||||
>编辑</a>
|
||||
<a href="javascript:;" @click="handleEditClick(item)">编辑</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-else-if="item.status === 'RECYCLE'">
|
||||
<a-popconfirm
|
||||
:title="'你确定要发布【' + item.title + '】页面?'"
|
||||
@confirm="handleEditStatusClick(item.id,'PUBLISHED')"
|
||||
@confirm="handleEditStatusClick(item.id, 'PUBLISHED')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
|
@ -50,7 +40,7 @@
|
|||
<a-menu-item v-if="item.status === 'PUBLISHED' || item.status === 'DRAFT'">
|
||||
<a-popconfirm
|
||||
:title="'你确定要将【' + item.title + '】页面移到回收站?'"
|
||||
@confirm="handleEditStatusClick(item.id,'RECYCLE')"
|
||||
@confirm="handleEditStatusClick(item.id, 'RECYCLE')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
|
@ -68,21 +58,14 @@
|
|||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="javascript:void(0);"
|
||||
@click="handleShowSheetSettings(item)"
|
||||
>设置</a>
|
||||
<a rel="noopener noreferrer" href="javascript:void(0);" @click="handleShowSheetSettings(item)">设置</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template slot="extra">
|
||||
<span>
|
||||
<a-badge
|
||||
:status="item.statusProperty.status"
|
||||
:text="item.statusProperty.text"
|
||||
/>
|
||||
<a-badge :status="item.statusProperty.status" :text="item.statusProperty.text" />
|
||||
</span>
|
||||
</template>
|
||||
<a-list-item-meta>
|
||||
|
@ -93,42 +76,23 @@
|
|||
slot="title"
|
||||
style="max-width: 300px;display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
>
|
||||
<a
|
||||
v-if="item.status=='PUBLISHED'"
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
class="no-underline"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="'点击访问【'+item.title+'】'"
|
||||
>{{ item.title }}</a-tooltip>
|
||||
<a v-if="item.status == 'PUBLISHED'" :href="item.fullPath" target="_blank" class="no-underline">
|
||||
<a-tooltip placement="top" :title="'点击访问【' + item.title + '】'">{{ item.title }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="item.status=='DRAFT'"
|
||||
v-else-if="item.status == 'DRAFT'"
|
||||
href="javascript:void(0)"
|
||||
class="no-underline"
|
||||
@click="handlePreview(item.id)"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
:title="'点击预览【'+item.title+'】'"
|
||||
>{{ item.title }}</a-tooltip>
|
||||
<a-tooltip placement="topLeft" :title="'点击预览【' + item.title + '】'">{{ item.title }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else
|
||||
href="javascript:void(0);"
|
||||
class="no-underline"
|
||||
disabled
|
||||
>
|
||||
<a v-else href="javascript:void(0);" class="no-underline" disabled>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
</span>
|
||||
|
||||
</a-list-item-meta>
|
||||
<span>
|
||||
{{ item.summary }}...
|
||||
</span>
|
||||
<span> {{ item.summary }}... </span>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
||||
|
@ -142,82 +106,46 @@
|
|||
:loading="loading"
|
||||
:scrollToFirstRowOnChange="true"
|
||||
>
|
||||
<span
|
||||
slot="sheetTitle"
|
||||
slot-scope="text,record"
|
||||
>
|
||||
<a
|
||||
v-if="record.status=='PUBLISHED'"
|
||||
:href="record.fullPath"
|
||||
target="_blank"
|
||||
class="no-underline"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="'点击访问【'+text+'】'"
|
||||
>{{ text }}</a-tooltip>
|
||||
<span slot="sheetTitle" slot-scope="text, record">
|
||||
<a v-if="record.status == 'PUBLISHED'" :href="record.fullPath" target="_blank" class="no-underline">
|
||||
<a-tooltip placement="top" :title="'点击访问【' + text + '】'">{{ text }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="record.status=='DRAFT'"
|
||||
v-else-if="record.status == 'DRAFT'"
|
||||
href="javascript:void(0)"
|
||||
class="no-underline"
|
||||
@click="handlePreview(record.id)"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
:title="'点击预览【'+text+'】'"
|
||||
>{{ text }}</a-tooltip>
|
||||
<a-tooltip placement="topLeft" :title="'点击预览【' + text + '】'">{{ text }}</a-tooltip>
|
||||
</a>
|
||||
<a
|
||||
v-else
|
||||
href="javascript:void(0);"
|
||||
class="no-underline"
|
||||
disabled
|
||||
>
|
||||
<a v-else href="javascript:void(0);" class="no-underline" disabled>
|
||||
{{ text }}
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="status"
|
||||
slot-scope="statusProperty"
|
||||
>
|
||||
<a-badge
|
||||
:status="statusProperty.status"
|
||||
:text="statusProperty.text"
|
||||
/>
|
||||
<span slot="status" slot-scope="statusProperty">
|
||||
<a-badge :status="statusProperty.status" :text="statusProperty.text" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="commentCount"
|
||||
slot-scope="text,record"
|
||||
slot-scope="text, record"
|
||||
@click="handleShowSheetComments(record)"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<a-badge
|
||||
:count="record.commentCount"
|
||||
:numberStyle="{backgroundColor: '#f38181'} "
|
||||
:numberStyle="{ backgroundColor: '#f38181' }"
|
||||
:showZero="true"
|
||||
:overflowCount="999"
|
||||
/>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="visits"
|
||||
slot-scope="visits"
|
||||
>
|
||||
<a-badge
|
||||
:count="visits"
|
||||
:numberStyle="{backgroundColor: '#00e0ff'} "
|
||||
:showZero="true"
|
||||
:overflowCount="9999"
|
||||
/>
|
||||
<span slot="visits" slot-scope="visits">
|
||||
<a-badge :count="visits" :numberStyle="{ backgroundColor: '#00e0ff' }" :showZero="true" :overflowCount="9999" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="createTime"
|
||||
slot-scope="createTime"
|
||||
>
|
||||
<span slot="createTime" slot-scope="createTime">
|
||||
<a-tooltip placement="top">
|
||||
<template slot="title">
|
||||
{{ createTime | moment }}
|
||||
|
@ -226,19 +154,17 @@
|
|||
</a-tooltip>
|
||||
</span>
|
||||
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, sheet"
|
||||
>
|
||||
<span slot="action" slot-scope="text, sheet">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@click="handleEditClick(sheet)"
|
||||
v-if="sheet.status === 'PUBLISHED' || sheet.status === 'DRAFT'"
|
||||
>编辑</a>
|
||||
>编辑</a
|
||||
>
|
||||
|
||||
<a-popconfirm
|
||||
:title="'你确定要发布【' + sheet.title + '】?'"
|
||||
@confirm="handleEditStatusClick(sheet.id,'PUBLISHED')"
|
||||
@confirm="handleEditStatusClick(sheet.id, 'PUBLISHED')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
v-else-if="sheet.status === 'RECYCLE'"
|
||||
|
@ -250,7 +176,7 @@
|
|||
|
||||
<a-popconfirm
|
||||
:title="'你确定要将【' + sheet.title + '】页面移到回收站?'"
|
||||
@confirm="handleEditStatusClick(sheet.id,'RECYCLE')"
|
||||
@confirm="handleEditStatusClick(sheet.id, 'RECYCLE')"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
v-if="sheet.status === 'PUBLISHED' || sheet.status === 'DRAFT'"
|
||||
|
@ -268,10 +194,7 @@
|
|||
<a href="javascript:;">删除</a>
|
||||
</a-popconfirm>
|
||||
<a-divider type="vertical" />
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleShowSheetSettings(sheet)"
|
||||
>设置</a>
|
||||
<a href="javascript:void(0);" @click="handleShowSheetSettings(sheet)">设置</a>
|
||||
</span>
|
||||
</a-table>
|
||||
<div class="page-wrapper">
|
||||
|
@ -319,41 +242,41 @@ const customColumns = [
|
|||
title: '标题',
|
||||
dataIndex: 'title',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'sheetTitle' },
|
||||
scopedSlots: { customRender: 'sheetTitle' }
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
className: 'status',
|
||||
dataIndex: 'statusProperty',
|
||||
scopedSlots: { customRender: 'status' },
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
{
|
||||
title: '评论量',
|
||||
dataIndex: 'commentCount',
|
||||
scopedSlots: { customRender: 'commentCount' },
|
||||
scopedSlots: { customRender: 'commentCount' }
|
||||
},
|
||||
{
|
||||
title: '访问量',
|
||||
dataIndex: 'visits',
|
||||
scopedSlots: { customRender: 'visits' },
|
||||
scopedSlots: { customRender: 'visits' }
|
||||
},
|
||||
{
|
||||
title: '发布时间',
|
||||
dataIndex: 'createTime',
|
||||
scopedSlots: { customRender: 'createTime' },
|
||||
scopedSlots: { customRender: 'createTime' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: '180px',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: 'CustomSheetList',
|
||||
mixins: [mixin, mixinDevice],
|
||||
components: {
|
||||
SheetSettingDrawer,
|
||||
TargetCommentDrawer,
|
||||
TargetCommentDrawer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -361,7 +284,7 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
|
@ -369,7 +292,7 @@ export default {
|
|||
sort: null,
|
||||
keyword: null,
|
||||
categoryId: null,
|
||||
status: null,
|
||||
status: null
|
||||
},
|
||||
loading: false,
|
||||
sheetStatus: sheetApi.sheetStatus,
|
||||
|
@ -379,16 +302,16 @@ export default {
|
|||
sheetSettingVisible: false,
|
||||
sheetCommentVisible: false,
|
||||
sheets: [],
|
||||
menu: {},
|
||||
menu: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formattedSheets() {
|
||||
return this.sheets.map((sheet) => {
|
||||
return this.sheets.map(sheet => {
|
||||
sheet.statusProperty = this.sheetStatus[sheet.status]
|
||||
return sheet
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.handleListSheets()
|
||||
|
@ -414,7 +337,7 @@ export default {
|
|||
this.queryParam.sort = this.pagination.sort
|
||||
sheetApi
|
||||
.list(this.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.sheets = response.data.data.content
|
||||
this.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -430,7 +353,7 @@ export default {
|
|||
handleEditStatusClick(sheetId, status) {
|
||||
sheetApi
|
||||
.updateStatus(sheetId, status)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('操作成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -440,7 +363,7 @@ export default {
|
|||
handleDeleteClick(sheetId) {
|
||||
sheetApi
|
||||
.delete(sheetId)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -448,20 +371,20 @@ export default {
|
|||
})
|
||||
},
|
||||
handleShowSheetSettings(sheet) {
|
||||
sheetApi.get(sheet.id).then((response) => {
|
||||
sheetApi.get(sheet.id).then(response => {
|
||||
this.selectedSheet = response.data.data
|
||||
this.selectedMetas = this.selectedSheet.metas
|
||||
this.sheetSettingVisible = true
|
||||
})
|
||||
},
|
||||
handleShowSheetComments(sheet) {
|
||||
sheetApi.get(sheet.id).then((response) => {
|
||||
sheetApi.get(sheet.id).then(response => {
|
||||
this.selectedSheet = response.data.data
|
||||
this.sheetCommentVisible = true
|
||||
})
|
||||
},
|
||||
handlePreview(sheetId) {
|
||||
sheetApi.preview(sheetId).then((response) => {
|
||||
sheetApi.preview(sheetId).then(response => {
|
||||
window.open(response.data, '_blank')
|
||||
})
|
||||
},
|
||||
|
@ -490,7 +413,7 @@ export default {
|
|||
},
|
||||
onRefreshSheetMetasFromSetting(metas) {
|
||||
this.selectedMetas = metas
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -9,25 +9,19 @@
|
|||
:dataSource="independentSheets"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<span>
|
||||
<router-link :to="{name:item.routeName}">
|
||||
<router-link :to="{ name: item.routeName }">
|
||||
<a-icon type="edit" />
|
||||
</router-link>
|
||||
</span>
|
||||
</template>
|
||||
<template slot="extra">
|
||||
<span v-if="item.available">可用</span>
|
||||
<span v-else>不可用
|
||||
<a-tooltip
|
||||
slot="action"
|
||||
title="当前主题没有对应模板"
|
||||
>
|
||||
<span v-else
|
||||
>不可用
|
||||
<a-tooltip slot="action" title="当前主题没有对应模板">
|
||||
<a-icon type="info-circle-o" />
|
||||
</a-tooltip>
|
||||
</span>
|
||||
|
@ -37,19 +31,9 @@
|
|||
slot="title"
|
||||
style="max-width: 300px;display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
>
|
||||
<a
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
v-if="item.available"
|
||||
>{{ item.title }}</a>
|
||||
<a
|
||||
:href="item.fullPath"
|
||||
target="_blank"
|
||||
disabled
|
||||
v-else
|
||||
>{{ item.title }}</a>
|
||||
<a :href="item.fullPath" target="_blank" v-if="item.available">{{ item.title }}</a>
|
||||
<a :href="item.fullPath" target="_blank" disabled v-else>{{ item.title }}</a>
|
||||
</span>
|
||||
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
@ -63,39 +47,22 @@
|
|||
:rowKey="sheet => sheet.id"
|
||||
:loading="loading"
|
||||
>
|
||||
<template
|
||||
slot="available"
|
||||
slot-scope="available"
|
||||
>
|
||||
<template slot="available" slot-scope="available">
|
||||
<span v-if="available">可用</span>
|
||||
<span v-else>不可用
|
||||
<a-tooltip
|
||||
slot="action"
|
||||
title="当前主题没有对应模板"
|
||||
>
|
||||
<span v-else
|
||||
>不可用
|
||||
<a-tooltip slot="action" title="当前主题没有对应模板">
|
||||
<a-icon type="info-circle-o" />
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
<router-link :to="{name:record.routeName}">
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<router-link :to="{ name: record.routeName }">
|
||||
<a href="javascript:void(0);">管理</a>
|
||||
</router-link>
|
||||
<a-divider type="vertical" />
|
||||
<a
|
||||
:href="record.fullPath"
|
||||
target="_blank"
|
||||
v-if="record.available"
|
||||
>访问</a>
|
||||
<a
|
||||
:href="record.fullPath"
|
||||
target="_blank"
|
||||
disabled
|
||||
v-else
|
||||
>访问</a>
|
||||
<a :href="record.fullPath" target="_blank" v-if="record.available">访问</a>
|
||||
<a :href="record.fullPath" target="_blank" disabled v-else>访问</a>
|
||||
</span>
|
||||
</a-table>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="页面设置"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
placement="right"
|
||||
closable
|
||||
destroyOnClose
|
||||
|
@ -14,16 +14,10 @@
|
|||
<h3 class="post-setting-drawer-title">基本设置</h3>
|
||||
<div class="post-setting-drawer-item">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
label="页面标题:"
|
||||
v-if="needTitle"
|
||||
>
|
||||
<a-form-item label="页面标题:" v-if="needTitle">
|
||||
<a-input v-model="selectedSheet.title" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="页面别名:"
|
||||
:help="fullPath"
|
||||
>
|
||||
<a-form-item label="页面别名:" :help="fullPath">
|
||||
<a-input v-model="selectedSheet.slug" />
|
||||
</a-form-item>
|
||||
<a-form-item label="发表时间:">
|
||||
|
@ -37,31 +31,15 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="开启评论:">
|
||||
<a-radio-group
|
||||
v-model="selectedSheet.disallowComment"
|
||||
:defaultValue="false"
|
||||
>
|
||||
<a-radio-group v-model="selectedSheet.disallowComment" :defaultValue="false">
|
||||
<a-radio :value="false">开启</a-radio>
|
||||
<a-radio :value="true">关闭</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="自定义模板:"
|
||||
v-if="customTpls.length>0"
|
||||
>
|
||||
<a-select
|
||||
v-model="selectedSheet.template"
|
||||
:loading="customTplsLoading"
|
||||
>
|
||||
<a-select-option
|
||||
key=""
|
||||
value=""
|
||||
>无</a-select-option>
|
||||
<a-select-option
|
||||
v-for="tpl in customTpls"
|
||||
:key="tpl"
|
||||
:value="tpl"
|
||||
>{{ tpl }}</a-select-option>
|
||||
<a-form-item label="自定义模板:" v-if="customTpls.length > 0">
|
||||
<a-select v-model="selectedSheet.template" :loading="customTplsLoading">
|
||||
<a-select-option key="" value="">无</a-select-option>
|
||||
<a-select-option v-for="tpl in customTpls" :key="tpl" :value="tpl">{{ tpl }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -94,36 +72,25 @@
|
|||
class="img"
|
||||
:src="selectedSheet.thumbnail || '/images/placeholder.jpg'"
|
||||
@click="thumbDrawerVisible = true"
|
||||
>
|
||||
/>
|
||||
|
||||
<a-form layout="vertial">
|
||||
<a-form-item>
|
||||
<a-input
|
||||
v-model="selectedSheet.thumbnail"
|
||||
placeholder="点击封面图选择图片,或者输入外部链接"
|
||||
></a-input>
|
||||
<a-input v-model="selectedSheet.thumbnail" placeholder="点击封面图选择图片,或者输入外部链接"></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<a-button
|
||||
class="sheet-thumb-remove"
|
||||
type="dashed"
|
||||
@click="selectedSheet.thumbnail = null"
|
||||
>移除</a-button>
|
||||
<a-button class="sheet-thumb-remove" type="dashed" @click="selectedSheet.thumbnail = null">移除</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider class="divider-transparent" />
|
||||
</div>
|
||||
<AttachmentSelectDrawer
|
||||
v-model="thumbDrawerVisible"
|
||||
@listenToSelect="handleSelectSheetThumb"
|
||||
:drawerWidth="480"
|
||||
/>
|
||||
<AttachmentSelectDrawer v-model="thumbDrawerVisible" @listenToSelect="handleSelectSheetThumb" :drawerWidth="480" />
|
||||
|
||||
<a-drawer
|
||||
title="高级设置"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
placement="right"
|
||||
closable
|
||||
destroyOnClose
|
||||
|
@ -136,10 +103,7 @@
|
|||
<div class="post-setting-drawer-item">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="自定义关键词:">
|
||||
<a-input
|
||||
v-model="selectedSheet.metaKeywords"
|
||||
placeholder="多个关键词以英文逗号隔开"
|
||||
/>
|
||||
<a-input v-model="selectedSheet.metaKeywords" placeholder="多个关键词以英文逗号隔开" />
|
||||
</a-form-item>
|
||||
<a-form-item label="自定义描述:">
|
||||
<a-input
|
||||
|
@ -156,11 +120,7 @@
|
|||
<div class="mb-4">
|
||||
<h3 class="post-setting-drawer-title">元数据</h3>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
v-for="(meta, index) in selectedMetas"
|
||||
:key="index"
|
||||
:prop="'meta.' + index + '.value'"
|
||||
>
|
||||
<a-form-item v-for="(meta, index) in selectedMetas" :key="index" :prop="'meta.' + index + '.value'">
|
||||
<a-row :gutter="5">
|
||||
<a-col :span="12">
|
||||
<a-input v-model="meta.key"><i slot="addonBefore">K</i></a-input>
|
||||
|
@ -168,11 +128,7 @@
|
|||
<a-col :span="12">
|
||||
<a-input v-model="meta.value">
|
||||
<i slot="addonBefore">V</i>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click.prevent="handleRemoveSheetMeta(meta)"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click.prevent="handleRemoveSheetMeta(meta)">
|
||||
<a-icon type="close" />
|
||||
</a>
|
||||
</a-input>
|
||||
|
@ -180,10 +136,7 @@
|
|||
</a-row>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="handleInsertSheetMeta()"
|
||||
>新增</a-button>
|
||||
<a-button type="dashed" @click="handleInsertSheetMeta()">新增</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
|
@ -191,20 +144,14 @@
|
|||
</div>
|
||||
<div class="bottom-control">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="advancedVisible = false"
|
||||
>返回</a-button>
|
||||
<a-button type="primary" @click="advancedVisible = false">返回</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
||||
<div class="bottom-control">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="advancedVisible = true"
|
||||
>高级</a-button>
|
||||
<a-button type="dashed" @click="advancedVisible = true">高级</a-button>
|
||||
<ReactiveButton
|
||||
type="danger"
|
||||
v-if="saveDraftButton"
|
||||
|
@ -221,9 +168,9 @@
|
|||
@callback="handleSavedCallback"
|
||||
:loading="saving"
|
||||
:errored="savedErrored"
|
||||
:text="`${selectedSheet.id?'保存':'发布'}`"
|
||||
:loadedText="`${selectedSheet.id?'保存':'发布'}成功`"
|
||||
:erroredText="`${selectedSheet.id?'保存':'发布'}失败`"
|
||||
:text="`${selectedSheet.id ? '保存' : '发布'}`"
|
||||
:loadedText="`${selectedSheet.id ? '保存' : '发布'}成功`"
|
||||
:erroredText="`${selectedSheet.id ? '保存' : '发布'}失败`"
|
||||
></ReactiveButton>
|
||||
</a-space>
|
||||
</div>
|
||||
|
@ -252,33 +199,33 @@ export default {
|
|||
saving: false,
|
||||
savedErrored: false,
|
||||
draftSaving: false,
|
||||
draftSavedErrored: false,
|
||||
draftSavedErrored: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
sheet: {
|
||||
type: Object,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
metas: {
|
||||
type: Array,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
needTitle: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
saveDraftButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
default: true
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
sheet(val) {
|
||||
|
@ -289,7 +236,7 @@ export default {
|
|||
},
|
||||
selectedMetas(val) {
|
||||
this.$emit('onRefreshSheetMetas', val)
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['options']),
|
||||
|
@ -318,7 +265,7 @@ export default {
|
|||
default:
|
||||
return ''
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAfterVisibleChanged(visible) {
|
||||
|
@ -330,13 +277,13 @@ export default {
|
|||
},
|
||||
handleListPresetMetasField() {
|
||||
if (this.metas.length <= 0) {
|
||||
themeApi.getActivatedTheme().then((response) => {
|
||||
themeApi.getActivatedTheme().then(response => {
|
||||
const fields = response.data.data.sheetMetaField
|
||||
if (fields && fields.length > 0) {
|
||||
for (let i = 0, len = fields.length; i < len; i++) {
|
||||
this.selectedMetas.push({
|
||||
value: '',
|
||||
key: fields[i],
|
||||
key: fields[i]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +294,7 @@ export default {
|
|||
this.customTplsLoading = true
|
||||
themeApi
|
||||
.customSheetTpls()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.customTpls = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -372,7 +319,7 @@ export default {
|
|||
if (!this.selectedSheet.title) {
|
||||
this.$notification['error']({
|
||||
message: '提示',
|
||||
description: '页面标题不能为空!',
|
||||
description: '页面标题不能为空!'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -408,7 +355,7 @@ export default {
|
|||
this.savedErrored = true
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.selectedSheet = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -431,7 +378,7 @@ export default {
|
|||
onClose() {
|
||||
this.$emit('close', false)
|
||||
},
|
||||
onSheetDateChange(value, dateString) {
|
||||
onSheetDateChange(value) {
|
||||
this.selectedSheet.createTime = value.valueOf()
|
||||
},
|
||||
onSheetDateOk(value) {
|
||||
|
@ -446,7 +393,7 @@ export default {
|
|||
handleInsertSheetMeta() {
|
||||
this.selectedMetas.push({
|
||||
value: '',
|
||||
key: '',
|
||||
key: ''
|
||||
})
|
||||
},
|
||||
handleSetPinyinSlug() {
|
||||
|
@ -455,7 +402,7 @@ export default {
|
|||
let result = ''
|
||||
const tokens = pinyin.parse(this.selectedSheet.title)
|
||||
let lastToken
|
||||
tokens.forEach((token, i) => {
|
||||
tokens.forEach(token => {
|
||||
if (token.type === 2) {
|
||||
const target = token.target ? token.target.toLowerCase() : ''
|
||||
result += result && !/\n|\s/.test(lastToken.target) ? '-' + target : target
|
||||
|
@ -467,7 +414,7 @@ export default {
|
|||
this.$set(this.selectedSheet, 'slug', result)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,52 +2,28 @@
|
|||
<page-view>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input
|
||||
v-model="list.queryParam.keyword"
|
||||
@keyup.enter="handleQuery()"
|
||||
/>
|
||||
<a-input v-model="list.queryParam.keyword" @keyup.enter="handleQuery()" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="状态:">
|
||||
<a-select
|
||||
placeholder="请选择状态"
|
||||
v-model="list.queryParam.type"
|
||||
@change="handleQuery()"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="type in Object.keys(list.journalType)"
|
||||
:key="type"
|
||||
:value="type"
|
||||
>{{ list.journalType[type].text }}</a-select-option>
|
||||
<a-select placeholder="请选择状态" v-model="list.queryParam.type" @change="handleQuery()">
|
||||
<a-select-option v-for="type in Object.keys(list.journalType)" :key="type" :value="type">{{
|
||||
list.journalType[type].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<span class="table-page-search-submitButtons">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleQuery()"
|
||||
>查询</a-button>
|
||||
<a-button type="primary" @click="handleQuery()">查询</a-button>
|
||||
<a-button @click="handleResetParam()">重置</a-button>
|
||||
</a-space>
|
||||
</span>
|
||||
|
@ -56,27 +32,13 @@
|
|||
</a-form>
|
||||
</div>
|
||||
<div class="table-operator">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="handleOpenPublishModal"
|
||||
>写日志</a-button>
|
||||
<a-button type="primary" icon="plus" @click="handleOpenPublishModal">写日志</a-button>
|
||||
</div>
|
||||
<a-divider />
|
||||
<div class="mt-4">
|
||||
<a-empty v-if="!list.loading && list.data.length==0" />
|
||||
<a-list
|
||||
v-else
|
||||
itemLayout="vertical"
|
||||
:pagination="false"
|
||||
:dataSource="list.data"
|
||||
:loading="list.loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-empty v-if="!list.loading && list.data.length == 0" />
|
||||
<a-list v-else itemLayout="vertical" :pagination="false" :dataSource="list.data" :loading="list.loading">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<span>
|
||||
<a href="javascript:void(0);">
|
||||
|
@ -85,19 +47,13 @@
|
|||
</a>
|
||||
</span>
|
||||
<span>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenJournalCommentsDrawer(item)"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="handleOpenJournalCommentsDrawer(item)">
|
||||
<a-icon type="message" />
|
||||
{{ item.commentCount }}
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="item.type=='INTIMATE'">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
disabled
|
||||
>
|
||||
<span v-if="item.type == 'INTIMATE'">
|
||||
<a href="javascript:void(0);" disabled>
|
||||
<a-icon type="lock" />
|
||||
</a>
|
||||
</span>
|
||||
|
@ -108,10 +64,7 @@
|
|||
</span>
|
||||
</template>
|
||||
<template slot="extra">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenEditModal(item)"
|
||||
>编辑</a>
|
||||
<a href="javascript:void(0);" @click="handleOpenEditModal(item)">编辑</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="你确定要删除这条日志?"
|
||||
|
@ -125,17 +78,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
|
||||
slot="avatar"
|
||||
size="large"
|
||||
:src="user.avatar"
|
||||
/>
|
||||
<a-avatar slot="avatar" size="large" :src="user.avatar" />
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<div class="page-wrapper">
|
||||
|
@ -163,33 +109,19 @@
|
|||
shape="circle"
|
||||
icon="setting"
|
||||
size="large"
|
||||
@click="optionModal.visible=true"
|
||||
@click="optionModal.visible = true"
|
||||
></a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
v-model="optionModal.visible"
|
||||
title="页面设置"
|
||||
:afterClose="() => optionModal.visible = false"
|
||||
>
|
||||
<a-modal v-model="optionModal.visible" title="页面设置" :afterClose="() => (optionModal.visible = false)">
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
@click="handleSaveOptions()"
|
||||
>保存</a-button>
|
||||
<a-button key="submit" type="primary" @click="handleSaveOptions()">保存</a-button>
|
||||
</template>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
label="页面标题:"
|
||||
help="* 需要主题进行适配"
|
||||
>
|
||||
<a-form-item label="页面标题:" help="* 需要主题进行适配">
|
||||
<a-input v-model="optionModal.options.journals_title" />
|
||||
</a-form-item>
|
||||
<a-form-item label="每页显示条数:">
|
||||
<a-input-number
|
||||
v-model="optionModal.options.journals_page_size"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="optionModal.options.journals_page_size" style="width:100%" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
@ -198,18 +130,12 @@
|
|||
<a-modal v-model="form.visible">
|
||||
<template slot="title">
|
||||
{{ formTitle }}
|
||||
<a-tooltip
|
||||
slot="action"
|
||||
title="只能输入250字"
|
||||
>
|
||||
<a-tooltip slot="action" title="只能输入250字">
|
||||
<a-icon type="info-circle-o" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="attachmentDrawer.visible = true"
|
||||
>附件库</a-button>
|
||||
<a-button type="dashed" @click="attachmentDrawer.visible = true">附件库</a-button>
|
||||
<ReactiveButton
|
||||
type="primary"
|
||||
@click="handleSaveOrUpdate"
|
||||
|
@ -221,12 +147,7 @@
|
|||
erroredText="发布失败"
|
||||
></ReactiveButton>
|
||||
</template>
|
||||
<a-form-model
|
||||
ref="journalForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model ref="journalForm" :model="form.model" :rules="form.rules" layout="vertical">
|
||||
<a-form-model-item prop="sourceContent">
|
||||
<a-input
|
||||
ref="sourceContentInput"
|
||||
|
@ -236,12 +157,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
<a-switch
|
||||
checkedChildren="公开"
|
||||
unCheckedChildren="私密"
|
||||
v-model="form.isPublic"
|
||||
defaultChecked
|
||||
/>
|
||||
<a-switch checkedChildren="公开" unCheckedChildren="私密" v-model="form.isPublic" defaultChecked />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
|
@ -278,40 +194,40 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
size: 10,
|
||||
sort: null,
|
||||
keyword: null,
|
||||
type: null,
|
||||
type: null
|
||||
},
|
||||
selected: {},
|
||||
|
||||
journalType: journalApi.journalType,
|
||||
journalType: journalApi.journalType
|
||||
},
|
||||
|
||||
form: {
|
||||
model: {},
|
||||
rules: {
|
||||
sourceContent: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }],
|
||||
sourceContent: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }]
|
||||
},
|
||||
visible: false,
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
isPublic: true,
|
||||
isPublic: true
|
||||
},
|
||||
journalCommentDrawer: {
|
||||
visible: false,
|
||||
visible: false
|
||||
},
|
||||
attachmentDrawer: {
|
||||
visible: false,
|
||||
visible: false
|
||||
},
|
||||
optionModal: {
|
||||
visible: false,
|
||||
options: [],
|
||||
},
|
||||
options: []
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
@ -322,7 +238,7 @@ export default {
|
|||
...mapGetters(['user']),
|
||||
formTitle() {
|
||||
return this.form.model.id ? '编辑' : '发表'
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['refreshOptionsCache']),
|
||||
|
@ -333,7 +249,7 @@ export default {
|
|||
this.list.queryParam.sort = this.list.pagination.sort
|
||||
journalApi
|
||||
.query(this.list.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.list.data = response.data.data.content
|
||||
this.list.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -344,7 +260,7 @@ export default {
|
|||
})
|
||||
},
|
||||
hanldeListOptions() {
|
||||
optionApi.listAll().then((response) => {
|
||||
optionApi.listAll().then(response => {
|
||||
this.optionModal.options = response.data.data
|
||||
})
|
||||
},
|
||||
|
@ -382,7 +298,7 @@ export default {
|
|||
},
|
||||
handleSaveOrUpdate() {
|
||||
const _this = this
|
||||
_this.$refs.journalForm.validate((valid) => {
|
||||
_this.$refs.journalForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.model.type = _this.form.isPublic ? 'PUBLIC' : 'INTIMATE'
|
||||
_this.form.saving = true
|
||||
|
@ -434,7 +350,7 @@ export default {
|
|||
handleSaveOptions() {
|
||||
optionApi
|
||||
.save(this.optionModal.options)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('保存成功!')
|
||||
this.optionModal.visible = false
|
||||
})
|
||||
|
@ -442,7 +358,7 @@ export default {
|
|||
this.hanldeListOptions()
|
||||
this.refreshOptionsCache()
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,35 +1,13 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="10"
|
||||
:lg="10"
|
||||
:md="10"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:title="title"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-form-model
|
||||
ref="linkForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="horizontal"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="网站名称:"
|
||||
prop="name"
|
||||
>
|
||||
<a-col :xl="10" :lg="10" :md="10" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :title="title" :bodyStyle="{ padding: '16px' }">
|
||||
<a-form-model ref="linkForm" :model="form.model" :rules="form.rules" layout="horizontal">
|
||||
<a-form-model-item label="网站名称:" prop="name">
|
||||
<a-input v-model="form.model.name" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="网站地址:"
|
||||
help="* 需要加上 http://"
|
||||
prop="url"
|
||||
>
|
||||
<a-form-model-item label="网站地址:" help="* 需要加上 http://" prop="url">
|
||||
<a-input v-model="form.model.url">
|
||||
<!-- <a
|
||||
href="javascript:void(0);"
|
||||
|
@ -40,41 +18,17 @@
|
|||
</a> -->
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="Logo:"
|
||||
prop="logo"
|
||||
>
|
||||
<a-form-model-item label="Logo:" prop="logo">
|
||||
<a-input v-model="form.model.logo" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="分组:"
|
||||
prop="team"
|
||||
>
|
||||
<a-auto-complete
|
||||
:dataSource="computedTeams"
|
||||
v-model="form.model.team"
|
||||
allowClear
|
||||
/>
|
||||
<a-form-model-item label="分组:" prop="team">
|
||||
<a-auto-complete :dataSource="computedTeams" v-model="form.model.team" allowClear />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="排序编号:"
|
||||
prop="priority"
|
||||
>
|
||||
<a-input-number
|
||||
:min="0"
|
||||
v-model="form.model.priority"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-form-model-item label="排序编号:" prop="priority">
|
||||
<a-input-number :min="0" v-model="form.model.priority" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="描述:"
|
||||
prop="description"
|
||||
>
|
||||
<a-input
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
v-model="form.model.description"
|
||||
/>
|
||||
<a-form-model-item label="描述:" prop="description">
|
||||
<a-input type="textarea" :autoSize="{ minRows: 5 }" v-model="form.model.description" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
<ReactiveButton
|
||||
|
@ -99,28 +53,14 @@
|
|||
loadedText="更新成功"
|
||||
erroredText="更新失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="form.model = {}"
|
||||
v-if="isUpdateMode"
|
||||
>返回添加</a-button>
|
||||
<a-button type="dashed" @click="form.model = {}" v-if="isUpdateMode">返回添加</a-button>
|
||||
</a-button-group>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="14"
|
||||
:lg="14"
|
||||
:md="14"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
title="所有友情链接"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-col :xl="14" :lg="14" :md="14" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card title="所有友情链接" :bodyStyle="{ padding: '16px' }">
|
||||
<!-- Mobile -->
|
||||
<a-list
|
||||
v-if="isMobile()"
|
||||
|
@ -129,25 +69,15 @@
|
|||
:dataSource="table.data"
|
||||
:loading="table.loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<template slot="actions">
|
||||
<a-dropdown
|
||||
placement="topLeft"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a-dropdown placement="topLeft" :trigger="['click']">
|
||||
<span>
|
||||
<a-icon type="bars" />
|
||||
</span>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="form.model = item"
|
||||
>编辑</a>
|
||||
<a href="javascript:void(0);" @click="form.model = item">编辑</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
|
@ -178,10 +108,7 @@
|
|||
{{ item.name }}
|
||||
</span>
|
||||
</a-list-item-meta>
|
||||
<a
|
||||
:href="item.url"
|
||||
target="_blank"
|
||||
>{{ item.url }}</a>
|
||||
<a :href="item.url" target="_blank">{{ item.url }}</a>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
<!-- Desktop -->
|
||||
|
@ -193,29 +120,12 @@
|
|||
:rowKey="link => link.id"
|
||||
:scrollToFirstRowOnChange="true"
|
||||
>
|
||||
<template
|
||||
slot="url"
|
||||
slot-scope="text"
|
||||
>
|
||||
<a
|
||||
target="_blank"
|
||||
:href="text"
|
||||
>{{ text }}</a>
|
||||
<template slot="url" slot-scope="text">
|
||||
<a target="_blank" :href="text">{{ text }}</a>
|
||||
</template>
|
||||
<ellipsis
|
||||
:length="15"
|
||||
tooltip
|
||||
slot="name"
|
||||
slot-scope="text"
|
||||
>{{ text }}</ellipsis>
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="form.model = record"
|
||||
>编辑</a>
|
||||
<ellipsis :length="15" tooltip slot="name" slot-scope="text">{{ text }}</ellipsis>
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<a href="javascript:void(0);" @click="form.model = record">编辑</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
:title="'你确定要删除【' + record.name + '】链接?'"
|
||||
|
@ -236,26 +146,15 @@
|
|||
shape="circle"
|
||||
icon="setting"
|
||||
size="large"
|
||||
@click="optionsModal.visible=true"
|
||||
@click="optionsModal.visible = true"
|
||||
></a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
v-model="optionsModal.visible"
|
||||
title="页面设置"
|
||||
:afterClose="() => optionsModal.visible = false"
|
||||
>
|
||||
<a-modal v-model="optionsModal.visible" title="页面设置" :afterClose="() => (optionsModal.visible = false)">
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
@click="handleSaveOptions()"
|
||||
>保存</a-button>
|
||||
<a-button key="submit" type="primary" @click="handleSaveOptions()">保存</a-button>
|
||||
</template>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
label="页面标题:"
|
||||
help="* 需要主题进行适配"
|
||||
>
|
||||
<a-form-item label="页面标题:" help="* 需要主题进行适配">
|
||||
<a-input v-model="optionsModal.data.links_title" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -274,40 +173,40 @@ const columns = [
|
|||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'name' },
|
||||
scopedSlots: { customRender: 'name' }
|
||||
},
|
||||
{
|
||||
title: '网址',
|
||||
dataIndex: 'url',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'url' },
|
||||
scopedSlots: { customRender: 'url' }
|
||||
},
|
||||
{
|
||||
title: '分组',
|
||||
ellipsis: true,
|
||||
dataIndex: 'team',
|
||||
dataIndex: 'team'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'priority',
|
||||
dataIndex: 'priority'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
mixins: [mixin, mixinDevice],
|
||||
components: {
|
||||
PageView,
|
||||
PageView
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
table: {
|
||||
columns,
|
||||
data: [],
|
||||
loading: false,
|
||||
loading: false
|
||||
},
|
||||
form: {
|
||||
model: {},
|
||||
|
@ -316,23 +215,23 @@ export default {
|
|||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '* 友情链接名称不能为空', trigger: ['change'] },
|
||||
{ max: 255, message: '* 友情链接名称的字符长度不能超过 255', trigger: ['change'] },
|
||||
{ max: 255, message: '* 友情链接名称的字符长度不能超过 255', trigger: ['change'] }
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: '* 友情链接地址不能为空', trigger: ['change'] },
|
||||
{ max: 1023, message: '* 友情链接地址的字符长度不能超过 1023', trigger: ['change'] },
|
||||
{ type: 'url', message: '* 友情链接地址格式有误', trigger: ['change'] },
|
||||
{ type: 'url', message: '* 友情链接地址格式有误', trigger: ['change'] }
|
||||
],
|
||||
logo: [{ max: 1023, message: '* 友情链接 Logo 的字符长度不能超过 1023', trigger: ['change'] }],
|
||||
description: [{ max: 255, message: '* 友情链接描述的字符长度不能超过 255', trigger: ['change'] }],
|
||||
team: [{ max: 255, message: '* 友情链接分组的字符长度 255', trigger: ['change'] }],
|
||||
},
|
||||
team: [{ max: 255, message: '* 友情链接分组的字符长度 255', trigger: ['change'] }]
|
||||
}
|
||||
},
|
||||
optionsModal: {
|
||||
visible: false,
|
||||
data: [],
|
||||
data: []
|
||||
},
|
||||
teams: [],
|
||||
teams: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -346,10 +245,10 @@ export default {
|
|||
return !!this.form.model.id
|
||||
},
|
||||
computedTeams() {
|
||||
return this.teams.filter((item) => {
|
||||
return this.teams.filter(item => {
|
||||
return item !== ''
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.handleListLinks()
|
||||
|
@ -362,7 +261,7 @@ export default {
|
|||
this.table.loading = true
|
||||
linkApi
|
||||
.listAll()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.table.data = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -372,19 +271,19 @@ export default {
|
|||
})
|
||||
},
|
||||
handleListLinkTeams() {
|
||||
linkApi.listTeams().then((response) => {
|
||||
linkApi.listTeams().then(response => {
|
||||
this.teams = response.data.data
|
||||
})
|
||||
},
|
||||
handleListOptions() {
|
||||
optionApi.listAll().then((response) => {
|
||||
optionApi.listAll().then(response => {
|
||||
this.optionsModal.data = response.data.data
|
||||
})
|
||||
},
|
||||
handleDeleteLink(id) {
|
||||
linkApi
|
||||
.delete(id)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -393,13 +292,13 @@ export default {
|
|||
})
|
||||
},
|
||||
handleParseUrl() {
|
||||
linkApi.getByParse(this.form.model.url).then((response) => {
|
||||
linkApi.getByParse(this.form.model.url).then(response => {
|
||||
this.form.model = response.data.data
|
||||
})
|
||||
},
|
||||
handleCreateOrUpdateLink() {
|
||||
const _this = this
|
||||
_this.$refs.linkForm.validate((valid) => {
|
||||
_this.$refs.linkForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.saving = true
|
||||
if (_this.isUpdateMode) {
|
||||
|
@ -429,19 +328,18 @@ export default {
|
|||
})
|
||||
},
|
||||
handleSavedCallback() {
|
||||
const _this = this
|
||||
if (_this.form.errored) {
|
||||
_this.form.errored = false
|
||||
if (this.form.errored) {
|
||||
this.form.errored = false
|
||||
} else {
|
||||
_this.form.model = {}
|
||||
_this.handleListLinks()
|
||||
_this.handleListLinkTeams()
|
||||
this.form.model = {}
|
||||
this.handleListLinks()
|
||||
this.handleListLinkTeams()
|
||||
}
|
||||
},
|
||||
handleSaveOptions() {
|
||||
optionApi
|
||||
.save(this.optionsModal.data)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('保存成功!')
|
||||
this.optionsModal.visible = false
|
||||
})
|
||||
|
@ -449,7 +347,7 @@ export default {
|
|||
this.handleListOptions()
|
||||
this.refreshOptionsCache()
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,56 +1,29 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row
|
||||
:gutter="12"
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-col
|
||||
:span="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-row :gutter="12" type="flex" align="middle">
|
||||
<a-col :span="24" class="pb-3">
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input v-model="list.queryParam.keyword" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="分组:">
|
||||
<a-select
|
||||
v-model="list.queryParam.team"
|
||||
@change="handleQuery()"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(item,index) in computedTeams"
|
||||
:key="index"
|
||||
:value="item"
|
||||
>{{ item }}</a-select-option>
|
||||
<a-select v-model="list.queryParam.team" @change="handleQuery()">
|
||||
<a-select-option v-for="(item, index) in computedTeams" :key="index" :value="item">{{
|
||||
item
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<span class="table-page-search-submitButtons">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleQuery()"
|
||||
>查询</a-button>
|
||||
<a-button type="primary" @click="handleQuery()">查询</a-button>
|
||||
<a-button @click="handleResetParam()">重置</a-button>
|
||||
</a-space>
|
||||
</span>
|
||||
|
@ -58,12 +31,8 @@
|
|||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="table-operator mb-0">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="form.visible = true"
|
||||
>添加</a-button>
|
||||
<div class="mb-0 table-operator">
|
||||
<a-button type="primary" icon="plus" @click="form.visible = true">添加</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
@ -73,28 +42,13 @@
|
|||
:dataSource="list.data"
|
||||
:loading="list.loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="item, index"
|
||||
:key="index"
|
||||
>
|
||||
<a-card
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
hoverable
|
||||
@click="handleOpenEditForm(item)"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index" :key="index">
|
||||
<a-card :bodyStyle="{ padding: 0 }" hoverable @click="handleOpenEditForm(item)">
|
||||
<div class="photo-thumb">
|
||||
<img
|
||||
:src="item.thumbnail"
|
||||
loading="lazy"
|
||||
>
|
||||
<img :src="item.thumbnail" loading="lazy" />
|
||||
</div>
|
||||
<a-card-meta class="p-3">
|
||||
<ellipsis
|
||||
:length="isMobile()?12:16"
|
||||
tooltip
|
||||
slot="description"
|
||||
>{{ item.name }}</ellipsis>
|
||||
<ellipsis :length="isMobile() ? 12 : 16" tooltip slot="description">{{ item.name }}</ellipsis>
|
||||
</a-card-meta>
|
||||
</a-card>
|
||||
</a-list-item>
|
||||
|
@ -106,7 +60,7 @@
|
|||
:current="list.pagination.page"
|
||||
:total="list.pagination.total"
|
||||
:defaultPageSize="list.pagination.size"
|
||||
:pageSizeOptions="['18', '36', '54','72','90','108']"
|
||||
:pageSizeOptions="['18', '36', '54', '72', '90', '108']"
|
||||
showSizeChanger
|
||||
@change="handlePaginationChange"
|
||||
@showSizeChange="handlePaginationChange"
|
||||
|
@ -114,88 +68,48 @@
|
|||
/>
|
||||
</div>
|
||||
<div style="position: fixed;bottom: 30px;right: 30px;">
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon="setting"
|
||||
size="large"
|
||||
@click="optionFormVisible=true"
|
||||
></a-button>
|
||||
<a-button type="primary" shape="circle" icon="setting" size="large" @click="optionFormVisible = true"></a-button>
|
||||
</div>
|
||||
<a-modal
|
||||
v-model="optionFormVisible"
|
||||
title="页面设置"
|
||||
:afterClose="() => optionFormVisible = false"
|
||||
>
|
||||
<a-modal v-model="optionFormVisible" title="页面设置" :afterClose="() => (optionFormVisible = false)">
|
||||
<template slot="footer">
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
@click="handleSaveOptions()"
|
||||
>保存</a-button>
|
||||
<a-button key="submit" type="primary" @click="handleSaveOptions()">保存</a-button>
|
||||
</template>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
label="页面标题:"
|
||||
help="* 需要主题进行适配"
|
||||
>
|
||||
<a-form-item label="页面标题:" help="* 需要主题进行适配">
|
||||
<a-input v-model="options.photos_title" />
|
||||
</a-form-item>
|
||||
<a-form-item label="每页显示条数:">
|
||||
<a-input-number
|
||||
v-model="options.photos_page_size"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.photos_page_size" style="width:100%" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<a-drawer
|
||||
:title="`图片${form.model.id?'修改':'添加'}`"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:title="`图片${form.model.id ? '修改' : '添加'}`"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="form.visible"
|
||||
destroyOnClose
|
||||
@close="onDrawerClose"
|
||||
>
|
||||
<a-form-model
|
||||
ref="photoForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model-item
|
||||
prop="url"
|
||||
label="图片地址:"
|
||||
>
|
||||
<a-form-model ref="photoForm" :model="form.model" :rules="form.rules" layout="vertical">
|
||||
<a-form-model-item prop="url" label="图片地址:">
|
||||
<div class="pb-2">
|
||||
<img
|
||||
:src="form.model.url || '/images/placeholder.jpg'"
|
||||
@click="attachmentSelectDrawer.visible = true"
|
||||
class="w-full cursor-pointer"
|
||||
style="border-radius:4px"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
<a-input
|
||||
v-model="form.model.url"
|
||||
placeholder="点击封面图选择图片,或者输入外部链接"
|
||||
/>
|
||||
<a-input v-model="form.model.url" placeholder="点击封面图选择图片,或者输入外部链接" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="thumbnail"
|
||||
label="缩略图地址:"
|
||||
>
|
||||
<a-form-model-item prop="thumbnail" label="缩略图地址:">
|
||||
<a-input v-model="form.model.thumbnail" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="name"
|
||||
label="图片名称:"
|
||||
>
|
||||
<a-form-model-item prop="name" label="图片名称:">
|
||||
<a-input v-model="form.model.name" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="takeTime"
|
||||
label="拍摄日期:"
|
||||
>
|
||||
<a-form-model-item prop="takeTime" label="拍摄日期:">
|
||||
<a-date-picker
|
||||
showTime
|
||||
:defaultValue="takeTimeDefaultValue"
|
||||
|
@ -205,32 +119,14 @@
|
|||
@ok="onTakeTimeSelect"
|
||||
/>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="location"
|
||||
label="拍摄地点:"
|
||||
>
|
||||
<a-form-model-item prop="location" label="拍摄地点:">
|
||||
<a-input v-model="form.model.location" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="team"
|
||||
label="分组:"
|
||||
>
|
||||
<a-auto-complete
|
||||
:dataSource="computedTeams"
|
||||
v-model="form.model.team"
|
||||
allowClear
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-form-model-item prop="team" label="分组:">
|
||||
<a-auto-complete :dataSource="computedTeams" v-model="form.model.team" allowClear style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="description"
|
||||
label="描述:"
|
||||
>
|
||||
<a-input
|
||||
v-model="form.model.description"
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
/>
|
||||
<a-form-model-item prop="description" label="描述:">
|
||||
<a-input v-model="form.model.description" type="textarea" :autoSize="{ minRows: 5 }" />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
<a-divider class="divider-transparent" />
|
||||
|
@ -241,9 +137,9 @@
|
|||
@callback="handleCreateOrUpdateCallback"
|
||||
:loading="form.saving"
|
||||
:errored="form.saveErrored"
|
||||
:text="`${form.model.id?'修改':'添加'}`"
|
||||
:loadedText="`${form.model.id?'修改':'添加'}成功`"
|
||||
:erroredText="`${form.model.id?'修改':'添加'}失败`"
|
||||
:text="`${form.model.id ? '修改' : '添加'}`"
|
||||
:loadedText="`${form.model.id ? '修改' : '添加'}成功`"
|
||||
:erroredText="`${form.model.id ? '修改' : '添加'}失败`"
|
||||
></ReactiveButton>
|
||||
<a-popconfirm
|
||||
title="你确定要删除该图片?"
|
||||
|
@ -295,15 +191,15 @@ export default {
|
|||
page: 1,
|
||||
size: 18,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
size: 18,
|
||||
sort: null,
|
||||
keyword: null,
|
||||
team: null,
|
||||
},
|
||||
team: null
|
||||
}
|
||||
},
|
||||
|
||||
form: {
|
||||
|
@ -312,21 +208,21 @@ export default {
|
|||
rules: {
|
||||
url: [{ required: true, message: '* 图片地址不能为空', trigger: ['change'] }],
|
||||
thumbnail: [{ required: true, message: '* 缩略图地址不能为空', trigger: ['change'] }],
|
||||
name: [{ required: true, message: '* 图片名称不能为空', trigger: ['change'] }],
|
||||
name: [{ required: true, message: '* 图片名称不能为空', trigger: ['change'] }]
|
||||
},
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
deleting: false,
|
||||
deleteErrored: false,
|
||||
deleteErrored: false
|
||||
},
|
||||
|
||||
attachmentSelectDrawer: {
|
||||
visible: false,
|
||||
visible: false
|
||||
},
|
||||
|
||||
optionFormVisible: false,
|
||||
teams: [],
|
||||
options: [],
|
||||
options: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -343,10 +239,10 @@ export default {
|
|||
return datetimeFormat(new Date(), 'YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
computedTeams() {
|
||||
return this.teams.filter((item) => {
|
||||
return this.teams.filter(item => {
|
||||
return item !== ''
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['refreshOptionsCache']),
|
||||
|
@ -357,7 +253,7 @@ export default {
|
|||
this.list.queryParam.sort = this.list.pagination.sort
|
||||
photoApi
|
||||
.query(this.list.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.list.data = response.data.data.content
|
||||
this.list.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -371,18 +267,18 @@ export default {
|
|||
this.handlePaginationChange(1, this.list.pagination.size)
|
||||
},
|
||||
hanldeListOptions() {
|
||||
optionApi.listAll().then((response) => {
|
||||
optionApi.listAll().then(response => {
|
||||
this.options = response.data.data
|
||||
})
|
||||
},
|
||||
hanldeListPhotoTeams() {
|
||||
photoApi.listTeams().then((response) => {
|
||||
photoApi.listTeams().then(response => {
|
||||
this.teams = response.data.data
|
||||
})
|
||||
},
|
||||
handleCreateOrUpdate() {
|
||||
const _this = this
|
||||
_this.$refs.photoForm.validate((valid) => {
|
||||
_this.$refs.photoForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.saving = true
|
||||
if (_this.form.model.id) {
|
||||
|
@ -472,7 +368,7 @@ export default {
|
|||
handleSaveOptions() {
|
||||
optionApi
|
||||
.save(this.options)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('保存成功!')
|
||||
this.optionFormVisible = false
|
||||
})
|
||||
|
@ -481,12 +377,12 @@ export default {
|
|||
this.refreshOptionsCache()
|
||||
})
|
||||
},
|
||||
onTakeTimeChange(value, dateString) {
|
||||
onTakeTimeChange(value) {
|
||||
this.form.model.takeTime = value.valueOf()
|
||||
},
|
||||
onTakeTimeSelect(value) {
|
||||
this.form.model.takeTime = value.valueOf()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,116 +2,69 @@
|
|||
<page-view>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
class="environment-info"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<a-card :bordered="false" class="environment-info" :bodyStyle="{ padding: '16px' }">
|
||||
<template slot="title">
|
||||
环境信息
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleCopyEnvironments"
|
||||
>
|
||||
<a href="javascript:void(0);" @click="handleCopyEnvironments">
|
||||
<a-icon type="copy" />
|
||||
</a>
|
||||
</template>
|
||||
<a-popover
|
||||
slot="extra"
|
||||
placement="left"
|
||||
:title="isLatest?'当前为最新版本':'有新版本'"
|
||||
>
|
||||
<a-popover slot="extra" placement="left" :title="isLatest ? '当前为最新版本' : '有新版本'">
|
||||
<template slot="content">
|
||||
<p>{{ versionMessage }}</p>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="handleShowVersionContent"
|
||||
>查看详情</a-button>
|
||||
<a-button type="dashed" @click="handleShowVersionContent">查看详情</a-button>
|
||||
</template>
|
||||
<a-button
|
||||
:loading="checking"
|
||||
type="dashed"
|
||||
shape="circle"
|
||||
:icon="isLatest?'check-circle':'exclamation-circle'"
|
||||
:icon="isLatest ? 'check-circle' : 'exclamation-circle'"
|
||||
></a-button>
|
||||
</a-popover>
|
||||
|
||||
<ul class="m-0 p-0 list-none">
|
||||
<ul class="p-0 m-0 list-none">
|
||||
<li>版本:{{ environments.version }}</li>
|
||||
<li>数据库:{{ environments.database }}</li>
|
||||
<li>运行模式:{{ environments.mode }}</li>
|
||||
<li>启动时间:{{ environments.startTime | moment }}</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://halo.run"
|
||||
target="_blank"
|
||||
class="mr-3"
|
||||
>官网
|
||||
<a href="https://halo.run" target="_blank" class="mr-3"
|
||||
>官网
|
||||
<a-icon type="link" />
|
||||
</a>
|
||||
<a
|
||||
href="https://docs.halo.run"
|
||||
target="_blank"
|
||||
class="mr-3"
|
||||
>文档
|
||||
<a href="https://docs.halo.run" target="_blank" class="mr-3"
|
||||
>文档
|
||||
<a-icon type="link" />
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/halo-dev"
|
||||
target="_blank"
|
||||
class="mr-3"
|
||||
>开源组织
|
||||
<a href="https://github.com/halo-dev" target="_blank" class="mr-3"
|
||||
>开源组织
|
||||
<a-icon type="link" />
|
||||
</a>
|
||||
<a
|
||||
href="https://bbs.halo.run"
|
||||
target="_blank"
|
||||
class="mr-3"
|
||||
>在线社区
|
||||
<a href="https://bbs.halo.run" target="_blank" class="mr-3"
|
||||
>在线社区
|
||||
<a-icon type="link" />
|
||||
</a>
|
||||
</a-card>
|
||||
|
||||
<a-card
|
||||
title="开发者"
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
:loading="contributorsLoading"
|
||||
>
|
||||
<a
|
||||
:href="item.html_url"
|
||||
v-for="(item,index) in contributors"
|
||||
:key="index"
|
||||
target="_blank"
|
||||
>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="item.login"
|
||||
>
|
||||
<a-avatar
|
||||
size="large"
|
||||
:src="item.avatar_url"
|
||||
:style="{ marginRight: '10px',marginBottom: '10px'}"
|
||||
/>
|
||||
<a-card title="开发者" :bordered="false" :bodyStyle="{ padding: '16px' }" :loading="contributorsLoading">
|
||||
<a :href="item.html_url" v-for="(item, index) in contributors" :key="index" target="_blank">
|
||||
<a-tooltip placement="top" :title="item.login">
|
||||
<a-avatar size="large" :src="item.avatar_url" :style="{ marginRight: '10px', marginBottom: '10px' }" />
|
||||
</a-tooltip>
|
||||
</a>
|
||||
</a-card>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
</a-col>
|
||||
<a-col :span="24"> </a-col>
|
||||
</a-row>
|
||||
|
||||
<a-modal
|
||||
:title="versionContentModalTitle"
|
||||
:visible="versionContentVisible"
|
||||
ok-text="查看更多"
|
||||
@cancel="versionContentVisible=false"
|
||||
@cancel="versionContentVisible = false"
|
||||
@ok="handleOpenVersionUrl"
|
||||
:width="620"
|
||||
>
|
||||
|
@ -127,7 +80,7 @@ import marked from 'marked'
|
|||
import { PageView } from '@/layouts'
|
||||
export default {
|
||||
components: {
|
||||
PageView,
|
||||
PageView
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -152,14 +105,14 @@ export default {
|
|||
received_events_url: '',
|
||||
type: '',
|
||||
site_admin: false,
|
||||
contributions: 0,
|
||||
},
|
||||
contributions: 0
|
||||
}
|
||||
],
|
||||
contributorsLoading: true,
|
||||
checking: false,
|
||||
isLatest: false,
|
||||
latestData: {},
|
||||
versionContentVisible: false,
|
||||
versionContentVisible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -177,7 +130,7 @@ export default {
|
|||
},
|
||||
versionContentModalTitle() {
|
||||
return `${this.latestData.name} 更新内容`
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getEnvironments()
|
||||
|
@ -185,7 +138,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async getEnvironments() {
|
||||
await adminApi.environments().then((response) => {
|
||||
await adminApi.environments().then(response => {
|
||||
this.environments = response.data.data
|
||||
})
|
||||
this.checkServerUpdate()
|
||||
|
@ -196,11 +149,11 @@ export default {
|
|||
运行模式:${this.environments.mode}
|
||||
User Agent:${navigator.userAgent}`
|
||||
this.$copyText(text)
|
||||
.then((message) => {
|
||||
.then(message => {
|
||||
this.$log.debug('copy', message)
|
||||
this.$message.success('复制成功!')
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
this.$log.debug('copy.err', err)
|
||||
this.$message.error('复制失败!')
|
||||
})
|
||||
|
@ -210,11 +163,11 @@ User Agent:${navigator.userAgent}`
|
|||
_this.contributorsLoading = true
|
||||
axios
|
||||
.get('https://api.github.com/repos/halo-dev/halo/contributors')
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
_this.contributors = response.data
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Fetch contributors error', error)
|
||||
_this.$log.error('Fetch contributors error', error)
|
||||
})
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
|
@ -227,7 +180,7 @@ User Agent:${navigator.userAgent}`
|
|||
_this.checking = true
|
||||
axios
|
||||
.get('https://api.github.com/repos/halo-dev/halo/releases/latest')
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
const data = response.data
|
||||
_this.latestData = data
|
||||
if (data.draft || data.prerelease) {
|
||||
|
@ -245,25 +198,25 @@ User Agent:${navigator.userAgent}`
|
|||
message: title,
|
||||
description: content,
|
||||
icon: <a-icon type="smile" style="color: #108ee9" />,
|
||||
btn: (h) => {
|
||||
btn: h => {
|
||||
return h(
|
||||
'a-button',
|
||||
{
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'small',
|
||||
size: 'small'
|
||||
},
|
||||
on: {
|
||||
click: () => this.handleShowVersionContent(),
|
||||
},
|
||||
click: () => this.handleShowVersionContent()
|
||||
}
|
||||
},
|
||||
'去看看'
|
||||
)
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Check update fail', error)
|
||||
this.$log.error('Check update fail', error)
|
||||
})
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
|
@ -290,7 +243,7 @@ User Agent:${navigator.userAgent}`
|
|||
return -1
|
||||
}
|
||||
return major * 1000000 + minor * 1000 + micro
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,34 +1,16 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-row
|
||||
type="flex"
|
||||
justify="center"
|
||||
align="middle"
|
||||
class="h-screen"
|
||||
>
|
||||
<a-col
|
||||
:xxl="8"
|
||||
:xl="12"
|
||||
:lg="16"
|
||||
:md="20"
|
||||
:sm="20"
|
||||
:xs="23"
|
||||
>
|
||||
<a-row type="flex" justify="center" align="middle" class="h-screen">
|
||||
<a-col :xxl="8" :xl="12" :lg="16" :md="20" :sm="20" :xs="23">
|
||||
<div class="card-container animated fadeIn">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
style="box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;"
|
||||
>
|
||||
<a-card :bordered="false" style="box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;">
|
||||
<div class="halo-logo">
|
||||
<span>Halo
|
||||
<span
|
||||
>Halo
|
||||
<small>安装向导</small>
|
||||
</span>
|
||||
</div>
|
||||
<a-alert
|
||||
:message="`欢迎使用 Halo,您正在安装的是 Halo ${VERSION}。`"
|
||||
type="success"
|
||||
show-icon
|
||||
/>
|
||||
<a-alert :message="`欢迎使用 Halo,您正在安装的是 Halo ${VERSION}。`" type="success" show-icon />
|
||||
<!-- Blogger info -->
|
||||
<div class="mt-5 mb-5">
|
||||
<a-radio-group v-model="installationMode">
|
||||
|
@ -48,111 +30,51 @@
|
|||
layout="horizontal"
|
||||
v-show="isInstallMode"
|
||||
>
|
||||
<a-divider
|
||||
orientation="left"
|
||||
dashed
|
||||
>
|
||||
<a-divider orientation="left" dashed>
|
||||
管理员信息
|
||||
</a-divider>
|
||||
<a-form-model-item prop="username">
|
||||
<a-input
|
||||
v-model="form.model.username"
|
||||
placeholder="用户名"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="user"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.username" placeholder="用户名">
|
||||
<a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item prop="username">
|
||||
<a-input
|
||||
v-model="form.model.nickname"
|
||||
placeholder="用户昵称"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="user"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.nickname" placeholder="用户昵称">
|
||||
<a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item prop="email">
|
||||
<a-input
|
||||
v-model="form.model.email"
|
||||
placeholder="用户邮箱"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="mail"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.email" placeholder="用户邮箱">
|
||||
<a-icon slot="prefix" type="mail" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item prop="password">
|
||||
<a-input
|
||||
v-model="form.model.password"
|
||||
type="password"
|
||||
placeholder="登录密码(8-100位)"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="lock"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.password" type="password" placeholder="登录密码(8-100位)">
|
||||
<a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item prop="confirmPassword">
|
||||
<a-input
|
||||
v-model="form.model.confirmPassword"
|
||||
type="password"
|
||||
placeholder="确认登录密码"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="lock"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.confirmPassword" type="password" placeholder="确认登录密码">
|
||||
<a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-divider
|
||||
orientation="left"
|
||||
dashed
|
||||
>
|
||||
<a-divider orientation="left" dashed>
|
||||
站点信息
|
||||
</a-divider>
|
||||
<a-form-model-item prop="url">
|
||||
<a-input
|
||||
v-model="form.model.url"
|
||||
placeholder="博客地址"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="link"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.url" placeholder="博客地址">
|
||||
<a-icon slot="prefix" type="link" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item prop="title">
|
||||
<a-input
|
||||
v-model="form.model.title"
|
||||
placeholder="博客标题"
|
||||
>
|
||||
<a-icon
|
||||
slot="prefix"
|
||||
type="book"
|
||||
style="color: rgba(0,0,0,.25)"
|
||||
/>
|
||||
<a-input v-model="form.model.title" placeholder="博客标题">
|
||||
<a-icon slot="prefix" type="book" style="color: rgba(0,0,0,.25)" />
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
|
||||
<!-- Data migration -->
|
||||
<div
|
||||
class="animated fadeIn"
|
||||
v-show="isImportMode"
|
||||
>
|
||||
<div class="animated fadeIn" v-show="isImportMode">
|
||||
<FilePondUpload
|
||||
ref="upload"
|
||||
name="file"
|
||||
|
@ -222,11 +144,11 @@ export default {
|
|||
rules: {
|
||||
username: [
|
||||
{ required: true, message: '* 用户名不能为空', trigger: ['change'] },
|
||||
{ max: 50, message: '* 用户名的字符长度不能超过 50', trigger: ['change'] },
|
||||
{ max: 50, message: '* 用户名的字符长度不能超过 50', trigger: ['change'] }
|
||||
],
|
||||
nickname: [
|
||||
{ required: true, message: '* 用户昵称不能为空', trigger: ['change'] },
|
||||
{ max: 255, message: '* 用户昵称的字符长度不能超过 255', trigger: ['change'] },
|
||||
{ max: 255, message: '* 用户昵称的字符长度不能超过 255', trigger: ['change'] }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: '* 电子邮件地址不能为空', trigger: ['change'] },
|
||||
|
@ -234,27 +156,27 @@ export default {
|
|||
{
|
||||
pattern: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/g,
|
||||
message: '* 电子邮件地址的格式不正确',
|
||||
trigger: ['change'],
|
||||
},
|
||||
trigger: ['change']
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '* 密码不能为空', trigger: ['change'] },
|
||||
{ min: 8, max: 100, message: '* 密码的字符长度必须在 8 - 100 之间', trigger: ['change'] },
|
||||
{ min: 8, max: 100, message: '* 密码的字符长度必须在 8 - 100 之间', trigger: ['change'] }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: '* 确认密码不能为空', trigger: ['change'] },
|
||||
{ validator: confirmPasswordValidate, trigger: ['change'] },
|
||||
{ validator: confirmPasswordValidate, trigger: ['change'] }
|
||||
],
|
||||
url: [{ required: true, message: '* 博客地址不能为空', trigger: ['change'] }],
|
||||
title: [{ required: true, message: '* 博客标题不能为空', trigger: ['change'] }],
|
||||
title: [{ required: true, message: '* 博客标题不能为空', trigger: ['change'] }]
|
||||
},
|
||||
installing: false,
|
||||
installErrored: false,
|
||||
|
||||
importing: false,
|
||||
importErrored: false,
|
||||
importData: null,
|
||||
},
|
||||
importData: null
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
@ -267,7 +189,7 @@ export default {
|
|||
},
|
||||
isImportMode() {
|
||||
return this.installationMode === 'import'
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['installCleanToken']),
|
||||
|
@ -278,11 +200,11 @@ export default {
|
|||
}
|
||||
},
|
||||
handleInstall() {
|
||||
this.$refs.installationForm.validate((valid) => {
|
||||
this.$refs.installationForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.form.installing = true
|
||||
this.installCleanToken(this.form.model)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.$log.debug('Installation response', response)
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -307,7 +229,7 @@ export default {
|
|||
onImportUpload(data) {
|
||||
this.$log.debug('Selected data', data)
|
||||
this.form.importData = data
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(resolve => {
|
||||
this.$log.debug('Handle uploading')
|
||||
resolve()
|
||||
})
|
||||
|
@ -320,7 +242,7 @@ export default {
|
|||
this.form.importing = true
|
||||
migrateApi
|
||||
.migrate(this.form.importData)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$log.debug('Migrated successfullly')
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -339,8 +261,8 @@ export default {
|
|||
this.$message.success('导入成功!')
|
||||
this.$router.push({ name: 'Login' })
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -1,157 +1,125 @@
|
|||
<template>
|
||||
<page-view :title="advancedOptions?'高级选项':'基础选项'">
|
||||
<page-view :title="advancedOptions ? '高级选项' : '基础选项'">
|
||||
<template slot="extra">
|
||||
<a-button
|
||||
type="link"
|
||||
@click="advancedOptions = !advancedOptions"
|
||||
style="padding:0"
|
||||
>
|
||||
切换到{{ advancedOptions?'基础选项':'高级选项' }}
|
||||
<a-button type="link" @click="advancedOptions = !advancedOptions" style="padding:0">
|
||||
切换到{{ advancedOptions ? '基础选项' : '高级选项' }}
|
||||
</a-button>
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div class="card-container">
|
||||
<a-tabs
|
||||
type="card"
|
||||
class="general"
|
||||
v-if="!advancedOptions"
|
||||
>
|
||||
<a-tabs type="card" class="general" v-if="!advancedOptions">
|
||||
<a-tab-pane key="general">
|
||||
<span slot="tab">
|
||||
<a-icon type="tool" />常规设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="tool" />常规设置 </span>
|
||||
<GeneralTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="seo">
|
||||
<span slot="tab">
|
||||
<a-icon type="global" />SEO 设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="global" />SEO 设置 </span>
|
||||
<SeoTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="post">
|
||||
<span slot="tab">
|
||||
<a-icon type="form" />文章设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="form" />文章设置 </span>
|
||||
<PostTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="comment">
|
||||
<span slot="tab">
|
||||
<a-icon type="message" />评论设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="message" />评论设置 </span>
|
||||
<CommentTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="attachment">
|
||||
<span slot="tab">
|
||||
<a-icon type="picture" />附件设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="picture" />附件设置 </span>
|
||||
<AttachmentTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="smtp">
|
||||
<span slot="tab">
|
||||
<a-icon type="mail" />SMTP 服务
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="mail" />SMTP 服务 </span>
|
||||
<SmtpTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="other">
|
||||
<span slot="tab">
|
||||
<a-icon type="align-left" />其他设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="align-left" />其他设置 </span>
|
||||
<OtherTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
<a-tabs
|
||||
type="card"
|
||||
class="advanced"
|
||||
v-else
|
||||
>
|
||||
<a-tabs type="card" class="advanced" v-else>
|
||||
<a-tab-pane key="permalink">
|
||||
<span slot="tab">
|
||||
<a-icon type="link" />固定链接
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="link" />固定链接 </span>
|
||||
<PermalinkTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="api">
|
||||
<span slot="tab">
|
||||
<a-icon type="api" />API 设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="api" />API 设置 </span>
|
||||
<ApiTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="advanced-other">
|
||||
<span slot="tab">
|
||||
<a-icon type="align-left" />其他设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="align-left" />其他设置 </span>
|
||||
<AdvancedOtherTab
|
||||
:options="options"
|
||||
@onChange="onOptionsChange"
|
||||
@onSave="onSaveOptions"
|
||||
:saving="saving"
|
||||
:errored="errored"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
@ -187,14 +155,14 @@ export default {
|
|||
OtherTab,
|
||||
PermalinkTab,
|
||||
ApiTab,
|
||||
AdvancedOtherTab,
|
||||
AdvancedOtherTab
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {},
|
||||
advancedOptions: false,
|
||||
saving: false,
|
||||
errored: false,
|
||||
errored: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -203,7 +171,7 @@ export default {
|
|||
methods: {
|
||||
...mapActions(['refreshUserCache', 'refreshOptionsCache']),
|
||||
hanldeListOptions() {
|
||||
optionApi.listAll().then((response) => {
|
||||
optionApi.listAll().then(response => {
|
||||
this.options = response.data.data
|
||||
})
|
||||
},
|
||||
|
@ -225,7 +193,7 @@ export default {
|
|||
this.refreshOptionsCache()
|
||||
this.refreshUserCache()
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,95 +1,42 @@
|
|||
<template>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
v-if="options.developer_mode"
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<div slot="title">
|
||||
<a-icon type="experiment" /> 开发者选项
|
||||
</div>
|
||||
<a-col v-if="options.developer_mode" :xl="6" :lg="6" :md="12" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div slot="title"><a-icon type="experiment" /> 开发者选项</div>
|
||||
<p style="min-height: 50px;">点击进入开发者选项页面</p>
|
||||
<a-button
|
||||
type="primary"
|
||||
class="float-right"
|
||||
@click="handleToDeveloperOptions()"
|
||||
>进入</a-button>
|
||||
<a-button type="primary" class="float-right" @click="handleToDeveloperOptions()">进入</a-button>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<div slot="title">
|
||||
<a-icon type="hdd" /> 博客备份
|
||||
</div>
|
||||
<a-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div slot="title"><a-icon type="hdd" /> 博客备份</div>
|
||||
<p style="min-height: 50px;">支持备份全站数据和数据导出,支持下载到本地</p>
|
||||
|
||||
<a-dropdown class="float-right">
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item
|
||||
key="1"
|
||||
@click="backupWorkDirDrawerVisible = true"
|
||||
>
|
||||
<a-menu-item key="1" @click="backupWorkDirDrawerVisible = true">
|
||||
整站备份
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="2"
|
||||
@click="exportDataDrawerVisible = true"
|
||||
>
|
||||
<a-menu-item key="2" @click="exportDataDrawerVisible = true">
|
||||
数据导出
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="3"
|
||||
@click="exportMarkdownDrawerVisible = true"
|
||||
>
|
||||
<a-menu-item key="3" @click="exportMarkdownDrawerVisible = true">
|
||||
导出文章为 Markdown 文档
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<a-button class="ml-2"> 备份
|
||||
<a-button class="ml-2">
|
||||
备份
|
||||
<a-icon type="down" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="6"
|
||||
:lg="6"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="pb-3"
|
||||
>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: '16px' }"
|
||||
>
|
||||
<div slot="title">
|
||||
<a-icon type="file-markdown" /> Markdown 文章导入
|
||||
</div>
|
||||
<a-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24" class="pb-3">
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: '16px' }">
|
||||
<div slot="title"><a-icon type="file-markdown" /> Markdown 文章导入</div>
|
||||
<p style="min-height: 50px;">支持 Hexo/Jekyll 文章导入并解析元数据</p>
|
||||
<a-button
|
||||
type="primary"
|
||||
class="float-right"
|
||||
@click="markdownUpload = true"
|
||||
>导入</a-button>
|
||||
<a-button type="primary" class="float-right" @click="markdownUpload = true">导入</a-button>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -131,11 +78,11 @@ export default {
|
|||
exportDataDrawerVisible: false,
|
||||
exportMarkdownDrawerVisible: false,
|
||||
markdownUpload: false,
|
||||
uploadHandler: backupApi.importMarkdown,
|
||||
uploadHandler: backupApi.importMarkdown
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['options']),
|
||||
...mapGetters(['options'])
|
||||
},
|
||||
methods: {
|
||||
handleChange(info) {
|
||||
|
@ -154,7 +101,7 @@ export default {
|
|||
},
|
||||
onUploadClose() {
|
||||
this.$refs.upload.handleClearFileList()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="整站备份"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-alert
|
||||
message="注意:备份后生成的压缩文件存储在临时文件中,重启服务器会造成备份文件的丢失,所以请尽快下载。"
|
||||
|
@ -19,16 +16,8 @@
|
|||
closable
|
||||
/>
|
||||
<a-divider>历史备份</a-divider>
|
||||
<a-list
|
||||
itemLayout="vertical"
|
||||
size="small"
|
||||
:dataSource="backups"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="backup"
|
||||
>
|
||||
<a-list itemLayout="vertical" size="small" :dataSource="backups" :loading="loading">
|
||||
<a-list-item slot="renderItem" slot-scope="backup">
|
||||
<a-button
|
||||
slot="extra"
|
||||
type="link"
|
||||
|
@ -36,17 +25,11 @@
|
|||
icon="delete"
|
||||
:loading="backup.deleting"
|
||||
@click="handleBackupDeleteClick(backup)"
|
||||
>删除</a-button>
|
||||
>删除</a-button
|
||||
>
|
||||
<a-list-item-meta>
|
||||
<a
|
||||
slot="title"
|
||||
href="javascript:void(0)"
|
||||
@click="handleDownloadBackupPackage(backup)"
|
||||
>
|
||||
<a-icon
|
||||
type="schedule"
|
||||
style="color: #52c41a"
|
||||
/>
|
||||
<a slot="title" href="javascript:void(0)" @click="handleDownloadBackupPackage(backup)">
|
||||
<a-icon type="schedule" style="color: #52c41a" />
|
||||
{{ backup.filename }}
|
||||
</a>
|
||||
<p slot="description">{{ backup.updateTime | timeAgo }}/{{ backup.fileSize | fileSizeFormat }}</p>
|
||||
|
@ -69,12 +52,7 @@
|
|||
loadedText="备份成功"
|
||||
erroredText="备份失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
type="dashed"
|
||||
icon="reload"
|
||||
:loading="loading"
|
||||
@click="handleListBackups"
|
||||
>刷新</a-button>
|
||||
<a-button type="dashed" icon="reload" :loading="loading" @click="handleListBackups">刷新</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
@ -90,19 +68,19 @@ export default {
|
|||
backuping: false,
|
||||
loading: false,
|
||||
backupErrored: false,
|
||||
backups: [],
|
||||
backups: []
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'visible',
|
||||
event: 'close',
|
||||
event: 'close'
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAfterVisibleChanged(visible) {
|
||||
|
@ -114,7 +92,7 @@ export default {
|
|||
this.loading = true
|
||||
backupApi
|
||||
.listWorkDirBackups()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.backups = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -155,7 +133,7 @@ export default {
|
|||
handleDownloadBackupPackage(item) {
|
||||
backupApi
|
||||
.fetchWorkDir(item.filename)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
var downloadElement = document.createElement('a')
|
||||
var href = new window.URL(response.data.data.downloadLink)
|
||||
downloadElement.href = href
|
||||
|
@ -165,13 +143,13 @@ export default {
|
|||
document.body.removeChild(downloadElement)
|
||||
window.URL.revokeObjectURL(href)
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
this.$message.error(error.data.message)
|
||||
})
|
||||
},
|
||||
onClose() {
|
||||
this.$emit('close', false)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="数据导出"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-alert
|
||||
message="注意:导出后的数据文件存储在临时文件中,重启服务器会造成备份文件的丢失,所以请尽快下载。"
|
||||
|
@ -19,16 +16,8 @@
|
|||
closable
|
||||
/>
|
||||
<a-divider>历史文件</a-divider>
|
||||
<a-list
|
||||
itemLayout="vertical"
|
||||
size="small"
|
||||
:dataSource="files"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="file"
|
||||
>
|
||||
<a-list itemLayout="vertical" size="small" :dataSource="files" :loading="loading">
|
||||
<a-list-item slot="renderItem" slot-scope="file">
|
||||
<a-button
|
||||
slot="extra"
|
||||
type="link"
|
||||
|
@ -36,17 +25,11 @@
|
|||
icon="delete"
|
||||
:loading="file.deleting"
|
||||
@click="handleFileDeleteClick(file)"
|
||||
>删除</a-button>
|
||||
>删除</a-button
|
||||
>
|
||||
<a-list-item-meta>
|
||||
<a
|
||||
slot="title"
|
||||
href="javascript:void(0)"
|
||||
@click="handleDownloadBackupFile(file)"
|
||||
>
|
||||
<a-icon
|
||||
type="schedule"
|
||||
style="color: #52c41a"
|
||||
/>
|
||||
<a slot="title" href="javascript:void(0)" @click="handleDownloadBackupFile(file)">
|
||||
<a-icon type="schedule" style="color: #52c41a" />
|
||||
{{ file.filename }}
|
||||
</a>
|
||||
<p slot="description">{{ file.updateTime | timeAgo }}/{{ file.fileSize | fileSizeFormat }}</p>
|
||||
|
@ -69,12 +52,7 @@
|
|||
loadedText="备份成功"
|
||||
erroredText="备份失败"
|
||||
></ReactiveButton>
|
||||
<a-button
|
||||
type="dashed"
|
||||
icon="reload"
|
||||
:loading="loading"
|
||||
@click="handleListBackups"
|
||||
>刷新</a-button>
|
||||
<a-button type="dashed" icon="reload" :loading="loading" @click="handleListBackups">刷新</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
@ -90,19 +68,19 @@ export default {
|
|||
backuping: false,
|
||||
loading: false,
|
||||
backupErrored: false,
|
||||
files: [],
|
||||
files: []
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'visible',
|
||||
event: 'close',
|
||||
event: 'close'
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAfterVisibleChanged(visible) {
|
||||
|
@ -114,7 +92,7 @@ export default {
|
|||
this.loading = true
|
||||
backupApi
|
||||
.listExportedData()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.files = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -155,7 +133,7 @@ export default {
|
|||
handleDownloadBackupFile(item) {
|
||||
backupApi
|
||||
.fetchData(item.filename)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
var downloadElement = document.createElement('a')
|
||||
var href = new window.URL(response.data.data.downloadLink)
|
||||
downloadElement.href = href
|
||||
|
@ -171,7 +149,7 @@ export default {
|
|||
},
|
||||
onClose() {
|
||||
this.$emit('close', false)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="导出文章为 Markdown 文档"
|
||||
:width="isMobile()?'100%':'480'"
|
||||
:width="isMobile() ? '100%' : '480'"
|
||||
closable
|
||||
:visible="visible"
|
||||
destroyOnClose
|
||||
@close="onClose"
|
||||
:afterVisibleChange="handleAfterVisibleChanged"
|
||||
>
|
||||
<a-row
|
||||
type="flex"
|
||||
align="middle"
|
||||
>
|
||||
<a-row type="flex" align="middle">
|
||||
<a-col :span="24">
|
||||
<a-alert
|
||||
message="注意:导出后的数据文件存储在临时文件中,重启服务器会造成备份文件的丢失,所以请尽快下载。"
|
||||
|
@ -19,16 +16,8 @@
|
|||
closable
|
||||
/>
|
||||
<a-divider>历史文件</a-divider>
|
||||
<a-list
|
||||
itemLayout="vertical"
|
||||
size="small"
|
||||
:dataSource="files"
|
||||
:loading="loading"
|
||||
>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="file"
|
||||
>
|
||||
<a-list itemLayout="vertical" size="small" :dataSource="files" :loading="loading">
|
||||
<a-list-item slot="renderItem" slot-scope="file">
|
||||
<a-button
|
||||
slot="extra"
|
||||
type="link"
|
||||
|
@ -36,17 +25,11 @@
|
|||
icon="delete"
|
||||
:loading="file.deleting"
|
||||
@click="handleFileDeleteClick(file)"
|
||||
>删除</a-button>
|
||||
>删除</a-button
|
||||
>
|
||||
<a-list-item-meta>
|
||||
<a
|
||||
slot="title"
|
||||
href="javascript:void(0)"
|
||||
@click="handleDownloadMarkdownPackage(file)"
|
||||
>
|
||||
<a-icon
|
||||
type="schedule"
|
||||
style="color: #52c41a"
|
||||
/>
|
||||
<a slot="title" href="javascript:void(0)" @click="handleDownloadMarkdownPackage(file)">
|
||||
<a-icon type="schedule" style="color: #52c41a" />
|
||||
{{ file.filename }}
|
||||
</a>
|
||||
<p slot="description">{{ file.updateTime | timeAgo }}/{{ file.fileSize | fileSizeFormat }}</p>
|
||||
|
@ -76,12 +59,7 @@
|
|||
erroredText="备份失败"
|
||||
></ReactiveButton>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
type="dashed"
|
||||
icon="reload"
|
||||
:loading="loading"
|
||||
@click="handleListBackups"
|
||||
>刷新</a-button>
|
||||
<a-button type="dashed" icon="reload" :loading="loading" @click="handleListBackups">刷新</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
@ -97,19 +75,19 @@ export default {
|
|||
backuping: false,
|
||||
loading: false,
|
||||
backupErrored: false,
|
||||
files: [],
|
||||
files: []
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'visible',
|
||||
event: 'close',
|
||||
event: 'close'
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
default: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAfterVisibleChanged(visible) {
|
||||
|
@ -121,7 +99,7 @@ export default {
|
|||
this.loading = true
|
||||
backupApi
|
||||
.listExportedMarkdowns()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.files = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -162,7 +140,7 @@ export default {
|
|||
handleDownloadMarkdownPackage(item) {
|
||||
backupApi
|
||||
.fetchMarkdown(item.filename)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
var downloadElement = document.createElement('a')
|
||||
var href = new window.URL(response.data.data.downloadLink)
|
||||
downloadElement.href = href
|
||||
|
@ -178,7 +156,7 @@ export default {
|
|||
},
|
||||
onClose() {
|
||||
this.$emit('close', false)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,39 +2,26 @@
|
|||
<page-view>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div
|
||||
class="card-container"
|
||||
v-if="options.developer_mode"
|
||||
>
|
||||
<div class="card-container" v-if="options.developer_mode">
|
||||
<a-tabs type="card">
|
||||
<a-tab-pane key="environment">
|
||||
<span slot="tab">
|
||||
<a-icon type="safety" />运行环境
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="safety" />运行环境 </span>
|
||||
<Environment />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="runtimeLogs">
|
||||
<span slot="tab">
|
||||
<a-icon type="code" />实时日志
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="code" />实时日志 </span>
|
||||
<RuntimeLogs />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="optionsList">
|
||||
<span slot="tab">
|
||||
<a-icon type="table" />系统变量
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="table" />系统变量 </span>
|
||||
<OptionsList />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="staticStorage">
|
||||
<span slot="tab">
|
||||
<a-icon type="cloud" />静态存储
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="cloud" />静态存储 </span>
|
||||
<StaticStorage />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="settings">
|
||||
<span slot="tab">
|
||||
<a-icon type="setting" />设置
|
||||
</span>
|
||||
<span slot="tab"> <a-icon type="setting" />设置 </span>
|
||||
<SettingsForm />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
@ -65,10 +52,10 @@ export default {
|
|||
RuntimeLogs,
|
||||
SettingsForm,
|
||||
OptionsList,
|
||||
StaticStorage,
|
||||
StaticStorage
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['options']),
|
||||
},
|
||||
...mapGetters(['options'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,20 +1,8 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="12"
|
||||
:lg="12"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
title="服务器"
|
||||
:bordered="false"
|
||||
hoverable
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card title="服务器" :bordered="false" hoverable :bodyStyle="{ padding: 0 }">
|
||||
<table class="w-full">
|
||||
<tbody class="ant-table-tbody">
|
||||
<tr>
|
||||
|
@ -46,20 +34,8 @@
|
|||
</a-card>
|
||||
<a-divider dashed />
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="12"
|
||||
:lg="12"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
title="使用情况"
|
||||
:bordered="false"
|
||||
hoverable
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card title="使用情况" :bordered="false" hoverable :bodyStyle="{ padding: 0 }">
|
||||
<table class="w-full">
|
||||
<tbody class="ant-table-tbody">
|
||||
<tr>
|
||||
|
@ -91,20 +67,8 @@
|
|||
</a-card>
|
||||
<a-divider dashed />
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="24"
|
||||
:lg="24"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
title="环境"
|
||||
:bordered="false"
|
||||
hoverable
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-col :xl="24" :lg="24" :md="24" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card title="环境" :bordered="false" hoverable :bodyStyle="{ padding: 0 }">
|
||||
<table class="w-full">
|
||||
<tbody class="ant-table-tbody">
|
||||
<tr>
|
||||
|
@ -118,10 +82,7 @@
|
|||
<tr>
|
||||
<td>Java Home</td>
|
||||
<td>
|
||||
<ellipsis
|
||||
:length="isMobile() ? 50 : 256"
|
||||
tooltip
|
||||
>
|
||||
<ellipsis :length="isMobile() ? 50 : 256" tooltip>
|
||||
{{ systemProperties['java.home'].value }}
|
||||
</ellipsis>
|
||||
</td>
|
||||
|
@ -131,20 +92,8 @@
|
|||
</a-card>
|
||||
<a-divider dashed />
|
||||
</a-col>
|
||||
<a-col
|
||||
:xl="24"
|
||||
:lg="24"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
class="mb-3"
|
||||
>
|
||||
<a-card
|
||||
title="应用"
|
||||
:bordered="false"
|
||||
hoverable
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-col :xl="24" :lg="24" :md="24" :sm="24" :xs="24" class="mb-3">
|
||||
<a-card title="应用" :bordered="false" hoverable :bodyStyle="{ padding: 0 }">
|
||||
<table class="w-full">
|
||||
<tbody class="ant-table-tbody">
|
||||
<tr>
|
||||
|
@ -161,15 +110,12 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>已启动时间</td>
|
||||
<td>{{ system.process.uptime | dayTime }} </td>
|
||||
<td>{{ system.process.uptime | dayTime }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启动目录</td>
|
||||
<td>
|
||||
<ellipsis
|
||||
:length="isMobile() ? 50 : 256"
|
||||
tooltip
|
||||
>
|
||||
<ellipsis :length="isMobile() ? 50 : 256" tooltip>
|
||||
{{ systemProperties['user.dir'].value }}
|
||||
</ellipsis>
|
||||
</td>
|
||||
|
@ -177,10 +123,7 @@
|
|||
<tr>
|
||||
<td>日志目录</td>
|
||||
<td>
|
||||
<ellipsis
|
||||
:length="isMobile() ? 50 : 256"
|
||||
tooltip
|
||||
>
|
||||
<ellipsis :length="isMobile() ? 50 : 256" tooltip>
|
||||
{{ systemProperties['LOG_FILE'].value }}
|
||||
</ellipsis>
|
||||
</td>
|
||||
|
@ -191,13 +134,7 @@
|
|||
</a-col>
|
||||
</a-row>
|
||||
<div style="position: fixed;bottom: 30px;right: 30px;">
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon="sync"
|
||||
size="large"
|
||||
@click="handleRefresh"
|
||||
></a-button>
|
||||
<a-button type="primary" shape="circle" icon="sync" size="large" @click="handleRefresh"></a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,53 +1,28 @@
|
|||
<template>
|
||||
<div class="option-tab-wrapper">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: 0 }">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="关键词:">
|
||||
<a-input
|
||||
v-model="queryParam.keyword"
|
||||
@keyup.enter="handleQuery()"
|
||||
/>
|
||||
<a-input v-model="queryParam.keyword" @keyup.enter="handleQuery()" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col
|
||||
:md="6"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="类型:">
|
||||
<a-select
|
||||
v-model="queryParam.type"
|
||||
placeholder="请选择类型"
|
||||
@change="handleQuery()"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in Object.keys(optionType)"
|
||||
:key="item"
|
||||
:value="item"
|
||||
>{{ optionType[item].text }}</a-select-option>
|
||||
<a-select v-model="queryParam.type" placeholder="请选择类型" @change="handleQuery()" allowClear>
|
||||
<a-select-option v-for="item in Object.keys(optionType)" :key="item" :value="item">{{
|
||||
optionType[item].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col
|
||||
:md="12"
|
||||
:sm="24"
|
||||
>
|
||||
<a-col :md="12" :sm="24">
|
||||
<span class="table-page-search-submitButtons">
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleQuery()"
|
||||
>查询</a-button>
|
||||
<a-button type="primary" @click="handleQuery()">查询</a-button>
|
||||
<a-button @click="handleResetParam()">重置</a-button>
|
||||
</a-space>
|
||||
</span>
|
||||
|
@ -56,11 +31,7 @@
|
|||
</a-form>
|
||||
</div>
|
||||
<div class="table-operator">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="handleOpenFormModal"
|
||||
>新增</a-button>
|
||||
<a-button type="primary" icon="plus" @click="handleOpenFormModal">新增</a-button>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<a-table
|
||||
|
@ -71,16 +42,10 @@
|
|||
:pagination="false"
|
||||
:scrollToFirstRowOnChange="true"
|
||||
>
|
||||
<span
|
||||
slot="type"
|
||||
slot-scope="typeProperty"
|
||||
>
|
||||
<span slot="type" slot-scope="typeProperty">
|
||||
{{ typeProperty.text }}
|
||||
</span>
|
||||
<span
|
||||
slot="createTime"
|
||||
slot-scope="createTime"
|
||||
>
|
||||
<span slot="createTime" slot-scope="createTime">
|
||||
<a-tooltip placement="top">
|
||||
<template slot="title">
|
||||
{{ createTime | moment }}
|
||||
|
@ -88,10 +53,7 @@
|
|||
{{ createTime | timeAgo }}
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span
|
||||
slot="updateTime"
|
||||
slot-scope="updateTime"
|
||||
>
|
||||
<span slot="updateTime" slot-scope="updateTime">
|
||||
<a-tooltip placement="top">
|
||||
<template slot="title">
|
||||
{{ updateTime | moment }}
|
||||
|
@ -99,14 +61,8 @@
|
|||
{{ updateTime | timeAgo }}
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenEditFormModal(record)"
|
||||
>编辑</a>
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<a href="javascript:void(0);" @click="handleOpenEditFormModal(record)">编辑</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
:title="'你确定要永久删除该变量?'"
|
||||
|
@ -133,11 +89,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
<a-modal
|
||||
v-model="form.visible"
|
||||
:title="formTitle"
|
||||
:afterClose="onFormClose"
|
||||
>
|
||||
<a-modal v-model="form.visible" :title="formTitle" :afterClose="onFormClose">
|
||||
<template slot="footer">
|
||||
<ReactiveButton
|
||||
@click="handleSaveOrUpdate"
|
||||
|
@ -155,30 +107,12 @@
|
|||
banner
|
||||
closable
|
||||
/>
|
||||
<a-form-model
|
||||
ref="optionForm"
|
||||
:model="form.model"
|
||||
:rules="form.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model-item
|
||||
prop="key"
|
||||
label="Key:"
|
||||
>
|
||||
<a-input
|
||||
ref="keyInput"
|
||||
v-model="form.model.key"
|
||||
/>
|
||||
<a-form-model ref="optionForm" :model="form.model" :rules="form.rules" layout="vertical">
|
||||
<a-form-model-item prop="key" label="Key:">
|
||||
<a-input ref="keyInput" v-model="form.model.key" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
prop="value"
|
||||
label="Value:"
|
||||
>
|
||||
<a-input
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
v-model="form.model.value"
|
||||
/>
|
||||
<a-form-model-item prop="value" label="Value:">
|
||||
<a-input type="textarea" :autoSize="{ minRows: 5 }" v-model="form.model.value" />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
|
@ -192,38 +126,38 @@ const columns = [
|
|||
title: 'Key',
|
||||
dataIndex: 'key',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'key' },
|
||||
scopedSlots: { customRender: 'key' }
|
||||
},
|
||||
{
|
||||
title: 'Value',
|
||||
dataIndex: 'value',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'value' },
|
||||
scopedSlots: { customRender: 'value' }
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'typeProperty',
|
||||
width: '100px',
|
||||
scopedSlots: { customRender: 'type' },
|
||||
scopedSlots: { customRender: 'type' }
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
width: '200px',
|
||||
scopedSlots: { customRender: 'createTime' },
|
||||
scopedSlots: { customRender: 'createTime' }
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
width: '200px',
|
||||
scopedSlots: { customRender: 'updateTime' },
|
||||
scopedSlots: { customRender: 'updateTime' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: '120px',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
name: 'OptionsList',
|
||||
|
@ -235,14 +169,14 @@ export default {
|
|||
page: 1,
|
||||
size: 10,
|
||||
sort: null,
|
||||
total: 1,
|
||||
total: 1
|
||||
},
|
||||
queryParam: {
|
||||
page: 0,
|
||||
size: 10,
|
||||
sort: null,
|
||||
keyword: null,
|
||||
type: null,
|
||||
type: null
|
||||
},
|
||||
loading: false,
|
||||
options: [],
|
||||
|
@ -252,23 +186,23 @@ export default {
|
|||
model: {},
|
||||
rules: {
|
||||
key: [{ required: true, message: '* Key 不能为空', trigger: ['change'] }],
|
||||
value: [{ required: true, message: '* Value 不能为空', trigger: ['change'] }],
|
||||
value: [{ required: true, message: '* Value 不能为空', trigger: ['change'] }]
|
||||
},
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
},
|
||||
saveErrored: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formattedDatas() {
|
||||
return this.options.map((option) => {
|
||||
return this.options.map(option => {
|
||||
option.typeProperty = this.optionType[option.type]
|
||||
return option
|
||||
})
|
||||
},
|
||||
formTitle() {
|
||||
return this.form.model.id ? '编辑' : '新增'
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.hanldeListOptions()
|
||||
|
@ -282,7 +216,7 @@ export default {
|
|||
this.queryParam.sort = this.pagination.sort
|
||||
optionApi
|
||||
.query(this.queryParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.options = response.data.data.content
|
||||
this.pagination.total = response.data.data.total
|
||||
})
|
||||
|
@ -298,7 +232,7 @@ export default {
|
|||
handleDeleteOption(id) {
|
||||
optionApi
|
||||
.delete(id)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -336,7 +270,7 @@ export default {
|
|||
},
|
||||
handleSaveOrUpdate() {
|
||||
const _this = this
|
||||
_this.$refs.optionForm.validate((valid) => {
|
||||
_this.$refs.optionForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.form.saving = true
|
||||
if (_this.form.model.id) {
|
||||
|
@ -375,7 +309,7 @@ export default {
|
|||
this.hanldeListOptions()
|
||||
this.refreshOptionsCache()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,35 +2,19 @@
|
|||
<a-form layout="vertical">
|
||||
<a-form-item>
|
||||
<a-spin :spinning="loading">
|
||||
<codemirror
|
||||
v-model="logContent"
|
||||
:options="codemirrorOptions"
|
||||
></codemirror>
|
||||
<codemirror v-model="logContent" :options="codemirrorOptions"></codemirror>
|
||||
</a-spin>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-select
|
||||
defaultValue="200"
|
||||
v-model="logLines"
|
||||
@change="handleLoadLogsLines"
|
||||
style="width: 100px"
|
||||
>
|
||||
<a-select defaultValue="200" v-model="logLines" @change="handleLoadLogsLines" style="width: 100px">
|
||||
<a-select-option value="200">200 行</a-select-option>
|
||||
<a-select-option value="500">500 行</a-select-option>
|
||||
<a-select-option value="800">800 行</a-select-option>
|
||||
<a-select-option value="1000">1000 行</a-select-option>
|
||||
</a-select>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleLoadLogsLines()"
|
||||
:loading="loading"
|
||||
>刷新</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="handleDownloadLogFile()"
|
||||
:loading="downloading"
|
||||
>下载</a-button>
|
||||
<a-button type="primary" @click="handleLoadLogsLines()" :loading="loading">刷新</a-button>
|
||||
<a-button type="dashed" @click="handleDownloadLogFile()" :loading="downloading">下载</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -43,7 +27,7 @@ import { datetimeFormat } from '@/utils/datetime'
|
|||
export default {
|
||||
name: 'RuntimeLogs',
|
||||
components: {
|
||||
codemirror,
|
||||
codemirror
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -51,12 +35,12 @@ export default {
|
|||
tabSize: 4,
|
||||
mode: 'shell',
|
||||
lineNumbers: true,
|
||||
line: true,
|
||||
line: true
|
||||
},
|
||||
logContent: '',
|
||||
loading: false,
|
||||
logLines: 200,
|
||||
downloading: false,
|
||||
downloading: false
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
@ -71,7 +55,7 @@ export default {
|
|||
this.loading = true
|
||||
adminApi
|
||||
.getLogFiles(this.logLines)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.logContent = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -85,7 +69,7 @@ export default {
|
|||
this.downloading = true
|
||||
adminApi
|
||||
.getLogFiles(this.logLines)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
var blob = new Blob([response.data.data])
|
||||
var downloadElement = document.createElement('a')
|
||||
var href = window.URL.createObjectURL(blob)
|
||||
|
@ -105,7 +89,7 @@ export default {
|
|||
hide()
|
||||
}, 400)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<a-form
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-item label="开发者选项:">
|
||||
<a-switch v-model="options.developer_mode" />
|
||||
</a-form-item>
|
||||
|
@ -10,7 +7,7 @@
|
|||
<ReactiveButton
|
||||
type="primary"
|
||||
@click="handleSaveOptions"
|
||||
@callback="errored=false"
|
||||
@callback="errored = false"
|
||||
:loading="saving"
|
||||
:errored="errored"
|
||||
text="保存"
|
||||
|
|
|
@ -1,26 +1,12 @@
|
|||
<template>
|
||||
<div class="option-tab-wrapper">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<a-card :bordered="false" :bodyStyle="{ padding: 0 }">
|
||||
<div class="table-operator">
|
||||
<a-button
|
||||
type="primary"
|
||||
icon="cloud-upload"
|
||||
@click="uploadModal.visible = true"
|
||||
>上传</a-button>
|
||||
<a-button
|
||||
icon="plus"
|
||||
@click="handleOpenCreateDirectoryModal({})"
|
||||
>
|
||||
<a-button type="primary" icon="cloud-upload" @click="uploadModal.visible = true">上传</a-button>
|
||||
<a-button icon="plus" @click="handleOpenCreateDirectoryModal({})">
|
||||
新建文件夹
|
||||
</a-button>
|
||||
<a-button
|
||||
icon="sync"
|
||||
@click="handleListStatics"
|
||||
:loading="list.loading"
|
||||
>
|
||||
<a-button icon="sync" @click="handleListStatics" :loading="list.loading">
|
||||
刷新
|
||||
</a-button>
|
||||
</div>
|
||||
|
@ -33,56 +19,27 @@
|
|||
size="middle"
|
||||
:loading="list.loading"
|
||||
>
|
||||
<span
|
||||
slot="name"
|
||||
slot-scope="name"
|
||||
>
|
||||
<ellipsis
|
||||
:length="64"
|
||||
tooltip
|
||||
>
|
||||
<span slot="name" slot-scope="name">
|
||||
<ellipsis :length="64" tooltip>
|
||||
{{ name }}
|
||||
</ellipsis>
|
||||
</span>
|
||||
<span
|
||||
slot="createTime"
|
||||
slot-scope="createTime"
|
||||
>
|
||||
<span slot="createTime" slot-scope="createTime">
|
||||
{{ createTime | moment }}
|
||||
</span>
|
||||
<span
|
||||
slot="action"
|
||||
slot-scope="text, record"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
v-if="!record.isFile"
|
||||
@click="handleUpload(record)"
|
||||
>上传</a>
|
||||
<a
|
||||
:href="options.blog_url+record.relativePath"
|
||||
target="_blank"
|
||||
v-else
|
||||
>访问</a>
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<a href="javascript:void(0);" v-if="!record.isFile" @click="handleUpload(record)">上传</a>
|
||||
<a :href="options.blog_url + record.relativePath" target="_blank" v-else>访问</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-dropdown :trigger="['click']">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
class="ant-dropdown-link"
|
||||
>更多</a>
|
||||
<a href="javascript:void(0);" class="ant-dropdown-link">更多</a>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item
|
||||
key="1"
|
||||
v-if="!record.isFile"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenCreateDirectoryModal(record)"
|
||||
>创建文件夹</a>
|
||||
<a-menu-item key="1" v-if="!record.isFile">
|
||||
<a href="javascript:void(0);" @click="handleOpenCreateDirectoryModal(record)">创建文件夹</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
<a-popconfirm
|
||||
:title="record.isFile?'你确定要删除该文件?':'你确定要删除该文件夹?'"
|
||||
:title="record.isFile ? '你确定要删除该文件?' : '你确定要删除该文件夹?'"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
@confirm="handleDelete(record.relativePath)"
|
||||
|
@ -91,19 +48,10 @@
|
|||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="3">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenRenameModal(record)"
|
||||
>重命名</a>
|
||||
<a href="javascript:void(0);" @click="handleOpenRenameModal(record)">重命名</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="4"
|
||||
v-if="record.isFile"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
@click="handleOpenEditContentModal(record)"
|
||||
>编辑</a>
|
||||
<a-menu-item key="4" v-if="record.isFile">
|
||||
<a href="javascript:void(0);" @click="handleOpenEditContentModal(record)">编辑</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
|
@ -125,11 +73,7 @@
|
|||
:filed="list.selected.relativePath"
|
||||
></FilePondUpload>
|
||||
</a-modal>
|
||||
<a-modal
|
||||
v-model="directoryForm.visible"
|
||||
:afterClose="onDirectoryFormModalClose"
|
||||
title="创建文件夹"
|
||||
>
|
||||
<a-modal v-model="directoryForm.visible" :afterClose="onDirectoryFormModalClose" title="创建文件夹">
|
||||
<template slot="footer">
|
||||
<ReactiveButton
|
||||
@click="handleCreateDirectory"
|
||||
|
@ -141,29 +85,13 @@
|
|||
erroredText="创建失败"
|
||||
></ReactiveButton>
|
||||
</template>
|
||||
<a-form-model
|
||||
ref="directoryForm"
|
||||
:model="directoryForm.model"
|
||||
:rules="directoryForm.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model-item
|
||||
prop="name"
|
||||
label="文件夹名:"
|
||||
>
|
||||
<a-input
|
||||
ref="createDirectoryInput"
|
||||
v-model="directoryForm.model.name"
|
||||
@keyup.enter="handleCreateDirectory"
|
||||
/>
|
||||
<a-form-model ref="directoryForm" :model="directoryForm.model" :rules="directoryForm.rules" layout="vertical">
|
||||
<a-form-model-item prop="name" label="文件夹名:">
|
||||
<a-input ref="createDirectoryInput" v-model="directoryForm.model.name" @keyup.enter="handleCreateDirectory" />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
<a-modal
|
||||
v-model="renameForm.visible"
|
||||
:afterClose="onRenameModalClose"
|
||||
title="重命名"
|
||||
>
|
||||
<a-modal v-model="renameForm.visible" :afterClose="onRenameModalClose" title="重命名">
|
||||
<template slot="footer">
|
||||
<ReactiveButton
|
||||
@click="handleRenameDirectoryOrFile"
|
||||
|
@ -175,21 +103,9 @@
|
|||
erroredText="重命名失败"
|
||||
></ReactiveButton>
|
||||
</template>
|
||||
<a-form-model
|
||||
ref="renameForm"
|
||||
:model="renameForm.model"
|
||||
:rules="renameForm.rules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-model-item
|
||||
prop="name"
|
||||
:label="list.selected.isFile?'文件名:':'文件夹名:'"
|
||||
>
|
||||
<a-input
|
||||
ref="renameModalInput"
|
||||
v-model="renameForm.model.name"
|
||||
@keyup.enter="handleRenameDirectoryOrFile"
|
||||
/>
|
||||
<a-form-model ref="renameForm" :model="renameForm.model" :rules="renameForm.rules" layout="vertical">
|
||||
<a-form-model-item prop="name" :label="list.selected.isFile ? '文件名:' : '文件夹名:'">
|
||||
<a-input ref="renameModalInput" v-model="renameForm.model.name" @keyup.enter="handleRenameDirectoryOrFile" />
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
|
@ -243,29 +159,29 @@ const columns = [
|
|||
{
|
||||
title: '文件名',
|
||||
dataIndex: 'name',
|
||||
scopedSlots: { customRender: 'name' },
|
||||
scopedSlots: { customRender: 'name' }
|
||||
},
|
||||
{
|
||||
title: '文件类型',
|
||||
dataIndex: 'mimeType',
|
||||
scopedSlots: { customRender: 'mimeType' },
|
||||
scopedSlots: { customRender: 'mimeType' }
|
||||
},
|
||||
{
|
||||
title: '上传时间',
|
||||
dataIndex: 'createTime',
|
||||
width: '200px',
|
||||
scopedSlots: { customRender: 'createTime' },
|
||||
scopedSlots: { customRender: 'createTime' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: '120px',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
export default {
|
||||
components: {
|
||||
codemirror,
|
||||
codemirror
|
||||
},
|
||||
name: 'StaticStorage',
|
||||
data() {
|
||||
|
@ -274,41 +190,41 @@ export default {
|
|||
columns: columns,
|
||||
data: [],
|
||||
loading: false,
|
||||
selected: {},
|
||||
selected: {}
|
||||
},
|
||||
|
||||
uploadModal: {
|
||||
visible: false,
|
||||
uploadHandler: staticApi.upload,
|
||||
uploadHandler: staticApi.upload
|
||||
},
|
||||
|
||||
directoryForm: {
|
||||
model: {
|
||||
name: null,
|
||||
name: null
|
||||
},
|
||||
visible: false,
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
rules: {
|
||||
name: [{ required: true, message: '* 文件夹名不能为空', trigger: ['change'] }],
|
||||
},
|
||||
name: [{ required: true, message: '* 文件夹名不能为空', trigger: ['change'] }]
|
||||
}
|
||||
},
|
||||
|
||||
renameForm: {
|
||||
model: {
|
||||
name: null,
|
||||
name: null
|
||||
},
|
||||
visible: false,
|
||||
saving: false,
|
||||
saveErrored: false,
|
||||
rules: {
|
||||
name: [{ required: true, message: '* 文件夹名不能为空', trigger: ['change'] }],
|
||||
},
|
||||
name: [{ required: true, message: '* 文件夹名不能为空', trigger: ['change'] }]
|
||||
}
|
||||
},
|
||||
|
||||
editContentForm: {
|
||||
model: {
|
||||
content: null,
|
||||
content: null
|
||||
},
|
||||
visible: false,
|
||||
saving: false,
|
||||
|
@ -318,10 +234,10 @@ export default {
|
|||
options: {
|
||||
tabSize: 4,
|
||||
lineNumbers: true,
|
||||
line: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
line: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
@ -336,14 +252,14 @@ export default {
|
|||
return data.sort(function(a, b) {
|
||||
return a.isFile - b.isFile
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleListStatics() {
|
||||
this.list.loading = true
|
||||
staticApi
|
||||
.list()
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.list.data = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -355,7 +271,7 @@ export default {
|
|||
handleDelete(path) {
|
||||
staticApi
|
||||
.delete(path)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
this.$message.success(`删除成功!`)
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -376,7 +292,7 @@ export default {
|
|||
},
|
||||
handleCreateDirectory() {
|
||||
const _this = this
|
||||
_this.$refs.directoryForm.validate((valid) => {
|
||||
_this.$refs.directoryForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.directoryForm.saving = true
|
||||
staticApi
|
||||
|
@ -419,7 +335,7 @@ export default {
|
|||
},
|
||||
handleRenameDirectoryOrFile() {
|
||||
const _this = this
|
||||
_this.$refs.renameForm.validate((valid) => {
|
||||
_this.$refs.renameForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.renameForm.saving = true
|
||||
staticApi
|
||||
|
@ -449,7 +365,7 @@ export default {
|
|||
_this.list.selected = file
|
||||
const arr = file.name.split('.')
|
||||
const postfix = arr[arr.length - 1]
|
||||
staticApi.getContent(_this.options.blog_url + file.relativePath).then((response) => {
|
||||
staticApi.getContent(_this.options.blog_url + file.relativePath).then(response => {
|
||||
_this.editContentForm.model.content = response.data
|
||||
const info = _this.editContentForm.codeMirror.instance.findModeByExtension(postfix)
|
||||
if (info === undefined) {
|
||||
|
@ -503,7 +419,7 @@ export default {
|
|||
this.editContentForm.visible = false
|
||||
this.list.selected = {}
|
||||
this.editContentForm.model.content = ''
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="advancedOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model ref="advancedOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item
|
||||
label="全局绝对路径:"
|
||||
help="* 对网站上面的所有页面路径、本地附件路径、以及主题中的静态资源路径有效。"
|
||||
|
|
|
@ -1,23 +1,11 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="apiOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model ref="apiOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="API 服务:">
|
||||
<a-switch v-model="options.api_enabled" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="Access key:"
|
||||
prop="api_access_key"
|
||||
>
|
||||
<a-input-password
|
||||
v-model="options.api_access_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-form-model-item label="Access key:" prop="api_access_key">
|
||||
<a-input-password v-model="options.api_access_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
<ReactiveButton
|
||||
|
@ -77,7 +65,7 @@ export default {
|
|||
methods: {
|
||||
handleSaveOptions() {
|
||||
const _this = this
|
||||
_this.$refs.apiOptionsForm.validate((valid) => {
|
||||
_this.$refs.apiOptionsForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.$emit('onSave')
|
||||
}
|
||||
|
|
|
@ -11,32 +11,19 @@
|
|||
<a-switch v-model="options.attachment_upload_image_preview_enable" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="最大上传文件数:">
|
||||
<a-input-number
|
||||
v-model="options.attachment_upload_max_files"
|
||||
:min="1"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.attachment_upload_max_files" :min="1" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="同时上传文件数:">
|
||||
<a-input-number
|
||||
v-model="options.attachment_upload_max_parallel_uploads"
|
||||
:min="1"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.attachment_upload_max_parallel_uploads" :min="1" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="存储位置:">
|
||||
<a-select v-model="options.attachment_type">
|
||||
<a-select-option
|
||||
v-for="item in Object.keys(attachmentType)"
|
||||
:key="item"
|
||||
:value="item"
|
||||
>{{ attachmentType[item].text }}</a-select-option>
|
||||
<a-select-option v-for="item in Object.keys(attachmentType)" :key="item" :value="item">{{
|
||||
attachmentType[item].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-model-item>
|
||||
<div
|
||||
id="smmsForm"
|
||||
v-show="options.attachment_type === 'SMMS'"
|
||||
>
|
||||
<div id="smmsForm" v-show="options.attachment_type === 'SMMS'">
|
||||
<a-form-model-item label="Secret Token:">
|
||||
<a-input-password
|
||||
v-model="options.smms_api_secret_token"
|
||||
|
@ -45,10 +32,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="upOssForm"
|
||||
v-show="options.attachment_type === 'UPOSS'"
|
||||
>
|
||||
<div id="upOssForm" v-show="options.attachment_type === 'UPOSS'">
|
||||
<a-form-model-item label="绑定域名协议:">
|
||||
<a-select v-model="options.oss_upyun_domain_protocol">
|
||||
<a-select-option value="https://">HTTPS</a-select-option>
|
||||
|
@ -56,10 +40,7 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="绑定域名:">
|
||||
<a-input
|
||||
v-model="options.oss_upyun_domain"
|
||||
placeholder="无需再加上 http:// 或者 https://"
|
||||
/>
|
||||
<a-input v-model="options.oss_upyun_domain" placeholder="无需再加上 http:// 或者 https://" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="空间名称:">
|
||||
<a-input v-model="options.oss_upyun_bucket" />
|
||||
|
@ -68,19 +49,13 @@
|
|||
<a-input v-model="options.oss_upyun_operator" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="操作员密码:">
|
||||
<a-input-password
|
||||
v-model="options.oss_upyun_password"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.oss_upyun_password" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件目录:">
|
||||
<a-input v-model="options.oss_upyun_source" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="图片处理策略:">
|
||||
<a-input
|
||||
v-model="options.oss_upyun_style_rule"
|
||||
placeholder="间隔标识符+图片处理版本名称"
|
||||
/>
|
||||
<a-input v-model="options.oss_upyun_style_rule" placeholder="间隔标识符+图片处理版本名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="缩略图处理策略:">
|
||||
<a-input
|
||||
|
@ -89,10 +64,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="qiniuOssForm"
|
||||
v-show="options.attachment_type === 'QINIUOSS'"
|
||||
>
|
||||
<div id="qiniuOssForm" v-show="options.attachment_type === 'QINIUOSS'">
|
||||
<a-form-model-item label="绑定域名协议:">
|
||||
<a-select v-model="options.oss_qiniu_domain_protocol">
|
||||
<a-select-option value="https://">HTTPS</a-select-option>
|
||||
|
@ -100,47 +72,25 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="绑定域名:">
|
||||
<a-input
|
||||
v-model="options.oss_qiniu_domain"
|
||||
placeholder="无需再加上 http:// 或者 https://"
|
||||
/>
|
||||
<a-input v-model="options.oss_qiniu_domain" placeholder="无需再加上 http:// 或者 https://" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="区域:">
|
||||
<a-auto-complete
|
||||
:dataSource="qiniuOssZones"
|
||||
v-model="options.oss_qiniu_zone"
|
||||
allowClear
|
||||
/>
|
||||
<a-auto-complete :dataSource="qiniuOssZones" v-model="options.oss_qiniu_zone" allowClear />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Key:">
|
||||
<a-input-password
|
||||
v-model="options.oss_qiniu_access_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.oss_qiniu_access_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Secret Key:">
|
||||
<a-input-password
|
||||
v-model="options.oss_qiniu_secret_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.oss_qiniu_secret_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件目录:">
|
||||
<a-input
|
||||
v-model="options.oss_qiniu_source"
|
||||
placeholder="不填写则上传到根目录"
|
||||
/>
|
||||
<a-input v-model="options.oss_qiniu_source" placeholder="不填写则上传到根目录" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Bucket:">
|
||||
<a-input
|
||||
v-model="options.oss_qiniu_bucket"
|
||||
placeholder="存储空间名称"
|
||||
/>
|
||||
<a-input v-model="options.oss_qiniu_bucket" placeholder="存储空间名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="图片处理策略:">
|
||||
<a-input
|
||||
v-model="options.oss_qiniu_style_rule"
|
||||
placeholder="样式分隔符+图片处理样式名称"
|
||||
/>
|
||||
<a-input v-model="options.oss_qiniu_style_rule" placeholder="样式分隔符+图片处理样式名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="缩略图处理策略:">
|
||||
<a-input
|
||||
|
@ -149,10 +99,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="aliOssForm"
|
||||
v-show="options.attachment_type === 'ALIOSS'"
|
||||
>
|
||||
<div id="aliOssForm" v-show="options.attachment_type === 'ALIOSS'">
|
||||
<a-form-model-item label="绑定域名协议:">
|
||||
<a-select v-model="options.oss_ali_domain_protocol">
|
||||
<a-select-option value="https://">HTTPS</a-select-option>
|
||||
|
@ -160,43 +107,25 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="绑定域名:">
|
||||
<a-input
|
||||
v-model="options.oss_ali_domain"
|
||||
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
|
||||
/>
|
||||
<a-input v-model="options.oss_ali_domain" placeholder="如不填写,路径根域名将为 Bucket + EndPoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Bucket:">
|
||||
<a-input
|
||||
v-model="options.oss_ali_bucket_name"
|
||||
placeholder="存储空间名称"
|
||||
/>
|
||||
<a-input v-model="options.oss_ali_bucket_name" placeholder="存储空间名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="EndPoint(地域节点):">
|
||||
<a-input v-model="options.oss_ali_endpoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Key:">
|
||||
<a-input-password
|
||||
v-model="options.oss_ali_access_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.oss_ali_access_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Secret:">
|
||||
<a-input-password
|
||||
v-model="options.oss_ali_access_secret"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.oss_ali_access_secret" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件目录:">
|
||||
<a-input
|
||||
v-model="options.oss_ali_source"
|
||||
placeholder="不填写则上传到根目录"
|
||||
/>
|
||||
<a-input v-model="options.oss_ali_source" placeholder="不填写则上传到根目录" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="图片处理策略:">
|
||||
<a-input
|
||||
v-model="options.oss_ali_style_rule"
|
||||
placeholder="请到阿里云控制台的图片处理获取"
|
||||
/>
|
||||
<a-input v-model="options.oss_ali_style_rule" placeholder="请到阿里云控制台的图片处理获取" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="缩略图处理策略:">
|
||||
<a-input
|
||||
|
@ -205,10 +134,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="baiduBosForm"
|
||||
v-show="options.attachment_type === 'BAIDUBOS'"
|
||||
>
|
||||
<div id="baiduBosForm" v-show="options.attachment_type === 'BAIDUBOS'">
|
||||
<a-form-model-item label="绑定域名协议:">
|
||||
<a-select v-model="options.bos_baidu_domain_protocol">
|
||||
<a-select-option value="https://">HTTPS</a-select-option>
|
||||
|
@ -216,37 +142,22 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="绑定域名:">
|
||||
<a-input
|
||||
v-model="options.bos_baidu_domain"
|
||||
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
|
||||
/>
|
||||
<a-input v-model="options.bos_baidu_domain" placeholder="如不填写,路径根域名将为 Bucket + EndPoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Bucket:">
|
||||
<a-input
|
||||
v-model="options.bos_baidu_bucket_name"
|
||||
placeholder="存储空间名称"
|
||||
/>
|
||||
<a-input v-model="options.bos_baidu_bucket_name" placeholder="存储空间名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="EndPoint(地域节点):">
|
||||
<a-input v-model="options.bos_baidu_endpoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Key:">
|
||||
<a-input-password
|
||||
v-model="options.bos_baidu_access_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.bos_baidu_access_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Secret Key:">
|
||||
<a-input-password
|
||||
v-model="options.bos_baidu_secret_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.bos_baidu_secret_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="图片处理策略:">
|
||||
<a-input
|
||||
v-model="options.bos_baidu_style_rule"
|
||||
placeholder="请到百度云控制台的图片处理获取"
|
||||
/>
|
||||
<a-input v-model="options.bos_baidu_style_rule" placeholder="请到百度云控制台的图片处理获取" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="缩略图处理策略:">
|
||||
<a-input
|
||||
|
@ -255,10 +166,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="tencentCosForm"
|
||||
v-show="options.attachment_type === 'TENCENTCOS'"
|
||||
>
|
||||
<div id="tencentCosForm" v-show="options.attachment_type === 'TENCENTCOS'">
|
||||
<a-form-model-item label="绑定域名协议:">
|
||||
<a-select v-model="options.cos_tencent_domain_protocol">
|
||||
<a-select-option value="https://">HTTPS</a-select-option>
|
||||
|
@ -266,47 +174,25 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="绑定域名:">
|
||||
<a-input
|
||||
v-model="options.cos_tencent_domain"
|
||||
placeholder="如不填写,路径根域名将为 Bucket + 区域地址"
|
||||
/>
|
||||
<a-input v-model="options.cos_tencent_domain" placeholder="如不填写,路径根域名将为 Bucket + 区域地址" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Bucket:">
|
||||
<a-input
|
||||
v-model="options.cos_tencent_bucket_name"
|
||||
placeholder="存储桶名称"
|
||||
/>
|
||||
<a-input v-model="options.cos_tencent_bucket_name" placeholder="存储桶名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="区域:">
|
||||
<a-auto-complete
|
||||
:dataSource="tencentCosRegions"
|
||||
v-model="options.cos_tencent_region"
|
||||
allowClear
|
||||
/>
|
||||
<a-auto-complete :dataSource="tencentCosRegions" v-model="options.cos_tencent_region" allowClear />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Secret Id:">
|
||||
<a-input-password
|
||||
v-model="options.cos_tencent_secret_id"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.cos_tencent_secret_id" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Secret Key:">
|
||||
<a-input-password
|
||||
v-model="options.cos_tencent_secret_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.cos_tencent_secret_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件目录:">
|
||||
<a-input
|
||||
v-model="options.cos_tencent_source"
|
||||
placeholder="不填写则上传到根目录"
|
||||
/>
|
||||
<a-input v-model="options.cos_tencent_source" placeholder="不填写则上传到根目录" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="图片处理策略:">
|
||||
<a-input
|
||||
v-model="options.cos_tencent_style_rule"
|
||||
placeholder="请到腾讯云控制台的图片处理获取"
|
||||
/>
|
||||
<a-input v-model="options.cos_tencent_style_rule" placeholder="请到腾讯云控制台的图片处理获取" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="缩略图处理策略:">
|
||||
<a-input
|
||||
|
@ -315,10 +201,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="huaweiObsForm"
|
||||
v-show="options.attachment_type === 'HUAWEIOBS'"
|
||||
>
|
||||
<div id="huaweiObsForm" v-show="options.attachment_type === 'HUAWEIOBS'">
|
||||
<a-form-model-item label="绑定域名协议:">
|
||||
<a-select v-model="options.obs_huawei_domain_protocol">
|
||||
<a-select-option value="https://">HTTPS</a-select-option>
|
||||
|
@ -326,46 +209,25 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="绑定域名:">
|
||||
<a-input
|
||||
v-model="options.obs_huawei_domain"
|
||||
placeholder="如不填写,路径根域名将为 Bucket + EndPoint"
|
||||
/>
|
||||
<a-input v-model="options.obs_huawei_domain" placeholder="如不填写,路径根域名将为 Bucket + EndPoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Bucket(桶名称):">
|
||||
<a-input
|
||||
v-model="options.obs_huawei_bucket_name"
|
||||
placeholder="桶名称"
|
||||
/>
|
||||
<a-input v-model="options.obs_huawei_bucket_name" placeholder="桶名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="EndPoint(终端节点):">
|
||||
<a-input
|
||||
v-model="options.obs_huawei_endpoint"
|
||||
placeholder="Endpoint"
|
||||
/>
|
||||
<a-input v-model="options.obs_huawei_endpoint" placeholder="Endpoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Key:">
|
||||
<a-input-password
|
||||
v-model="options.obs_huawei_access_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.obs_huawei_access_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Secret:">
|
||||
<a-input-password
|
||||
v-model="options.obs_huawei_access_secret"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.obs_huawei_access_secret" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件目录:">
|
||||
<a-input
|
||||
v-model="options.obs_huawei_source"
|
||||
placeholder="不填写则上传到根目录"
|
||||
/>
|
||||
<a-input v-model="options.obs_huawei_source" placeholder="不填写则上传到根目录" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="图片处理策略:">
|
||||
<a-input
|
||||
v-model="options.obs_huawei_style_rule"
|
||||
placeholder="请到华为云控制台的图片处理创建"
|
||||
/>
|
||||
<a-input v-model="options.obs_huawei_style_rule" placeholder="请到华为云控制台的图片处理创建" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="缩略图处理策略:">
|
||||
<a-input
|
||||
|
@ -374,39 +236,21 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<div
|
||||
id="minioForm"
|
||||
v-show="options.attachment_type === 'MINIO'"
|
||||
>
|
||||
<div id="minioForm" v-show="options.attachment_type === 'MINIO'">
|
||||
<a-form-model-item label="EndPoint(终端节点):">
|
||||
<a-input
|
||||
v-model="options.minio_endpoint"
|
||||
placeholder="Endpoint"
|
||||
/>
|
||||
<a-input v-model="options.minio_endpoint" placeholder="Endpoint" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Bucket(桶名称):">
|
||||
<a-input
|
||||
v-model="options.minio_bucket_name"
|
||||
placeholder="桶名称"
|
||||
/>
|
||||
<a-input v-model="options.minio_bucket_name" placeholder="桶名称" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Key:">
|
||||
<a-input-password
|
||||
v-model="options.minio_access_key"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.minio_access_key" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="Access Secret:">
|
||||
<a-input-password
|
||||
v-model="options.minio_access_secret"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<a-input-password v-model="options.minio_access_secret" autocomplete="new-password" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件目录:">
|
||||
<a-input
|
||||
v-model="options.minio_source"
|
||||
placeholder="不填写则上传到根目录"
|
||||
/>
|
||||
<a-input v-model="options.minio_source" placeholder="不填写则上传到根目录" />
|
||||
</a-form-model-item>
|
||||
</div>
|
||||
<a-form-model-item>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="commentOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model ref="commentOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="评论者头像:">
|
||||
<a-select v-model="options.comment_gravatar_default">
|
||||
<a-select-option value="mm">默认</a-select-option>
|
||||
|
@ -27,10 +21,7 @@
|
|||
<a-form-model-item label="评论回复通知对方:">
|
||||
<a-switch v-model="options.comment_reply_notice" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="API 评论开关:"
|
||||
help="* 关闭之后将无法进行评论"
|
||||
>
|
||||
<a-form-model-item label="API 评论开关:" help="* 关闭之后将无法进行评论">
|
||||
<a-switch v-model="options.comment_api_enabled" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="评论模块 JS:">
|
||||
|
@ -42,11 +33,7 @@
|
|||
/>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="每页显示条数: ">
|
||||
<a-input-number
|
||||
v-model="options.comment_page_size"
|
||||
:min="1"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.comment_page_size" :min="1" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="占位提示:">
|
||||
<a-input v-model="options.comment_content_placeholder" />
|
||||
|
|
|
@ -1,59 +1,27 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="generalOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="博客标题:"
|
||||
prop="blog_title"
|
||||
>
|
||||
<a-form-model ref="generalOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="博客标题:" prop="blog_title">
|
||||
<a-input v-model="options.blog_title" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="博客地址:"
|
||||
prop="blog_url"
|
||||
>
|
||||
<a-input
|
||||
v-model="options.blog_url"
|
||||
placeholder="如:https://halo.run"
|
||||
/>
|
||||
<a-form-model-item label="博客地址:" prop="blog_url">
|
||||
<a-input v-model="options.blog_url" placeholder="如:https://halo.run" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="Logo:"
|
||||
prop="blog_logo"
|
||||
>
|
||||
<a-form-model-item label="Logo:" prop="blog_logo">
|
||||
<a-input v-model="options.blog_logo">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="handleShowLogoSelector"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click="handleShowLogoSelector">
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="Favicon:"
|
||||
prop="blog_favicon"
|
||||
>
|
||||
<a-form-model-item label="Favicon:" prop="blog_favicon">
|
||||
<a-input v-model="options.blog_favicon">
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
slot="addonAfter"
|
||||
@click="handleShowFaviconSelector"
|
||||
>
|
||||
<a href="javascript:void(0);" slot="addonAfter" @click="handleShowFaviconSelector">
|
||||
<a-icon type="picture" />
|
||||
</a>
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="页脚信息:"
|
||||
prop="blog_footer_info"
|
||||
>
|
||||
<a-form-model-item label="页脚信息:" prop="blog_footer_info">
|
||||
<a-input
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="otherOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model ref="otherOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="自定义全局 head:">
|
||||
<a-input
|
||||
type="textarea"
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="permalinkOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model ref="permalinkOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="文章固定链接类型:">
|
||||
<template slot="help">
|
||||
<span v-if="options.post_permalink_type === 'DEFAULT'">{{ options.blog_url }}/{{ options.archives_prefix }}/{slug}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'YEAR'">{{ options.blog_url }}{{ new Date() | moment_post_year }}{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-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 === 'YEAR'"
|
||||
>{{ options.blog_url }}{{ new Date() | moment_post_year }}{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>
|
||||
<span v-else-if="options.post_permalink_type === 'ID_SLUG'">{{ options.blog_url }}/{{ options.archives_prefix }}/{id}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.post_permalink_type === 'ID_SLUG'"
|
||||
>{{ options.blog_url }}/{{ options.archives_prefix }}/{id}{{ options.path_suffix }}</span
|
||||
>
|
||||
</template>
|
||||
<a-select v-model="options.post_permalink_type">
|
||||
<a-select-option
|
||||
v-for="item in Object.keys(postPermalinkType)"
|
||||
:key="item"
|
||||
:value="item"
|
||||
>{{ postPermalinkType[item].text }}</a-select-option>
|
||||
<a-select-option v-for="item in Object.keys(postPermalinkType)" :key="item" :value="item">{{
|
||||
postPermalinkType[item].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="归档前缀:">
|
||||
|
@ -44,21 +46,20 @@
|
|||
</a-form-model-item>
|
||||
<a-form-model-item label="自定义页面固定链接类型:">
|
||||
<template slot="help">
|
||||
<span v-if="options.sheet_permalink_type === 'SECONDARY'">{{ options.blog_url }}/{{ options.sheet_prefix }}/{slug}{{ options.path_suffix }}</span>
|
||||
<span v-else-if="options.sheet_permalink_type === 'ROOT'">{{ options.blog_url }}/{slug}{{ options.path_suffix }}</span>
|
||||
<span v-if="options.sheet_permalink_type === 'SECONDARY'"
|
||||
>{{ options.blog_url }}/{{ options.sheet_prefix }}/{slug}{{ options.path_suffix }}</span
|
||||
>
|
||||
<span v-else-if="options.sheet_permalink_type === 'ROOT'"
|
||||
>{{ options.blog_url }}/{slug}{{ options.path_suffix }}</span
|
||||
>
|
||||
</template>
|
||||
<a-select v-model="options.sheet_permalink_type">
|
||||
<a-select-option
|
||||
v-for="item in Object.keys(sheetPermalinkType)"
|
||||
:key="item"
|
||||
:value="item"
|
||||
>{{ sheetPermalinkType[item].text }}</a-select-option>
|
||||
<a-select-option v-for="item in Object.keys(sheetPermalinkType)" :key="item" :value="item">{{
|
||||
sheetPermalinkType[item].text
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="自定义页面前缀:"
|
||||
v-show="options.sheet_permalink_type === 'SECONDARY'"
|
||||
>
|
||||
<a-form-model-item label="自定义页面前缀:" v-show="options.sheet_permalink_type === 'SECONDARY'">
|
||||
<template slot="help">
|
||||
<span>{{ options.blog_url }}/{{ options.sheet_prefix }}/{slug}{{ options.path_suffix }}</span>
|
||||
</template>
|
||||
|
@ -111,16 +112,16 @@ export default {
|
|||
props: {
|
||||
options: {
|
||||
type: Object,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
saving: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: false
|
||||
},
|
||||
errored: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -130,25 +131,25 @@ export default {
|
|||
xl: { span: 8 },
|
||||
lg: { span: 8 },
|
||||
sm: { span: 12 },
|
||||
xs: { span: 24 },
|
||||
xs: { span: 24 }
|
||||
},
|
||||
rules: {},
|
||||
rules: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options(val) {
|
||||
this.$emit('onChange', val)
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSaveOptions() {
|
||||
const _this = this
|
||||
_this.$refs.permalinkOptionsForm.validate((valid) => {
|
||||
_this.$refs.permalinkOptionsForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.$emit('onSave')
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="postOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model ref="postOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<!-- <a-form-model-item label="默认编辑器:">
|
||||
<a-select v-model="options.default_editor">
|
||||
<a-select-option value="MARKDOWN">Markdown 编辑器</a-select-option>
|
||||
|
@ -21,18 +15,10 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="首页每页文章条数:">
|
||||
<a-input-number
|
||||
v-model="options.post_index_page_size"
|
||||
:min="1"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.post_index_page_size" :min="1" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="归档页面每页文章条数:" help="* 包括标签所属文章页面、分类所属文章页面">
|
||||
<a-input-number
|
||||
v-model="options.post_archives_page_size"
|
||||
:min="1"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.post_archives_page_size" :min="1" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="RSS 内容类型:">
|
||||
<a-select v-model="options.rss_content_type">
|
||||
|
@ -41,33 +27,18 @@
|
|||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="RSS 内容条数:">
|
||||
<a-input-number
|
||||
v-model="options.rss_page_size"
|
||||
:min="1"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.rss_page_size" :min="1" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文章摘要字数:">
|
||||
<a-input-number
|
||||
v-model="options.post_summary_length"
|
||||
style="width:100%"
|
||||
/>
|
||||
<a-input-number v-model="options.post_summary_length" style="width:100%" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="自动清理回收站文章:">
|
||||
<a-switch v-model="options.recycled_post_cleaning_enabled" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
v-show="options.recycled_post_cleaning_enabled"
|
||||
label="回收站文章保留时长:">
|
||||
<a-form-model-item v-show="options.recycled_post_cleaning_enabled" label="回收站文章保留时长:">
|
||||
<a-input-group compact>
|
||||
<a-input-number
|
||||
v-model="options.recycled_post_retention_time"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
style="width: 70%"/>
|
||||
<a-select
|
||||
v-model="options.recycled_post_retention_timeunit"
|
||||
style="width: 30%">
|
||||
<a-input-number v-model="options.recycled_post_retention_time" :min="1" :precision="0" style="width: 70%" />
|
||||
<a-select v-model="options.recycled_post_retention_timeunit" style="width: 30%">
|
||||
<a-select-option value="DAY">天</a-select-option>
|
||||
<a-select-option value="HOUR">小时</a-select-option>
|
||||
</a-select>
|
||||
|
|
|
@ -1,36 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-model
|
||||
ref="seoOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="屏蔽搜索引擎:"
|
||||
prop="seo_spider_disabled"
|
||||
>
|
||||
<a-form-model ref="seoOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="屏蔽搜索引擎:" prop="seo_spider_disabled">
|
||||
<a-switch v-model="options.seo_spider_disabled" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="关键词:"
|
||||
prop="seo_keywords"
|
||||
>
|
||||
<a-input
|
||||
v-model="options.seo_keywords"
|
||||
placeholder="多个关键词以英文状态下的逗号隔开"
|
||||
/>
|
||||
<a-form-model-item label="关键词:" prop="seo_keywords">
|
||||
<a-input v-model="options.seo_keywords" placeholder="多个关键词以英文状态下的逗号隔开" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="博客描述:"
|
||||
prop="seo_description"
|
||||
>
|
||||
<a-input
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
v-model="options.seo_description"
|
||||
/>
|
||||
<a-form-model-item label="博客描述:" prop="seo_description">
|
||||
<a-input type="textarea" :autoSize="{ minRows: 5 }" v-model="options.seo_description" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
<ReactiveButton
|
||||
|
|
|
@ -1,58 +1,31 @@
|
|||
<template>
|
||||
<div class="custom-tab-wrapper">
|
||||
<a-tabs>
|
||||
<a-tab-pane
|
||||
tab="发信设置"
|
||||
key="smtpoptions"
|
||||
>
|
||||
<a-form-model
|
||||
ref="smtpOptionsForm"
|
||||
:model="options"
|
||||
:rules="rules"
|
||||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-tab-pane tab="发信设置" key="smtpoptions">
|
||||
<a-form-model ref="smtpOptionsForm" :model="options" :rules="rules" layout="vertical" :wrapperCol="wrapperCol">
|
||||
<a-form-model-item label="是否启用:">
|
||||
<a-switch v-model="options.email_enabled" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="SMTP 地址:"
|
||||
prop="email_host"
|
||||
>
|
||||
<a-form-model-item label="SMTP 地址:" prop="email_host">
|
||||
<a-input v-model="options.email_host" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="发送协议:"
|
||||
prop="email_protocol"
|
||||
>
|
||||
<a-form-model-item label="发送协议:" prop="email_protocol">
|
||||
<a-input v-model="options.email_protocol" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="SSL 端口:"
|
||||
prop="email_ssl_port"
|
||||
>
|
||||
<a-form-model-item label="SSL 端口:" prop="email_ssl_port">
|
||||
<a-input v-model="options.email_ssl_port" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="邮箱账号:"
|
||||
prop="email_username"
|
||||
>
|
||||
<a-form-model-item label="邮箱账号:" prop="email_username">
|
||||
<a-input v-model="options.email_username" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="邮箱密码:"
|
||||
prop="email_password"
|
||||
>
|
||||
<a-form-model-item label="邮箱密码:" prop="email_password">
|
||||
<a-input-password
|
||||
v-model="options.email_password"
|
||||
placeholder="部分邮箱可能是授权码"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="发件人:"
|
||||
prop="email_from_name"
|
||||
>
|
||||
<a-form-model-item label="发件人:" prop="email_from_name">
|
||||
<a-input v-model="options.email_from_name" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
|
@ -69,10 +42,7 @@
|
|||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
tab="发送测试"
|
||||
key="smtptest"
|
||||
>
|
||||
<a-tab-pane tab="发送测试" key="smtptest">
|
||||
<a-form-model
|
||||
ref="smtpTestForm"
|
||||
:model="mailParam"
|
||||
|
@ -80,33 +50,20 @@
|
|||
layout="vertical"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<a-form-model-item
|
||||
label="收件人地址:"
|
||||
prop="to"
|
||||
>
|
||||
<a-form-model-item label="收件人地址:" prop="to">
|
||||
<a-input v-model="mailParam.to" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="主题:"
|
||||
prop="subject"
|
||||
>
|
||||
<a-form-model-item label="主题:" prop="subject">
|
||||
<a-input v-model="mailParam.subject" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item
|
||||
label="内容:"
|
||||
prop="content"
|
||||
>
|
||||
<a-input
|
||||
type="textarea"
|
||||
:autoSize="{ minRows: 5 }"
|
||||
v-model="mailParam.content"
|
||||
/>
|
||||
<a-form-model-item label="内容:" prop="content">
|
||||
<a-input type="textarea" :autoSize="{ minRows: 5 }" v-model="mailParam.content" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item>
|
||||
<ReactiveButton
|
||||
type="primary"
|
||||
@click="handleTestMailClick"
|
||||
@callback="sendErrored=false"
|
||||
@callback="sendErrored = false"
|
||||
:loading="sending"
|
||||
:errored="sendErrored"
|
||||
text="发送"
|
||||
|
@ -179,7 +136,7 @@ export default {
|
|||
methods: {
|
||||
handleSaveOptions() {
|
||||
const _this = this
|
||||
_this.$refs.smtpOptionsForm.validate((valid) => {
|
||||
_this.$refs.smtpOptionsForm.validate(valid => {
|
||||
if (valid) {
|
||||
_this.$emit('onSave')
|
||||
}
|
||||
|
@ -187,12 +144,12 @@ export default {
|
|||
},
|
||||
handleTestMailClick() {
|
||||
const _this = this
|
||||
_this.$refs.smtpTestForm.validate((valid) => {
|
||||
_this.$refs.smtpTestForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.sending = true
|
||||
mailApi
|
||||
.testMail(this.mailParam)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
this.$message.info(response.data.message)
|
||||
})
|
||||
.catch(() => {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue