refactor: post editing (#439)

* refactor: post editing

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/443/head
Ryan Wang 2022-02-20 22:38:25 +08:00 committed by GitHub
parent 4c7e799a01
commit 460f770564
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 110 deletions

View File

@ -32,6 +32,7 @@
"filepond-plugin-file-validate-type": "^1.2.6",
"filepond-plugin-image-preview": "^4.6.10",
"halo-editor": "^2.8.4",
"lodash.debounce": "^4.0.8",
"marked": "^4.0.10",
"md5.js": "^1.3.5",
"nprogress": "^0.2.0",

View File

@ -27,6 +27,7 @@ specifiers:
less: ^3.13.1
less-loader: ^5.0.0
lint-staged: ^11.2.6
lodash.debounce: ^4.0.8
marked: ^4.0.10
md5.js: ^1.3.5
nprogress: ^0.2.0
@ -58,6 +59,7 @@ dependencies:
filepond-plugin-file-validate-type: 1.2.6_filepond@4.30.3
filepond-plugin-image-preview: 4.6.10_filepond@4.30.3
halo-editor: 2.8.4
lodash.debounce: 4.0.8
marked: 4.0.10
md5.js: 1.3.5
nprogress: 0.2.0
@ -5112,7 +5114,6 @@ packages:
/lodash.debounce/4.0.8:
resolution: {integrity: sha1-gteb/zCmfEAF/9XiUVMArZyk168=}
dev: true
/lodash.defaultsdeep/4.6.1:
resolution: {integrity: sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==}

View File

@ -1,18 +1,12 @@
<template>
<page-view :title="postToStage.title ? postToStage.title : '新文章'" affix>
<page-view
:title="postToStage.title ? postToStage.title : '新文章'"
:sub-title="postToStage.inProgress ? '当前内容已保存,但还未发布。' : ''"
affix
>
<template slot="extra">
<a-space>
<ReactiveButton
:errored="draftSaveErrored"
:loading="draftSaving"
erroredText="保存失败"
loadedText="保存成功"
text="保存草稿"
type="danger"
@callback="draftSaveErrored = false"
@click="handleSaveDraft(false)"
></ReactiveButton>
<a-button :loading="previewSaving" @click="handlePreview"></a-button>
<a-button :loading="previewSaving" @click="handlePreviewClick"></a-button>
<a-button type="primary" @click="postSettingVisible = true">发布</a-button>
</a-space>
</template>
@ -25,7 +19,7 @@
<MarkdownEditor
:originalContent="postToStage.originalContent"
@onContentChange="onContentChange"
@onSaveDraft="handleSaveDraft(true)"
@onSaveDraft="handleSaveDraft()"
/>
</div>
</a-col>
@ -50,6 +44,7 @@ import { PageView } from '@/layouts'
import { mixin, mixinDevice, mixinPostEdit } from '@/mixins/mixin.js'
import { datetimeFormat } from '@/utils/datetime'
import apiClient from '@/utils/api-client'
import debounce from 'lodash.debounce'
export default {
mixins: [mixin, mixinDevice, mixinPostEdit],
@ -63,19 +58,16 @@ export default {
postSettingVisible: false,
postToStage: {},
contentChanges: 0,
draftSaving: false,
previewSaving: false,
draftSaveErrored: false
previewSaving: false
}
},
beforeRouteEnter(to, from, next) {
// Get post id from query
const postId = to.query.postId
next(vm => {
next(async vm => {
if (postId) {
apiClient.post.get(postId).then(response => {
vm.postToStage = response.data
})
const { data } = await apiClient.post.get(Number(postId))
vm.postToStage = data
}
})
},
@ -110,104 +102,74 @@ export default {
}
},
methods: {
handleSaveDraft(draftOnly = false) {
this.$log.debug('Draft only: ' + draftOnly)
this.postToStage.status = 'DRAFT'
if (!this.postToStage.title) {
this.postToStage.title = datetimeFormat(new Date(), 'YYYY-MM-DD-HH-mm-ss')
}
this.draftSaving = true
handleSaveDraft: debounce(async function () {
if (this.postToStage.id) {
// Update the post
if (draftOnly) {
apiClient.post
.updateDraftById(this.postToStage.id, this.postToStage.originalContent)
.then(() => {
this.handleRestoreSavedStatus()
})
.catch(() => {
this.draftSaveErrored = true
})
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 400)
})
} else {
apiClient.post
.update(this.postToStage.id, this.postToStage)
.then(response => {
this.postToStage = response.data
this.handleRestoreSavedStatus()
})
.catch(() => {
this.draftSaveErrored = true
})
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 400)
})
// Update the post content
try {
const { data } = await apiClient.post.updateDraftById(this.postToStage.id, this.postToStage.originalContent)
this.postToStage.inProgress = data.inProgress
this.handleRestoreSavedStatus()
this.$message.success({
content: '内容已保存',
duration: 0.5
})
} catch (e) {
this.$log.error('Failed to update post content', e)
}
} else {
// Create the post
apiClient.post
.create(this.postToStage)
.then(response => {
this.postToStage = response.data
this.handleRestoreSavedStatus()
})
.catch(() => {
this.draftSaveErrored = true
})
.finally(() => {
setTimeout(() => {
this.draftSaving = false
}, 400)
})
await this.handleCreatePost()
}
},
handlePreview() {
this.postToStage.status = 'DRAFT'
}, 300),
async handleCreatePost() {
if (!this.postToStage.title) {
this.postToStage.title = datetimeFormat(new Date(), 'YYYY-MM-DD-HH-mm-ss')
}
this.previewSaving = true
if (this.postToStage.id) {
// Update the post
apiClient.post.update(this.postToStage.id, this.postToStage).then(response => {
this.$log.debug('Updated post', response.data)
apiClient.post
.getPreviewLinkById(this.postToStage.id)
.then(response => {
window.open(response, '_blank')
this.handleRestoreSavedStatus()
})
.finally(() => {
setTimeout(() => {
this.previewSaving = false
}, 400)
})
})
} else {
// Create the post
apiClient.post.create(this.postToStage).then(response => {
this.$log.debug('Created post', response.data)
this.postToStage = response.data
apiClient.post
.getPreviewLinkById(this.postToStage.id)
.then(response => {
window.open(response, '_blank')
this.handleRestoreSavedStatus()
})
.finally(() => {
setTimeout(() => {
this.previewSaving = false
}, 400)
})
// Create the post
try {
const { data } = await apiClient.post.create(this.postToStage)
this.postToStage = data
this.handleRestoreSavedStatus()
// add params to url
const path = this.$router.history.current.path
this.$router.push({ path, query: { postId: this.postToStage.id } }).catch(err => err)
this.$message.success({
content: '文章已创建',
duration: 0.5
})
} catch (e) {
this.$log.error('Failed to create post', e)
}
},
async handlePreviewClick() {
this.previewSaving = true
if (this.postToStage.id) {
// Update the post content
const { data } = await apiClient.post.updateDraftById(this.postToStage.id, this.postToStage.originalContent)
this.postToStage.inProgress = data.inProgress
} else {
await this.handleCreatePost()
}
await this.handleOpenPreview()
},
async handleOpenPreview() {
try {
const response = await apiClient.post.getPreviewLinkById(this.postToStage.id)
window.open(response, '_blank')
this.handleRestoreSavedStatus()
} catch (e) {
this.$log.error('Failed to get preview link', e)
} finally {
setTimeout(() => {
this.previewSaving = false
}, 400)
}
},
handleRestoreSavedStatus() {
this.contentChanges = 0
},

View File

@ -243,6 +243,15 @@
twoToneColor="red"
type="pushpin"
/>
<a-tooltip v-if="record.inProgress" title="当前有内容已保存,但还未发布。" placement="top">
<a-icon
class="cursor-pointer"
style="margin-right: 3px"
theme="twoTone"
twoToneColor="#52c41a"
type="info-circle"
/>
</a-tooltip>
<a-tooltip
v-if="['PUBLISHED', 'INTIMATE'].includes(record.status)"
:title="'点击访问【' + text + '】'"
@ -411,7 +420,7 @@ const columns = [
{
title: '标题',
dataIndex: 'title',
width: '150px',
width: '200px',
ellipsis: true,
scopedSlots: { customRender: 'postTitle' }
},