Add rich text editor. (halo-dev/console#76)

* refactor: pull out the editor component.

* feat: support rich text editor.
pull/3445/head
Ryan Wang 2020-02-28 22:26:05 +08:00 committed by GitHub
parent 5da3f267b7
commit 50af584f1f
7 changed files with 111 additions and 20 deletions

View File

@ -48,6 +48,16 @@ sheetApi.update = (sheetId, sheetToUpdate, autoSave) => {
}) })
} }
sheetApi.updateDraft = (sheetId, content) => {
return service({
url: `${baseUrl}/${sheetId}/status/draft/content`,
method: 'put',
data: {
content: content
}
})
}
sheetApi.updateStatus = (sheetId, status) => { sheetApi.updateStatus = (sheetId, status) => {
return service({ return service({
url: `${baseUrl}/${sheetId}/${status}`, url: `${baseUrl}/${sheetId}/${status}`,

View File

@ -2,7 +2,7 @@
<div> <div>
<halo-editor <halo-editor
ref="md" ref="md"
v-model="originalContentData" v-model="originalContent"
:boxShadow="false" :boxShadow="false"
:toolbars="toolbars" :toolbars="toolbars"
:ishljs="true" :ishljs="true"
@ -40,7 +40,7 @@ export default {
this.originalContentData = val this.originalContentData = val
}, },
originalContentData(val) { originalContentData(val) {
this.$emit('onChange', val) this.$emit('onContentChange', val)
} }
}, },
methods: { methods: {

View File

@ -0,0 +1,34 @@
<template>
<div>
<a-input
type="textarea"
v-model="originalContent"
:rows="16"
/>
</div>
</template>
<script>
export default {
name: 'RichTextEditor',
props: {
originalContent: {
type: String,
required: false,
default: ''
}
},
data() {
return {
originalContentData: ''
}
},
watch: {
originalContent(val) {
this.originalContentData = val
},
originalContentData(val) {
this.$emit('onContentChange', val)
}
}
}
</script>

View File

@ -12,7 +12,8 @@ const keys = [
'sheet_prefix', 'sheet_prefix',
'post_permalink_type', 'post_permalink_type',
'archives_prefix', 'archives_prefix',
'path_suffix' 'path_suffix',
'default_editor'
] ]
const option = { const option = {
state: { state: {

View File

@ -12,9 +12,16 @@
<div id="editor"> <div id="editor">
<MarkdownEditor <MarkdownEditor
v-if="postToStage.editorType=='MARKDOWN'"
:originalContent="postToStage.originalContent" :originalContent="postToStage.originalContent"
@onSaveDraft="handleSaveDraft(true)" @onSaveDraft="handleSaveDraft(true)"
@onChange="onContentChange" @onContentChange="onContentChange"
/>
<RichTextEditor
v-else
:originalContent="postToStage.originalContent"
@onContentChange="onContentChange"
/> />
</div> </div>
</a-col> </a-col>
@ -69,6 +76,7 @@ import PostSettingDrawer from './components/PostSettingDrawer'
import AttachmentDrawer from '../attachment/components/AttachmentDrawer' import AttachmentDrawer from '../attachment/components/AttachmentDrawer'
import FooterToolBar from '@/components/FooterToolbar' import FooterToolBar from '@/components/FooterToolbar'
import MarkdownEditor from '@/components/editor/MarkdownEditor' import MarkdownEditor from '@/components/editor/MarkdownEditor'
import RichTextEditor from '@/components/editor/RichTextEditor'
import postApi from '@/api/post' import postApi from '@/api/post'
export default { export default {
@ -77,7 +85,8 @@ export default {
PostSettingDrawer, PostSettingDrawer,
FooterToolBar, FooterToolBar,
AttachmentDrawer, AttachmentDrawer,
MarkdownEditor MarkdownEditor,
RichTextEditor
}, },
data() { data() {
return { return {
@ -151,6 +160,9 @@ export default {
} }
return '当前页面数据未保存,确定要离开吗?' return '当前页面数据未保存,确定要离开吗?'
} }
if (!this.postToStage.editorType) {
this.postToStage.editorType = this.options.default_editor
}
}, },
watch: { watch: {
temporaryContent: function(newValue, oldValue) { temporaryContent: function(newValue, oldValue) {
@ -190,6 +202,7 @@ export default {
.then(response => { .then(response => {
this.$log.debug('Updated post', response.data.data) this.$log.debug('Updated post', response.data.data)
this.$message.success('保存草稿成功!') this.$message.success('保存草稿成功!')
this.postToStage = response.data.data
}) })
.finally(() => { .finally(() => {
this.saving = false this.saving = false

View File

@ -9,11 +9,19 @@
placeholder="请输入页面标题" placeholder="请输入页面标题"
/> />
</div> </div>
<div id="editor"> <div id="editor">
<MarkdownEditor <MarkdownEditor
v-if="sheetToStage.editorType=='MARKDOWN'"
:originalContent="sheetToStage.originalContent" :originalContent="sheetToStage.originalContent"
@onSaveDraft="handleSaveDraft" @onSaveDraft="handleSaveDraft(true)"
@onChange="onContentChange" @onContentChange="onContentChange"
/>
<RichTextEditor
v-else
:originalContent="sheetToStage.originalContent"
@onContentChange="onContentChange"
/> />
</div> </div>
</a-col> </a-col>
@ -33,7 +41,7 @@
<footer-tool-bar :style="{ width: isSideMenu() && isDesktop() ? `calc(100% - ${sidebarOpened ? 256 : 80}px)` : '100%'}"> <footer-tool-bar :style="{ width: isSideMenu() && isDesktop() ? `calc(100% - ${sidebarOpened ? 256 : 80}px)` : '100%'}">
<a-button <a-button
type="danger" type="danger"
@click="handleSaveDraft" @click="handleSaveDraft(false)"
:disabled="saving" :disabled="saving"
>保存草稿</a-button> >保存草稿</a-button>
<a-button <a-button
@ -63,13 +71,16 @@ import SheetSettingDrawer from './components/SheetSettingDrawer'
import AttachmentDrawer from '../attachment/components/AttachmentDrawer' import AttachmentDrawer from '../attachment/components/AttachmentDrawer'
import FooterToolBar from '@/components/FooterToolbar' import FooterToolBar from '@/components/FooterToolbar'
import MarkdownEditor from '@/components/editor/MarkdownEditor' import MarkdownEditor from '@/components/editor/MarkdownEditor'
import RichTextEditor from '@/components/editor/RichTextEditor'
import sheetApi from '@/api/sheet' import sheetApi from '@/api/sheet'
export default { export default {
components: { components: {
FooterToolBar, FooterToolBar,
AttachmentDrawer, AttachmentDrawer,
SheetSettingDrawer, SheetSettingDrawer,
MarkdownEditor MarkdownEditor,
RichTextEditor
}, },
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
data() { data() {
@ -140,6 +151,9 @@ export default {
} }
return '当前页面数据未保存,确定要离开吗?' return '当前页面数据未保存,确定要离开吗?'
} }
if (!this.sheetToStage.editorType) {
this.sheetToStage.editorType = this.options.default_editor
}
}, },
watch: { watch: {
temporaryContent: function(newValue, oldValue) { temporaryContent: function(newValue, oldValue) {
@ -155,22 +169,35 @@ export default {
...mapGetters(['options']) ...mapGetters(['options'])
}, },
methods: { methods: {
handleSaveDraft() { handleSaveDraft(draftOnly = false) {
this.$log.debug('Draft only: ' + draftOnly)
this.sheetToStage.status = 'DRAFT' this.sheetToStage.status = 'DRAFT'
this.saving = true
if (!this.sheetToStage.title) { if (!this.sheetToStage.title) {
this.sheetToStage.title = moment(new Date()).format('YYYY-MM-DD-HH-mm-ss') this.sheetToStage.title = moment(new Date()).format('YYYY-MM-DD-HH-mm-ss')
} }
this.saving = true
if (this.sheetToStage.id) { if (this.sheetToStage.id) {
if (draftOnly) {
sheetApi sheetApi
.update(this.sheetToStage.id, this.sheetToStage, false) .updateDraft(this.sheetToStage.id, this.sheetToStage.originalContent)
.then(response => { .then(response => {
this.$log.debug('Updated sheet', response.data.data)
this.$message.success('保存草稿成功!') this.$message.success('保存草稿成功!')
}) })
.finally(() => { .finally(() => {
this.saving = false this.saving = false
}) })
} else {
sheetApi
.update(this.sheetToStage.id, this.sheetToStage, false)
.then(response => {
this.$log.debug('Updated sheet', response.data.data)
this.$message.success('保存草稿成功!')
this.sheetToStage = response.data.data
})
.finally(() => {
this.saving = false
})
}
} else { } else {
sheetApi sheetApi
.create(this.sheetToStage, false) .create(this.sheetToStage, false)

View File

@ -103,6 +103,12 @@
layout="vertical" layout="vertical"
:wrapperCol="wrapperCol" :wrapperCol="wrapperCol"
> >
<a-form-item label="默认编辑器:">
<a-select v-model="options.default_editor">
<a-select-option value="MARKDOWN">Markdown 编辑器</a-select-option>
<a-select-option value="RICHTEXT">富文本编辑器</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="首页文章排序:"> <a-form-item label="首页文章排序:">
<a-select v-model="options.post_index_sort"> <a-select v-model="options.post_index_sort">
<a-select-option value="createTime">创建时间</a-select-option> <a-select-option value="createTime">创建时间</a-select-option>