md/src/components/codeMirror/header.vue

281 lines
11 KiB
Vue
Raw Normal View History

2020-05-01 21:30:25 +08:00
<template>
2020-05-17 16:53:21 +08:00
<el-container class="top is-dark">
2020-05-01 21:30:25 +08:00
<!-- 图片上传 -->
2020-05-02 16:28:00 +08:00
<el-upload class="header__item" action="https://imgkr.com/api/files/upload"
:headers="{'Content-Type': 'multipart/form-data'}"
2020-05-01 21:30:25 +08:00
:show-file-list="false" :multiple="true" accept=".jpg,.jpeg,.png,.gif" name="file"
2020-05-02 17:40:03 +08:00
:before-upload="beforeUpload">
2020-05-17 16:53:21 +08:00
<el-tooltip :effect="effect" content="上传图片" placement="bottom-start">
2020-05-02 11:50:26 +08:00
<i class="el-icon-upload" size="medium"></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
</el-upload>
<!-- 下载文本文档 -->
2020-05-17 16:53:21 +08:00
<el-tooltip class="header__item" :effect="effect" content="下载编辑框Markdown文档" placement="bottom-start">
2020-05-02 11:50:26 +08:00
<i class="el-icon-download" size="medium" @click="downloadEditorContent"></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
<!-- 页面重置 -->
2020-05-17 16:53:21 +08:00
<el-tooltip class="header__item" :effect="effect" content="重置页面" placement="bottom-start">
2020-05-02 11:50:26 +08:00
<i class="el-icon-refresh" size="medium" @click="reset"></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
<!-- 插入表格 -->
2020-05-17 16:53:21 +08:00
<el-tooltip class="header__item header__item_last" :effect="effect" content="插入表格" placement="bottom-start">
2020-05-02 11:50:26 +08:00
<i class="el-icon-s-grid" size="medium" @click="$emit('showDialogForm')"></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
<el-form size="mini" class="ctrl" :inline=true>
<el-form-item>
2020-05-02 11:50:26 +08:00
<el-select v-model="selectFont" size="mini" placeholder="选择字体" clearable @change="fontChanged">
<el-option v-for="font in config.builtinFonts" :style="{fontFamily: font.value}" :key="font.value"
2020-05-01 21:30:25 +08:00
:label="font.label" :value="font.value">
2020-05-17 18:16:26 +08:00
<span class="select-item-left">{{ font.label }}</span>
<span class="select-item-right">Abc</span>
2020-05-01 21:30:25 +08:00
</el-option>
</el-select>
</el-form-item>
<el-form-item>
2020-05-02 11:50:26 +08:00
<el-select v-model="selectSize" size="mini" placeholder="选择段落字号" clearable @change="sizeChanged">
<el-option v-for="size in config.sizeOption" :key="size.value" :label="size.label" :value="size.value">
2020-05-17 18:16:26 +08:00
<span class="select-item-left">{{ size.label }}</span>
<span class="select-item-right">{{ size.desc }}</span>
2020-05-01 21:30:25 +08:00
</el-option>
</el-select>
</el-form-item>
<el-form-item>
2020-05-02 11:50:26 +08:00
<el-select v-model="selectColor" size="mini" placeholder="选择颜色" clearable @change="colorChanged">
<el-option v-for="color in config.colorOption" :key="color.value" :label="color.label" :value="color.value">
2020-05-17 18:16:26 +08:00
<span class="select-item-left">{{ color.label }}</span>
<span class="select-item-right">{{ color.hex }}</span>
2020-05-01 21:30:25 +08:00
</el-option>
</el-select>
</el-form-item>
2020-05-17 16:53:21 +08:00
<el-tooltip content="自定义颜色" :effect="effect" placement="top">
2020-05-02 11:50:26 +08:00
<el-color-picker v-model="selectColor" size="mini" show-alpha @change="colorChanged"></el-color-picker>
2020-05-01 21:30:25 +08:00
</el-tooltip>
2020-05-17 16:53:21 +08:00
<el-tooltip content="微信外链自动转为文末引用" :effect="effect" placement="top">
<el-switch class="header__switch" v-model="citeStatus" active-color="#67c23a" inactive-color="#dcdfe6" @change="statusChanged">
</el-switch>
2020-05-01 21:30:25 +08:00
</el-tooltip>
</el-form>
2020-05-17 16:53:21 +08:00
<el-tooltip class="item" :effect="effect" content="自定义CSS样式" placement="left">
<el-button :type="btnType" plain size="medium" icon="el-icon-setting" @click="customStyle"></el-button>
</el-tooltip>
<el-button :type="btnType" plain size="medium" @click="copy">复制</el-button>
<el-button :type="btnType" plain size="medium" class="about" @click="$emit('showAboutDialog')">关于</el-button>
<el-tooltip content="夜间模式" placement="bottom-start">
<div class="mode__switch" v-if="!nightMode" @click="themeChanged"></div>
<div class="mode__switch mode__switch_black" v-else @click="themeChanged"></div>
2020-05-01 21:30:25 +08:00
</el-tooltip>
2020-05-02 11:50:26 +08:00
</el-container>
2020-05-01 21:30:25 +08:00
</template>
<script>
2020-05-02 11:50:26 +08:00
import {
setColorWithCustomTemplate,
setFontSize,
2020-05-02 12:33:44 +08:00
isImageIllegal
2020-05-02 11:50:26 +08:00
} from '../../scripts/util'
2020-05-02 16:28:00 +08:00
import fileApi from '../../api/file';
2020-05-02 11:50:26 +08:00
import {
solveWeChatImage,
solveHtml
} from '../../scripts/converter'
import config from '../../scripts/config'
import DEFAULT_CSS_CONTENT from '../../scripts/themes/default-theme-css'
import {mapState, mapMutations} from 'vuex'
2020-05-01 21:30:25 +08:00
export default {
2020-05-02 11:50:26 +08:00
name: 'editor-header',
data() {
return {
config: config,
citeStatus: false,
selectFont: '',
selectSize: '',
selectColor: ''
};
},
computed: {
2020-05-17 16:53:21 +08:00
effect() {
return this.nightMode ? 'dark' : 'light'
},
btnType() {
return !this.nightMode ? 'success' : 'default';
},
2020-05-02 11:50:26 +08:00
...mapState({
output: state=> state.output,
editor: state=> state.editor,
cssEditor: state=> state.cssEditor,
currentFont: state=> state.currentFont,
currentSize: state=> state.currentSize,
2020-05-17 16:53:21 +08:00
currentColor: state=> state.currentColor,
nightMode: state=> state.nightMode
2020-05-02 11:50:26 +08:00
})
},
2020-05-01 21:30:25 +08:00
methods: {
2020-05-02 11:50:26 +08:00
fontChanged(fonts) {
this.setWxRendererOptions({
fonts: fonts
})
this.setCurrentFont(fonts);
2020-05-04 11:02:13 +08:00
this.$emit('refresh')
2020-05-02 11:50:26 +08:00
},
sizeChanged(size) {
let theme = setFontSize(size.replace('px', ''))
theme = setColorWithCustomTemplate(theme, this.currentColor)
this.setWxRendererOptions({
size: size,
theme: theme
})
this.setCurrentSize(size);
2020-05-04 11:02:13 +08:00
this.$emit('refresh')
2020-05-02 11:50:26 +08:00
},
colorChanged(color) {
let theme = setFontSize(this.currentSize.replace('px', ''))
theme = setColorWithCustomTemplate(theme, color)
this.setWxRendererOptions({
theme: theme
})
this.setCurrentColor(color);
2020-05-04 11:02:13 +08:00
this.$emit('refresh')
2020-05-02 11:50:26 +08:00
},
statusChanged(val) {
this.setCiteStatus(val)
2020-05-04 11:02:13 +08:00
this.$emit('refresh')
2020-05-02 11:50:26 +08:00
},
// 图片上传前的处理
beforeUpload(file) {
const checkImageResult = isImageIllegal(file);
if (checkImageResult) {
this.$message({
showClose: true,
message: checkImageResult,
type: 'error'
});
return false;
}
2020-05-02 16:28:00 +08:00
let fd = new FormData();
fd.append('file', file);
fileApi.fileUpload(fd).then(res => {
2020-05-02 17:40:03 +08:00
this.$emit('uploaded', res)
2020-05-02 16:28:00 +08:00
}).catch(err => {
console.log(err.message)
})
return false;
2020-05-02 11:50:26 +08:00
},
// 复制到微信公众号
copy() {
let clipboardDiv = document.getElementById('output')
2020-05-02 17:40:03 +08:00
solveWeChatImage()
this.setHtml(solveHtml())
clipboardDiv.focus()
window.getSelection().removeAllRanges()
let range = document.createRange()
range.setStartBefore(clipboardDiv.firstChild)
range.setEndAfter(clipboardDiv.lastChild)
window.getSelection().addRange(range)
document.execCommand('copy')
2020-05-02 11:50:26 +08:00
// 输出提示
this.$notify({
showClose: true,
message: '已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴',
offset: 80,
duration: 1600,
type: 'success'
})
2020-05-02 17:40:03 +08:00
clipboardDiv.innerHTML = this.output; // 恢复现场
2020-05-04 11:02:13 +08:00
this.$emit('refresh')
2020-05-02 11:50:26 +08:00
},
// 自定义CSS样式
async customStyle () {
this.$emit('showBox');
this.$nextTick(() => {
if(!this.cssEditor) {
this.cssEditor.refresh()
}
})
setTimeout(() => {
this.cssEditor.refresh()
},50)
let flag = await localStorage.getItem('__css_content')
if (!flag) {
this.setCssEditorValue(DEFAULT_CSS_CONTENT)
}
},
// 重置页面
reset() {
this.$confirm('此操作将丢失本地缓存的文本和自定义样式,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
confirmButtonClass: 'el-button--success',
cancelButtonClass: 'el-button--success is-plain',
type: 'warning',
center: true
}).then(() => {
localStorage.clear()
this.clearEditorToDefault();
this.editor.focus()
this.citeStatus = false;
this.statusChanged(false);
this.fontChanged(this.config.builtinFonts[0].value)
this.colorChanged(this.config.colorOption[1].value)
this.sizeChanged(this.config.sizeOption[2].value)
2020-05-02 12:33:44 +08:00
this.$emit('cssChanged')
2020-05-02 11:50:26 +08:00
}).catch(() => {
this.editor.focus()
})
},
// 下载编辑器内容到本地
downloadEditorContent () {
let downLink = document.createElement('a')
downLink.download = 'content.md'
downLink.style.display = 'none'
let blob = new Blob([this.editor.getValue(0)])
downLink.href = URL.createObjectURL(blob)
document.body.appendChild(downLink)
downLink.click()
document.body.removeChild(downLink)
},
2020-05-17 16:53:21 +08:00
...mapMutations(['clearEditorToDefault','setCurrentColor', 'setCiteStatus', 'themeChanged',
2020-05-02 17:40:03 +08:00
'setHtml', 'setCurrentFont', 'setCurrentSize', 'setCssEditorValue', 'setWxRendererOptions'])
2020-05-01 21:30:25 +08:00
},
2020-05-02 11:50:26 +08:00
mounted() {
this.selectFont = this.currentFont
this.selectSize = this.currentSize
this.selectColor = this.currentColor
}
2020-05-01 21:30:25 +08:00
}
</script>
<style lang="less" scoped>
2020-05-02 11:50:26 +08:00
.editor__header {
width: 100%;
}
.header__item {
margin: 0 3px;
}
.header__item_last {
margin-right: 8px;
}
.header__switch {
margin-left: 8px;
}
2020-05-17 16:53:21 +08:00
.mode__switch {
margin-left: 24px;
width: 24px;
height: 24px;
background: url('../../assets/images/night.png') no-repeat;
background-size: cover;
transition: all .3s;
}
.mode__switch_black {
background: url('../../assets/images/light.png') no-repeat;
background-size: cover;
}
.top {
margin-right: 0;
}
2020-05-01 21:30:25 +08:00
</style>