md/src/components/CodemirrorEditor/header.vue

392 lines
12 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-10-20 20:03:36 +08:00
<el-tooltip
:effect="effect"
content="上传图片"
placement="bottom-start"
>
<i
class="el-icon-upload"
size="medium"
2020-11-22 22:36:35 +08:00
@click="$emit('show-dialog-upload-img')"
2020-10-20 20:03:36 +08:00
></i>
2020-08-30 20:21:15 +08:00
</el-tooltip>
2020-05-01 21:30:25 +08:00
<!-- 下载文本文档 -->
2020-10-20 20:03:36 +08:00
<el-tooltip
class="header__item"
:effect="effect"
2020-11-22 22:36:35 +08:00
content="下载 Markdown 文档"
2020-10-20 20:03:36 +08:00
placement="bottom-start"
>
<i
class="el-icon-download"
size="medium"
2020-11-22 22:36:35 +08:00
@click="$emit('download')"
2020-10-20 20:03:36 +08:00
></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
<!-- 页面重置 -->
2020-10-20 20:03:36 +08:00
<el-tooltip
class="header__item"
:effect="effect"
content="重置页面"
placement="bottom-start"
>
<i
class="el-icon-refresh"
size="medium"
@click="showResetConfirm = true"
></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
<!-- 插入表格 -->
2020-10-20 20:03:36 +08:00
<el-tooltip
class="header__item header__item_last"
:effect="effect"
content="插入表格"
placement="bottom-start"
>
<i
class="el-icon-s-grid"
size="medium"
@click="$emit('showDialogForm')"
></i>
2020-05-01 21:30:25 +08:00
</el-tooltip>
2020-10-20 20:03:36 +08:00
<el-form size="mini" class="ctrl" :inline="true">
2020-05-01 21:30:25 +08:00
<el-form-item>
2020-10-20 20:03:36 +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"
:label="font.label"
:value="font.value"
>
2020-07-19 15:46:05 +08:00
<span class="select-item-left">{{ font.label }}</span>
<span class="select-item-right">Abc</span>
</el-option>
</el-select>
2020-05-01 21:30:25 +08:00
</el-form-item>
<el-form-item>
2020-10-20 20:03:36 +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-07-19 15:46:05 +08:00
<span class="select-item-left">{{ size.label }}</span>
<span class="select-item-right">{{ size.desc }}</span>
</el-option>
</el-select>
2020-05-01 21:30:25 +08:00
</el-form-item>
<el-form-item>
2020-10-20 20:03:36 +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-07-19 15:46:05 +08:00
<span class="select-item-left">{{ color.label }}</span>
<span class="select-item-right">{{ color.desc }}</span>
2020-07-19 15:46:05 +08:00
</el-option>
</el-select>
2020-05-01 21:30:25 +08:00
</el-form-item>
2020-05-17 16:53:21 +08:00
<el-tooltip content="自定义颜色" :effect="effect" placement="top">
2020-10-20 20:03:36 +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-10-20 20:03:36 +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"
>
2020-05-17 16:53:21 +08:00
</el-switch>
2020-05-01 21:30:25 +08:00
</el-tooltip>
</el-form>
2020-10-20 20:03:36 +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>
2020-05-17 16:53:21 +08:00
</el-tooltip>
2020-10-20 20:03:36 +08:00
<el-button
:type="btnType"
plain
size="medium"
@click="copy"
placement="bottom-start"
>复制</el-button
>
<el-button
:type="btnType"
plain
size="medium"
class="about"
2020-11-22 22:36:35 +08:00
@click="$emit('show-about-dialog')"
2020-10-20 20:03:36 +08:00
>关于</el-button
>
<el-tooltip
:content="btnContent"
:effect="effect"
placement="bottom-start"
>
<div
class="mode__switch mode__switch_black"
v-if="nightMode"
@click="themeChanged"
></div>
<div class="mode__switch" v-else @click="themeChanged"></div>
2020-05-01 21:30:25 +08:00
</el-tooltip>
2020-10-20 20:03:36 +08:00
<resetDialog
:showResetConfirm="showResetConfirm"
@confirm="confirmReset"
@close="cancelReset"
/>
</el-container>
2020-05-01 21:30:25 +08:00
</template>
<script>
2020-05-02 11:50:26 +08:00
import {
2020-11-22 22:36:35 +08:00
downloadMD,
2020-05-02 11:50:26 +08:00
setFontSize,
2020-07-13 00:26:29 +08:00
fixCodeWhiteSpace,
2020-10-20 20:03:36 +08:00
setColorWithCustomTemplate,
} from "../../assets/scripts/util";
import { solveWeChatImage, solveHtml } from "../../assets/scripts/converter";
import config from "../../assets/scripts/config";
import DEFAULT_CSS_CONTENT from "../../assets/scripts/themes/default-theme-css";
import resetDialog from "./resetDialog";
import { mapState, mapMutations } from "vuex";
2020-05-01 21:30:25 +08:00
export default {
2020-10-20 20:03:36 +08:00
name: "editor-header",
2020-05-02 11:50:26 +08:00
data() {
return {
config: config,
citeStatus: false,
2020-05-17 22:19:45 +08:00
showResetConfirm: false,
2020-10-20 20:03:36 +08:00
selectFont: "",
selectSize: "",
selectColor: "",
selectCodeTheme: "github",
2020-05-02 11:50:26 +08:00
};
},
2020-05-17 22:19:45 +08:00
components: {
2020-10-20 20:03:36 +08:00
resetDialog,
2020-05-17 22:19:45 +08:00
},
2020-05-02 11:50:26 +08:00
computed: {
2020-05-17 16:53:21 +08:00
effect() {
2020-10-20 20:03:36 +08:00
return this.nightMode ? "dark" : "light";
2020-05-17 16:53:21 +08:00
},
btnContent() {
2020-10-20 20:03:36 +08:00
return this.nightMode ? "浅色模式" : "暗黑模式";
},
2020-05-17 16:53:21 +08:00
btnType() {
2020-10-20 20:03:36 +08:00
return this.nightMode ? "default" : "primary";
2020-05-17 16:53:21 +08:00
},
2020-05-02 11:50:26 +08:00
...mapState({
2020-10-20 20:03:36 +08:00
output: (state) => state.output,
editor: (state) => state.editor,
cssEditor: (state) => state.cssEditor,
currentFont: (state) => state.currentFont,
currentSize: (state) => state.currentSize,
currentColor: (state) => state.currentColor,
codeTheme: (state) => state.codeTheme,
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({
2020-10-20 20:03:36 +08:00
fonts: fonts,
2020-10-13 00:07:14 +08:00
});
2020-05-02 11:50:26 +08:00
this.setCurrentFont(fonts);
2020-10-20 20:03:36 +08:00
this.$emit("refresh");
2020-05-02 11:50:26 +08:00
},
sizeChanged(size) {
2020-10-20 20:03:36 +08:00
let theme = setFontSize(size.replace("px", ""));
theme = setColorWithCustomTemplate(theme, this.currentColor);
2020-05-02 11:50:26 +08:00
this.setWxRendererOptions({
size: size,
2020-10-20 20:03:36 +08:00
theme: theme,
2020-10-13 00:07:14 +08:00
});
2020-05-02 11:50:26 +08:00
this.setCurrentSize(size);
2020-10-20 20:03:36 +08:00
this.$emit("refresh");
2020-05-02 11:50:26 +08:00
},
colorChanged(color) {
2020-10-20 20:03:36 +08:00
let theme = setFontSize(this.currentSize.replace("px", ""));
2020-10-13 00:07:14 +08:00
theme = setColorWithCustomTemplate(theme, color);
2020-05-02 11:50:26 +08:00
this.setWxRendererOptions({
2020-10-20 20:03:36 +08:00
theme: theme,
2020-10-13 00:07:14 +08:00
});
2020-05-02 11:50:26 +08:00
this.setCurrentColor(color);
2020-10-20 20:03:36 +08:00
this.$emit("refresh");
2020-05-02 11:50:26 +08:00
},
2020-07-19 15:46:05 +08:00
codeThemeChanged(theme) {
this.setCurrentCodeTheme(theme);
2020-10-20 20:03:36 +08:00
this.$emit("refresh");
2020-07-19 15:46:05 +08:00
},
2020-05-02 11:50:26 +08:00
statusChanged(val) {
2020-10-13 00:07:14 +08:00
this.setCiteStatus(val);
2020-10-20 20:03:36 +08:00
this.$emit("refresh");
2020-05-02 11:50:26 +08:00
},
// 复制到微信公众号
2020-07-04 01:03:57 +08:00
copy(e) {
2020-10-20 20:03:36 +08:00
this.$emit("startCopy");
2020-05-17 22:19:45 +08:00
setTimeout(() => {
2020-10-20 20:03:36 +08:00
let clipboardDiv = document.getElementById("output");
2020-07-04 01:03:57 +08:00
solveWeChatImage();
fixCodeWhiteSpace();
2020-07-04 17:54:48 +08:00
solveHtml();
2020-07-04 01:03:57 +08:00
clipboardDiv.focus();
window.getSelection().removeAllRanges();
let range = document.createRange();
2020-05-02 17:40:03 +08:00
2020-07-04 01:03:57 +08:00
range.setStartBefore(clipboardDiv.firstChild);
range.setEndAfter(clipboardDiv.lastChild);
window.getSelection().addRange(range);
2020-10-20 20:03:36 +08:00
document.execCommand("copy");
2020-10-13 00:07:14 +08:00
window.getSelection().removeAllRanges();
2020-10-20 20:03:36 +08:00
fixCodeWhiteSpace("normal");
2020-07-04 09:41:47 +08:00
clipboardDiv.innerHTML = this.output;
2020-05-17 22:19:45 +08:00
// 输出提示
this.$notify({
showClose: true,
2020-10-20 20:03:36 +08:00
message:
"已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴",
2020-05-17 22:19:45 +08:00
offset: 80,
duration: 1600,
2020-10-20 20:03:36 +08:00
type: "success",
2020-07-04 01:03:57 +08:00
});
2020-10-20 20:03:36 +08:00
this.$emit("refresh");
this.$emit("endCopy");
2020-05-17 23:04:16 +08:00
}, 350);
2020-10-20 20:03:36 +08:00
e.target.blur();
2020-05-02 11:50:26 +08:00
},
// 自定义CSS样式
2020-08-30 09:43:05 +08:00
async customStyle() {
2020-10-20 20:03:36 +08:00
this.$emit("showCssEditor");
2020-05-02 11:50:26 +08:00
this.$nextTick(() => {
2020-10-20 20:03:36 +08:00
if (!this.cssEditor) {
2020-10-13 00:07:14 +08:00
this.cssEditor.refresh();
2020-05-02 11:50:26 +08:00
}
2020-10-20 20:03:36 +08:00
});
2020-05-02 11:50:26 +08:00
setTimeout(() => {
2020-10-13 00:07:14 +08:00
this.cssEditor.refresh();
2020-10-20 20:03:36 +08:00
}, 50);
2020-05-02 11:50:26 +08:00
2020-11-21 09:33:45 +08:00
let flag = await localStorage.getItem("__css_content");
2020-05-02 11:50:26 +08:00
if (!flag) {
2020-10-13 00:07:14 +08:00
this.setCssEditorValue(DEFAULT_CSS_CONTENT);
2020-05-02 11:50:26 +08:00
}
},
// 重置页面
2020-05-17 22:19:45 +08:00
confirmReset() {
2020-10-20 20:03:36 +08:00
localStorage.clear();
2020-05-17 22:19:45 +08:00
this.clearEditorToDefault();
2020-10-20 20:03:36 +08:00
this.editor.focus();
2020-05-17 22:19:45 +08:00
this.citeStatus = false;
this.statusChanged(false);
2020-10-20 20:03:36 +08:00
this.fontChanged(this.config.builtinFonts[0].value);
2020-11-22 22:36:35 +08:00
this.colorChanged(this.config.colorOption[0].value);
2020-10-20 20:03:36 +08:00
this.sizeChanged(this.config.sizeOption[2].value);
this.$emit("cssChanged");
2020-06-06 10:35:11 +08:00
this.selectFont = this.currentFont;
this.selectSize = this.currentSize;
this.selectColor = this.currentColor;
2020-05-23 15:09:04 +08:00
this.showResetConfirm = false;
2020-05-17 22:19:45 +08:00
},
cancelReset() {
this.showResetConfirm = false;
2020-10-20 20:03:36 +08:00
this.editor.focus();
2020-05-02 11:50:26 +08:00
},
2020-07-19 15:46:05 +08:00
...mapMutations([
2020-10-20 20:03:36 +08:00
"clearEditorToDefault",
"setCurrentColor",
"setCiteStatus",
"themeChanged",
"setCurrentFont",
"setCurrentSize",
"setCssEditorValue",
"setCurrentCodeTheme",
"setWxRendererOptions",
]),
2020-05-01 21:30:25 +08:00
},
2020-05-02 11:50:26 +08:00
mounted() {
2020-06-06 10:35:11 +08:00
this.selectFont = this.currentFont;
this.selectSize = this.currentSize;
this.selectColor = this.currentColor;
2020-07-28 20:42:05 +08:00
this.selectCodeTheme = this.codeTheme;
2020-10-20 20:03:36 +08:00
},
};
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;
2020-10-20 20:03:36 +08:00
background: url("../../assets/images/night.png") no-repeat;
2020-05-17 16:53:21 +08:00
background-size: cover;
2020-10-20 20:03:36 +08:00
transition: all 0.3s;
2020-05-17 16:53:21 +08:00
}
.mode__switch_black {
2020-10-20 20:03:36 +08:00
background: url("../../assets/images/light.png") no-repeat;
2020-05-17 16:53:21 +08:00
background-size: cover;
}
.top {
margin-right: 0;
}
2020-10-20 20:03:36 +08:00
</style>