mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
Merge branch 'master' of github.com:doocs/md
This commit is contained in:
commit
5ae6fd4b28
28
src/App.vue
28
src/App.vue
@ -6,36 +6,38 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Loading from './components/Loading'
|
||||
import CodemirrorEditor from './view/CodemirrorEditor'
|
||||
import Loading from "./components/Loading";
|
||||
import CodemirrorEditor from "./view/CodemirrorEditor";
|
||||
export default {
|
||||
name: 'App',
|
||||
name: "App",
|
||||
components: {
|
||||
Loading,
|
||||
CodemirrorEditor
|
||||
CodemirrorEditor,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true
|
||||
}
|
||||
loading: true,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this.loading = false
|
||||
this.loading = false;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fade-enter, .fade-leave-to {
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
.fade-enter-to, .fade-leave {
|
||||
.fade-enter-to,
|
||||
.fade-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: all 1s;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,14 +1,14 @@
|
||||
@import './code-theme.less';
|
||||
@import "./code-theme.less";
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
h1,
|
||||
@ -17,109 +17,110 @@ h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: normal !important;
|
||||
font-style: normal !important;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif;
|
||||
height: 100%;
|
||||
font-family: "PingFang SC", BlinkMacSystemFont, Roboto, "Helvetica Neue",
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
.el-message__icon {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.top {
|
||||
height: 60px;
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
height: 60px;
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.web-title {
|
||||
margin: 0 15px 0 5px;
|
||||
margin: 0 15px 0 5px;
|
||||
}
|
||||
|
||||
.web-icon {
|
||||
width: auto;
|
||||
height: 1.5rem;
|
||||
vertical-align: middle;
|
||||
width: auto;
|
||||
height: 1.5rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#editor {
|
||||
height: 100%;
|
||||
display: block;
|
||||
border: none;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border: none;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
section {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 0;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 0;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.ctrl {
|
||||
flex-basis: 60px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-basis: 60px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.preview-wrapper {
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
overflow: scroll;
|
||||
word-break: break-all;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
overflow: scroll;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.main-section {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hint {
|
||||
opacity: 0.6;
|
||||
margin: 20px 0;
|
||||
opacity: 0.6;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.preview {
|
||||
margin: 0 -20px;
|
||||
width: 375px;
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
box-shadow: 0 0 60px rgba(0, 0, 0, 0.1);
|
||||
margin: 0 -20px;
|
||||
width: 375px;
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
box-shadow: 0 0 60px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.preview table {
|
||||
margin-bottom: 10px;
|
||||
border-collapse: collapse;
|
||||
display: table;
|
||||
width: 100% !important;
|
||||
margin-bottom: 10px;
|
||||
border-collapse: collapse;
|
||||
display: table;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -128,60 +129,61 @@ section {
|
||||
}
|
||||
*/
|
||||
.select-item-left {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select-item-right {
|
||||
float: right;
|
||||
color: #8492a6;
|
||||
font-size: 13px;
|
||||
float: right;
|
||||
color: #8492a6;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
height: 100% !important;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
width: 100% !important;
|
||||
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif !important;
|
||||
height: 100% !important;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
width: 100% !important;
|
||||
font-family: "PingFang SC", BlinkMacSystemFont, Roboto, "Helvetica Neue",
|
||||
sans-serif !important;
|
||||
}
|
||||
|
||||
/* ele ui */
|
||||
.el-form-item {
|
||||
margin-bottom: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.el-tooltip {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: #FFF;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
border-radius: 6px;
|
||||
background-color: rgba(200, 200, 200, 0.3);
|
||||
border-radius: 6px;
|
||||
background-color: rgba(200, 200, 200, 0.3);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
background-color: rgba(144, 146, 152, 0.5);
|
||||
transition: background-color .3s;
|
||||
border-radius: 6px;
|
||||
background-color: rgba(144, 146, 152, 0.5);
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(144, 146, 152, 0.5);
|
||||
background-color: rgba(144, 146, 152, 0.5);
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar:focus {
|
||||
outline: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll,
|
||||
.preview-wrapper {
|
||||
overflow: unset;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
overflow: unset;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
@import './codeTheme/wechat-code-block.less';
|
||||
@import './codeTheme/github-code-block.less';
|
||||
@import "./codeTheme/wechat-code-block.less";
|
||||
@import "./codeTheme/github-code-block.less";
|
||||
|
@ -1,47 +1,47 @@
|
||||
/*github code block*/
|
||||
.code-snippet__github {
|
||||
display: flex;
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
margin: 10px 8px;
|
||||
position: relative;
|
||||
height: auto;
|
||||
background-color: rgba(27, 31, 35, 0.05);
|
||||
|
||||
.code-snippet__line-index {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.code__pre {
|
||||
display: grid;
|
||||
position: relative;
|
||||
counter-reset: line;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
white-space: normal;
|
||||
flex: 1;
|
||||
line-height: 20px;
|
||||
font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
margin: 10px 8px;
|
||||
position: relative;
|
||||
height: auto;
|
||||
background-color: rgba(27,31,35,.05);
|
||||
}
|
||||
|
||||
.code-snippet__line-index {
|
||||
display: none;
|
||||
code {
|
||||
display: flex;
|
||||
position: relative;
|
||||
padding-right: 8px;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.code__pre {
|
||||
display: grid;
|
||||
position: relative;
|
||||
counter-reset: line;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
white-space: normal;
|
||||
flex: 1;
|
||||
line-height: 20px;
|
||||
font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
code {
|
||||
display: flex;
|
||||
position: relative;
|
||||
padding-right: 8px;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul li {
|
||||
list-style: none;
|
||||
}
|
||||
}
|
||||
ul li {
|
||||
list-style: none;
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +1,62 @@
|
||||
/*wechat code block*/
|
||||
.rich_media_content .code-snippet *,
|
||||
.rich_media_content .code-snippet__wechat * {
|
||||
max-width: 1000% !important;
|
||||
max-width: 1000% !important;
|
||||
}
|
||||
|
||||
.code-snippet__wechat {
|
||||
word-wrap: break-word !important;
|
||||
font-size: 14px;
|
||||
margin: 10px 8px;
|
||||
color: #333;
|
||||
position: relative;
|
||||
background-color: rgba(27, 31, 35, .05);
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
line-height: 24px;
|
||||
word-wrap: break-word !important;
|
||||
font-size: 14px;
|
||||
margin: 10px 8px;
|
||||
color: #333;
|
||||
position: relative;
|
||||
background-color: rgba(27, 31, 35, 0.05);
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.code-snippet__wechat .code-snippet__line-index {
|
||||
counter-reset: line;
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
list-style-type: none;
|
||||
counter-reset: line;
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.code-snippet__wechat .code-snippet__line-index li {
|
||||
list-style-type: none;
|
||||
text-align: right;
|
||||
list-style-type: none;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.code-snippet__wechat .code-snippet__line-index li::before {
|
||||
min-width: 1.5em;
|
||||
text-align: right;
|
||||
left: -2.5em;
|
||||
counter-increment: line;
|
||||
content: counter(line);
|
||||
display: inline;
|
||||
color: rgba(0, 0, 0, 0.15);
|
||||
min-width: 1.5em;
|
||||
text-align: right;
|
||||
left: -2.5em;
|
||||
counter-increment: line;
|
||||
content: counter(line);
|
||||
display: inline;
|
||||
color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.code-snippet__wechat pre {
|
||||
overflow-x: auto;
|
||||
padding: 1em 1em 1em 1em;
|
||||
white-space: normal;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overflow-x: auto;
|
||||
padding: 1em 1em 1em 1em;
|
||||
white-space: normal;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.code-snippet__wechat code {
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
display: flex;
|
||||
position: relative;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
display: flex;
|
||||
position: relative;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.code-snippet__wechat ul li {
|
||||
list-style: none;
|
||||
}
|
||||
list-style: none;
|
||||
}
|
||||
|
72
src/assets/less/github-v2.min.css
vendored
72
src/assets/less/github-v2.min.css
vendored
@ -1,2 +1,72 @@
|
||||
/*! Color themes for Google Code Prettify | MIT License | github.com/jmblog/color-themes-for-google-code-prettify */
|
||||
.prettyprint{font-family:Menlo,Bitstream Vera Sans Mono,DejaVu Sans Mono,Monaco,Consolas,monospace;border:0!important}.pln{color:#333}ol.linenums{margin-top:0;margin-bottom:0;color:#ccc}li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{padding-left:1em;background-color:#fff;list-style-type:decimal}@media screen{.str{color:#183691}.kwd{color:#a71d5d}.com{color:#969896}.typ{color:#0086b3}.lit{color:#0086b3}.pun{color:#333}.opn{color:#333}.clo{color:#333}.tag{color:navy}.atn{color:#795da3}.atv{color:#183691}.dec{color:#333}.var{color:teal}.fun{color:#900}}
|
||||
.prettyprint {
|
||||
font-family: Menlo, Bitstream Vera Sans Mono, DejaVu Sans Mono, Monaco,
|
||||
Consolas, monospace;
|
||||
border: 0 !important;
|
||||
}
|
||||
.pln {
|
||||
color: #333;
|
||||
}
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: #ccc;
|
||||
}
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L4,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8,
|
||||
li.L9 {
|
||||
padding-left: 1em;
|
||||
background-color: #fff;
|
||||
list-style-type: decimal;
|
||||
}
|
||||
@media screen {
|
||||
.str {
|
||||
color: #183691;
|
||||
}
|
||||
.kwd {
|
||||
color: #a71d5d;
|
||||
}
|
||||
.com {
|
||||
color: #969896;
|
||||
}
|
||||
.typ {
|
||||
color: #0086b3;
|
||||
}
|
||||
.lit {
|
||||
color: #0086b3;
|
||||
}
|
||||
.pun {
|
||||
color: #333;
|
||||
}
|
||||
.opn {
|
||||
color: #333;
|
||||
}
|
||||
.clo {
|
||||
color: #333;
|
||||
}
|
||||
.tag {
|
||||
color: navy;
|
||||
}
|
||||
.atn {
|
||||
color: #795da3;
|
||||
}
|
||||
.atv {
|
||||
color: #183691;
|
||||
}
|
||||
.dec {
|
||||
color: #333;
|
||||
}
|
||||
.var {
|
||||
color: teal;
|
||||
}
|
||||
.fun {
|
||||
color: #900;
|
||||
}
|
||||
}
|
||||
|
@ -9,116 +9,116 @@
|
||||
*/
|
||||
|
||||
.cm-s-style-mirror.CodeMirror {
|
||||
background: #f5f5f5;
|
||||
color: #444;
|
||||
font-size: 16px;
|
||||
padding: 20px;
|
||||
line-height: 25px;
|
||||
background: #f5f5f5;
|
||||
color: #444;
|
||||
font-size: 16px;
|
||||
padding: 20px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror div.CodeMirror-selected {
|
||||
background: #e0e0e0;
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-line::selection,
|
||||
.cm-s-style-mirror .CodeMirror-line>span::selection,
|
||||
.cm-s-style-mirror .CodeMirror-line>span>span::selection {
|
||||
background: #e0e0e0;
|
||||
.cm-s-style-mirror .CodeMirror-line > span::selection,
|
||||
.cm-s-style-mirror .CodeMirror-line > span > span::selection {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-line::-moz-selection,
|
||||
.cm-s-style-mirror .CodeMirror-line>span::-moz-selection,
|
||||
.cm-s-style-mirror .CodeMirror-line>span>span::-moz-selection {
|
||||
background: #e0e0e0;
|
||||
.cm-s-style-mirror .CodeMirror-line > span::-moz-selection,
|
||||
.cm-s-style-mirror .CodeMirror-line > span > span::-moz-selection {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-gutters {
|
||||
background: #f5f5f5;
|
||||
border-right: 0px;
|
||||
background: #f5f5f5;
|
||||
border-right: 0px;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-guttermarker {
|
||||
color: #ac4142;
|
||||
color: #ac4142;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-guttermarker-subtle {
|
||||
color: #b0b0b0;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-linenumber {
|
||||
color: #b0b0b0;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-cursor {
|
||||
border-left: 1px solid #505050;
|
||||
border-left: 1px solid #505050;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-comment {
|
||||
color: green;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-atom {
|
||||
color: #aa759f;
|
||||
color: #aa759f;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-number {
|
||||
color: #aa759f;
|
||||
color: #aa759f;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-property,
|
||||
.cm-s-style-mirror span.cm-attribute {
|
||||
color: #90a959;
|
||||
color: #90a959;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-keyword {
|
||||
color: #023a52;
|
||||
color: #023a52;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-string {
|
||||
color: #e46918;
|
||||
color: #e46918;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-variable {
|
||||
color: #90a959;
|
||||
color: #90a959;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-variable-2 {
|
||||
color: #00695f;
|
||||
color: #00695f;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-variable-3 {
|
||||
color: #2e6e8a;
|
||||
color: #2e6e8a;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-def {
|
||||
color: #d28445;
|
||||
color: #d28445;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-bracket {
|
||||
color: #202020;
|
||||
color: #202020;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-tag {
|
||||
color: #000;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-link {
|
||||
color: #b26a00;
|
||||
color: #b26a00;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror span.cm-error {
|
||||
/* background: #ac4142;
|
||||
/* background: #ac4142;
|
||||
color: #f5f5f5; */
|
||||
text-decoration: underline;
|
||||
text-decoration-style: wavy;
|
||||
text-decoration-color: #df8d8e;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: wavy;
|
||||
text-decoration-color: #df8d8e;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-activeline-background {
|
||||
background: #dddcdc;
|
||||
background: #dddcdc;
|
||||
}
|
||||
|
||||
.cm-s-style-mirror .CodeMirror-matchingbracket {
|
||||
color: rgb(32, 32, 32) !important;
|
||||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
color: rgb(32, 32, 32) !important;
|
||||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
@ -10,85 +10,94 @@
|
||||
@nightButtonBg: #1e1e1e;
|
||||
@nightButtonHoverColor: #84868b;
|
||||
.container_night {
|
||||
background-color: @nightBgColor;
|
||||
.el-main {
|
||||
background-color: @nightBgColor;
|
||||
.el-main {
|
||||
background-color: @nightBgColor;
|
||||
}
|
||||
.CodeMirror {
|
||||
caret-color: @nightFontColor;
|
||||
color: @nightFontColor;
|
||||
background-color: @nightCodeMirrorColor;
|
||||
box-shadow: inset 0 0 0 1px rgba(100, 37, 37, 0.102);
|
||||
}
|
||||
.output_night {
|
||||
.preview {
|
||||
background-color: @nightPreviewColor;
|
||||
box-shadow: 0 0 70px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.CodeMirror {
|
||||
caret-color: @nightFontColor;
|
||||
color: @nightFontColor;
|
||||
background-color: @nightCodeMirrorColor;
|
||||
box-shadow: inset 0 0 0 1px rgba(100, 37, 37, 0.102);
|
||||
.preview-wrapper {
|
||||
background-color: @nightCodeMirrorColor;
|
||||
box-shadow: inset 0 0 0 1px rgba(233, 231, 231, 0.102);
|
||||
}
|
||||
.output_night {
|
||||
.preview {
|
||||
background-color: @nightPreviewColor;
|
||||
box-shadow: 0 0 70px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.preview-wrapper {
|
||||
background-color: @nightCodeMirrorColor;
|
||||
box-shadow: inset 0 0 0 1px rgba(233, 231, 231, 0.102);
|
||||
}
|
||||
.code-snippet__fix {
|
||||
background-color: rgb(238,238,238);
|
||||
}
|
||||
.code-snippet__fix {
|
||||
background-color: rgb(238, 238, 238);
|
||||
}
|
||||
.cm-s-style-mirror .CodeMirror-matchingbracket {
|
||||
color: @nightWhiteColor!important;
|
||||
background: rgb(30, 30, 30)!important;
|
||||
}
|
||||
.cm-s-style-mirror .CodeMirror-matchingbracket {
|
||||
color: @nightWhiteColor!important;
|
||||
background: rgb(30, 30, 30) !important;
|
||||
}
|
||||
.cm-s-xq-light span.cm-variable-2,
|
||||
.cm-s-style-mirror span.cm-tag {
|
||||
color: @nightFontColor;
|
||||
}
|
||||
.cm-s-xq-light .CodeMirror-activeline-background {
|
||||
background-color: transparent;
|
||||
}
|
||||
.cm-s-xq-light span.cm-string {
|
||||
color: @nightLinkColor;
|
||||
}
|
||||
.cm-s-xq-light span.cm-link {
|
||||
color: @nightLinkTextColor;
|
||||
}
|
||||
.editor__header {
|
||||
background-color: @nightHeaderColor;
|
||||
}
|
||||
.el-button {
|
||||
color: @nightWhiteColor;
|
||||
background-color: @nightCodeMirrorColor;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.el-button.is-plain:focus,
|
||||
.el-button.is-plain:hover {
|
||||
background: @nightButtonBg;
|
||||
color: @nightWhiteColor;
|
||||
border: 1px solid @nightWhiteColor;
|
||||
i {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.cm-s-xq-light span.cm-variable-2, .cm-s-style-mirror span.cm-tag {
|
||||
color: @nightFontColor;
|
||||
}
|
||||
.insert__dialog,
|
||||
.about__dialog,
|
||||
.reset__dialog,
|
||||
.upload__dialog {
|
||||
.el-dialog {
|
||||
background-color: @nightBgColor;
|
||||
}
|
||||
.cm-s-xq-light .CodeMirror-activeline-background {
|
||||
background-color: transparent;
|
||||
.el-dialog__body {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.cm-s-xq-light span.cm-string {
|
||||
color: @nightLinkColor;
|
||||
.el-dialog__title,
|
||||
.el-form-item__label {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.cm-s-xq-light span.cm-link {
|
||||
color: @nightLinkTextColor;
|
||||
.el-tabs__item {
|
||||
color: @nightActiveCodeMirrorColor;
|
||||
}
|
||||
.editor__header {
|
||||
background-color: @nightHeaderColor;
|
||||
.is-active {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.el-button {
|
||||
color: @nightWhiteColor;
|
||||
background-color: @nightCodeMirrorColor;
|
||||
border: 1px solid transparent;
|
||||
.el-upload-dragger {
|
||||
background-color: @nightButtonBg;
|
||||
}
|
||||
.el-button.is-plain:focus, .el-button.is-plain:hover {
|
||||
background: @nightButtonBg;
|
||||
color: @nightWhiteColor;
|
||||
border: 1px solid @nightWhiteColor;
|
||||
i {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
}
|
||||
.insert__dialog, .about__dialog, .reset__dialog, .upload__dialog {
|
||||
.el-dialog {
|
||||
background-color: @nightBgColor;
|
||||
}
|
||||
.el-dialog__body {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.el-dialog__title, .el-form-item__label {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.el-tabs__item {
|
||||
color: @nightActiveCodeMirrorColor;
|
||||
}
|
||||
.is-active {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
.el-upload-dragger {
|
||||
background-color: @nightButtonBg;
|
||||
}
|
||||
}
|
||||
::v-deep .el-icon-upload, .el-icon-download, .el-icon-refresh, .el-icon-s-grid {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
background-color: @nightCodeMirrorColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
::v-deep .el-icon-upload,
|
||||
.el-icon-download,
|
||||
.el-icon-refresh,
|
||||
.el-icon-s-grid {
|
||||
color: @nightWhiteColor;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
background-color: @nightCodeMirrorColor;
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,35 @@
|
||||
<template>
|
||||
<el-dialog title="关于" class="about__dialog" :visible="value" @close="$emit('input', false)" width="30%" center>
|
||||
<div style="text-align: center;">
|
||||
<el-dialog
|
||||
title="关于"
|
||||
class="about__dialog"
|
||||
:visible="value"
|
||||
@close="$emit('input', false)"
|
||||
width="30%"
|
||||
center
|
||||
>
|
||||
<div style="text-align: center">
|
||||
<h3>一款高度简洁的微信 Markdown 编辑器</h3>
|
||||
</div>
|
||||
<div style="text-align: center;margin-top:10px;">
|
||||
<div style="text-align: center; margin-top: 10px">
|
||||
<p>扫码关注我的公众号,原创技术文章第一时间推送!</p>
|
||||
<img src="https://gitee.com/yanglbme/resource/raw/master/doocs-md/qrcode.png" style="width: 40%; display: block; margin: 20px auto 10px;">
|
||||
<img
|
||||
src="https://gitee.com/yanglbme/resource/raw/master/doocs-md/qrcode.png"
|
||||
style="width: 40%; display: block; margin: 20px auto 10px"
|
||||
/>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="onRedirect('https://github.com/doocs/md')" plain>GitHub 仓库</el-button>
|
||||
<el-button type="primary" @click="onRedirect('https://gitee.com/doocs/md')" plain>Gitee 仓库</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onRedirect('https://github.com/doocs/md')"
|
||||
plain
|
||||
>GitHub 仓库</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onRedirect('https://gitee.com/doocs/md')"
|
||||
plain
|
||||
>Gitee 仓库</el-button
|
||||
>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@ -19,16 +39,15 @@ export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onRedirect(url) {
|
||||
window.open(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
|
@ -1,162 +1,278 @@
|
||||
<template>
|
||||
<el-container class="top is-dark">
|
||||
<!-- 图片上传 -->
|
||||
<el-tooltip :effect="effect" content="上传图片" placement="bottom-start">
|
||||
<i class="el-icon-upload" size="medium" @click="$emit('showDialogUploadImg')"></i>
|
||||
<el-tooltip
|
||||
:effect="effect"
|
||||
content="上传图片"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<i
|
||||
class="el-icon-upload"
|
||||
size="medium"
|
||||
@click="$emit('showDialogUploadImg')"
|
||||
></i>
|
||||
</el-tooltip>
|
||||
<!-- 下载文本文档 -->
|
||||
<el-tooltip class="header__item" :effect="effect" content="下载编辑框Markdown文档" placement="bottom-start">
|
||||
<i class="el-icon-download" size="medium" @click="$emit('downLoad')"></i>
|
||||
<el-tooltip
|
||||
class="header__item"
|
||||
:effect="effect"
|
||||
content="下载编辑框Markdown文档"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<i
|
||||
class="el-icon-download"
|
||||
size="medium"
|
||||
@click="$emit('downLoad')"
|
||||
></i>
|
||||
</el-tooltip>
|
||||
<!-- 页面重置 -->
|
||||
<el-tooltip class="header__item" :effect="effect" content="重置页面" placement="bottom-start">
|
||||
<i class="el-icon-refresh" size="medium" @click="showResetConfirm = true"></i>
|
||||
<el-tooltip
|
||||
class="header__item"
|
||||
:effect="effect"
|
||||
content="重置页面"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<i
|
||||
class="el-icon-refresh"
|
||||
size="medium"
|
||||
@click="showResetConfirm = true"
|
||||
></i>
|
||||
</el-tooltip>
|
||||
<!-- 插入表格 -->
|
||||
<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>
|
||||
<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>
|
||||
</el-tooltip>
|
||||
<el-form size="mini" class="ctrl" :inline=true>
|
||||
<el-form size="mini" class="ctrl" :inline="true">
|
||||
<el-form-item>
|
||||
<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">
|
||||
<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"
|
||||
>
|
||||
<span class="select-item-left">{{ font.label }}</span>
|
||||
<span class="select-item-right">Abc</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<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">
|
||||
<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"
|
||||
>
|
||||
<span class="select-item-left">{{ size.label }}</span>
|
||||
<span class="select-item-right">{{ size.desc }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<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">
|
||||
<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"
|
||||
>
|
||||
<span class="select-item-left">{{ color.label }}</span>
|
||||
<span class="select-item-right">{{ color.desc }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-tooltip content="自定义颜色" :effect="effect" placement="top">
|
||||
<el-color-picker v-model="selectColor" size="mini" show-alpha @change="colorChanged"></el-color-picker>
|
||||
<el-color-picker
|
||||
v-model="selectColor"
|
||||
size="mini"
|
||||
show-alpha
|
||||
@change="colorChanged"
|
||||
></el-color-picker>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="微信外链自动转为文末引用" :effect="effect" placement="top">
|
||||
<el-switch class="header__switch" v-model="citeStatus" active-color="#67c23a" inactive-color="#dcdfe6" @change="statusChanged">
|
||||
<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>
|
||||
</el-tooltip>
|
||||
</el-form>
|
||||
<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
|
||||
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" placement="bottom-start">复制</el-button>
|
||||
<el-button :type="btnType" plain size="medium" class="about" @click="$emit('showAboutDialog')">关于</el-button>
|
||||
<el-tooltip :content="btnContent" :effect="effect" placement="bottom-start">
|
||||
<div class="mode__switch mode__switch_black" v-if="nightMode" @click="themeChanged"></div>
|
||||
<el-button
|
||||
:type="btnType"
|
||||
plain
|
||||
size="medium"
|
||||
@click="copy"
|
||||
placement="bottom-start"
|
||||
>复制</el-button
|
||||
>
|
||||
<el-button
|
||||
:type="btnType"
|
||||
plain
|
||||
size="medium"
|
||||
class="about"
|
||||
@click="$emit('showAboutDialog')"
|
||||
>关于</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>
|
||||
</el-tooltip>
|
||||
<resetDialog :showResetConfirm="showResetConfirm" @confirm="confirmReset" @close="cancelReset"/>
|
||||
</el-container>
|
||||
<resetDialog
|
||||
:showResetConfirm="showResetConfirm"
|
||||
@confirm="confirmReset"
|
||||
@close="cancelReset"
|
||||
/>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
downLoadMD,
|
||||
setFontSize,
|
||||
fixCodeWhiteSpace,
|
||||
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'
|
||||
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";
|
||||
export default {
|
||||
name: 'editor-header',
|
||||
name: "editor-header",
|
||||
data() {
|
||||
return {
|
||||
config: config,
|
||||
citeStatus: false,
|
||||
showResetConfirm: false,
|
||||
selectFont: '',
|
||||
selectSize: '',
|
||||
selectColor: '',
|
||||
selectCodeTheme: 'github'
|
||||
selectFont: "",
|
||||
selectSize: "",
|
||||
selectColor: "",
|
||||
selectCodeTheme: "github",
|
||||
};
|
||||
},
|
||||
components: {
|
||||
resetDialog
|
||||
resetDialog,
|
||||
},
|
||||
computed: {
|
||||
effect() {
|
||||
return this.nightMode ? 'dark' : 'light'
|
||||
return this.nightMode ? "dark" : "light";
|
||||
},
|
||||
btnContent() {
|
||||
return this.nightMode ? '浅色模式' : '暗黑模式'
|
||||
return this.nightMode ? "浅色模式" : "暗黑模式";
|
||||
},
|
||||
btnType() {
|
||||
return this.nightMode ? 'default' : 'primary';
|
||||
return this.nightMode ? "default" : "primary";
|
||||
},
|
||||
...mapState({
|
||||
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
|
||||
})
|
||||
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,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
fontChanged(fonts) {
|
||||
this.setWxRendererOptions({
|
||||
fonts: fonts
|
||||
fonts: fonts,
|
||||
});
|
||||
this.setCurrentFont(fonts);
|
||||
this.$emit('refresh');
|
||||
this.$emit("refresh");
|
||||
},
|
||||
sizeChanged(size) {
|
||||
let theme = setFontSize(size.replace('px', ''))
|
||||
theme = setColorWithCustomTemplate(theme, this.currentColor)
|
||||
let theme = setFontSize(size.replace("px", ""));
|
||||
theme = setColorWithCustomTemplate(theme, this.currentColor);
|
||||
this.setWxRendererOptions({
|
||||
size: size,
|
||||
theme: theme
|
||||
theme: theme,
|
||||
});
|
||||
this.setCurrentSize(size);
|
||||
this.$emit('refresh');
|
||||
this.$emit("refresh");
|
||||
},
|
||||
colorChanged(color) {
|
||||
let theme = setFontSize(this.currentSize.replace('px', ''));
|
||||
let theme = setFontSize(this.currentSize.replace("px", ""));
|
||||
|
||||
theme = setColorWithCustomTemplate(theme, color);
|
||||
this.setWxRendererOptions({
|
||||
theme: theme
|
||||
theme: theme,
|
||||
});
|
||||
this.setCurrentColor(color);
|
||||
this.$emit('refresh');
|
||||
this.$emit("refresh");
|
||||
},
|
||||
codeThemeChanged(theme) {
|
||||
this.setCurrentCodeTheme(theme);
|
||||
this.$emit('refresh');
|
||||
this.$emit("refresh");
|
||||
},
|
||||
statusChanged(val) {
|
||||
this.setCiteStatus(val);
|
||||
this.$emit('refresh');
|
||||
this.$emit("refresh");
|
||||
},
|
||||
// 复制到微信公众号
|
||||
copy(e) {
|
||||
this.$emit('startCopy');
|
||||
this.$emit("startCopy");
|
||||
setTimeout(() => {
|
||||
let clipboardDiv = document.getElementById('output');
|
||||
let clipboardDiv = document.getElementById("output");
|
||||
solveWeChatImage();
|
||||
fixCodeWhiteSpace();
|
||||
solveHtml();
|
||||
@ -167,36 +283,37 @@ export default {
|
||||
range.setStartBefore(clipboardDiv.firstChild);
|
||||
range.setEndAfter(clipboardDiv.lastChild);
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand('copy');
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
fixCodeWhiteSpace('normal');
|
||||
|
||||
fixCodeWhiteSpace("normal");
|
||||
|
||||
clipboardDiv.innerHTML = this.output;
|
||||
// 输出提示
|
||||
this.$notify({
|
||||
showClose: true,
|
||||
message: '已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴',
|
||||
message:
|
||||
"已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴",
|
||||
offset: 80,
|
||||
duration: 1600,
|
||||
type: 'success'
|
||||
type: "success",
|
||||
});
|
||||
this.$emit('refresh');
|
||||
this.$emit('endCopy');
|
||||
this.$emit("refresh");
|
||||
this.$emit("endCopy");
|
||||
}, 350);
|
||||
e.target.blur();
|
||||
e.target.blur();
|
||||
},
|
||||
// 自定义CSS样式
|
||||
async customStyle() {
|
||||
this.$emit('showCssEditor');
|
||||
this.$emit("showCssEditor");
|
||||
this.$nextTick(() => {
|
||||
if(!this.cssEditor) {
|
||||
if (!this.cssEditor) {
|
||||
this.cssEditor.refresh();
|
||||
}
|
||||
})
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.cssEditor.refresh();
|
||||
},50)
|
||||
let flag = await localStorage.getItem('__css_content');
|
||||
}, 50);
|
||||
let flag = await localStorage.getItem("__css_content");
|
||||
|
||||
if (!flag) {
|
||||
this.setCssEditorValue(DEFAULT_CSS_CONTENT);
|
||||
@ -204,15 +321,15 @@ export default {
|
||||
},
|
||||
// 重置页面
|
||||
confirmReset() {
|
||||
localStorage.clear()
|
||||
localStorage.clear();
|
||||
this.clearEditorToDefault();
|
||||
this.editor.focus()
|
||||
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)
|
||||
this.$emit('cssChanged')
|
||||
this.fontChanged(this.config.builtinFonts[0].value);
|
||||
this.colorChanged(this.config.colorOption[1].value);
|
||||
this.sizeChanged(this.config.sizeOption[2].value);
|
||||
this.$emit("cssChanged");
|
||||
this.selectFont = this.currentFont;
|
||||
this.selectSize = this.currentSize;
|
||||
this.selectColor = this.currentColor;
|
||||
@ -220,27 +337,27 @@ export default {
|
||||
},
|
||||
cancelReset() {
|
||||
this.showResetConfirm = false;
|
||||
this.editor.focus()
|
||||
this.editor.focus();
|
||||
},
|
||||
...mapMutations([
|
||||
'clearEditorToDefault',
|
||||
'setCurrentColor',
|
||||
'setCiteStatus',
|
||||
'themeChanged',
|
||||
'setCurrentFont',
|
||||
'setCurrentSize',
|
||||
'setCssEditorValue',
|
||||
'setCurrentCodeTheme',
|
||||
'setWxRendererOptions'
|
||||
])
|
||||
"clearEditorToDefault",
|
||||
"setCurrentColor",
|
||||
"setCiteStatus",
|
||||
"themeChanged",
|
||||
"setCurrentFont",
|
||||
"setCurrentSize",
|
||||
"setCssEditorValue",
|
||||
"setCurrentCodeTheme",
|
||||
"setWxRendererOptions",
|
||||
]),
|
||||
},
|
||||
mounted() {
|
||||
this.selectFont = this.currentFont;
|
||||
this.selectSize = this.currentSize;
|
||||
this.selectColor = this.currentColor;
|
||||
this.selectCodeTheme = this.codeTheme;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@ -260,15 +377,15 @@ export default {
|
||||
margin-left: 24px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: url('../../assets/images/night.png') no-repeat;
|
||||
background: url("../../assets/images/night.png") no-repeat;
|
||||
background-size: cover;
|
||||
transition: all .3s;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.mode__switch_black {
|
||||
background: url('../../assets/images/light.png') no-repeat;
|
||||
background: url("../../assets/images/light.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.top {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@ -6,66 +6,71 @@
|
||||
@close="$emit('input', false)"
|
||||
border
|
||||
>
|
||||
<el-row class="tb-options" type="flex" align="middle" :gutter="10">
|
||||
<el-col>
|
||||
行数:
|
||||
<el-input-number
|
||||
v-model="rowNum"
|
||||
controls-position="right"
|
||||
:min="1"
|
||||
:max="100"
|
||||
size="small"
|
||||
<el-row class="tb-options" type="flex" align="middle" :gutter="10">
|
||||
<el-col>
|
||||
行数:
|
||||
<el-input-number
|
||||
v-model="rowNum"
|
||||
controls-position="right"
|
||||
:min="1"
|
||||
:max="100"
|
||||
size="small"
|
||||
></el-input-number>
|
||||
</el-col>
|
||||
<el-col>
|
||||
列数:
|
||||
<el-input-number
|
||||
v-model="colNum"
|
||||
controls-position="right"
|
||||
:min="1"
|
||||
:max="100"
|
||||
size="small"
|
||||
</el-col>
|
||||
<el-col>
|
||||
列数:
|
||||
<el-input-number
|
||||
v-model="colNum"
|
||||
controls-position="right"
|
||||
:min="1"
|
||||
:max="100"
|
||||
size="small"
|
||||
></el-input-number>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<table style="border-collapse: collapse" class="input-table">
|
||||
<tr :class="{ 'head-style': row === 1 }" v-for="row in rowNum+1" :key="row">
|
||||
<td v-for="col in colNum" :key="col">
|
||||
<el-input
|
||||
align="center"
|
||||
v-model="tableData[`k_${row-1}_${col-1}`]"
|
||||
:placeholder="row===1?'表头':''"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :type="btnType" plain @click="$emit('input', false)">取 消</el-button>
|
||||
<el-button :type="btnType" @click="insertTable" plain>确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<table style="border-collapse: collapse" class="input-table">
|
||||
<tr
|
||||
:class="{ 'head-style': row === 1 }"
|
||||
v-for="row in rowNum + 1"
|
||||
:key="row"
|
||||
>
|
||||
<td v-for="col in colNum" :key="col">
|
||||
<el-input
|
||||
align="center"
|
||||
v-model="tableData[`k_${row - 1}_${col - 1}`]"
|
||||
:placeholder="row === 1 ? '表头' : ''"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :type="btnType" plain @click="$emit('input', false)"
|
||||
>取 消</el-button
|
||||
>
|
||||
<el-button :type="btnType" @click="insertTable" plain
|
||||
>确 定</el-button
|
||||
>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "../../assets/scripts/config";
|
||||
import {createTable} from '../../assets/scripts/util';
|
||||
import {
|
||||
mapState,
|
||||
mapMutations
|
||||
} from "vuex";
|
||||
import { createTable } from "../../assets/scripts/util";
|
||||
import { mapState, mapMutations } from "vuex";
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
config: config,
|
||||
rowNum: 3,
|
||||
colNum: 3,
|
||||
tableData: {}
|
||||
tableData: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -73,9 +78,9 @@ export default {
|
||||
return this.nightMode ? "default" : "primary";
|
||||
},
|
||||
...mapState({
|
||||
nightMode: state => state.nightMode,
|
||||
editor: state => state.editor
|
||||
})
|
||||
nightMode: (state) => state.nightMode,
|
||||
editor: (state) => state.editor,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
// 插入表格
|
||||
@ -84,18 +89,18 @@ export default {
|
||||
const table = createTable({
|
||||
data: this.tableData,
|
||||
rows: this.rowNum,
|
||||
cols: this.colNum
|
||||
cols: this.colNum,
|
||||
});
|
||||
|
||||
|
||||
this.tableData = {};
|
||||
this.rowNum = 3;
|
||||
this.colNum = 3;
|
||||
this.editor.replaceSelection(`\n${table}\n`, "end");
|
||||
this.$emit('input', false);
|
||||
this.$emit("input", false);
|
||||
this.editorRefresh();
|
||||
},
|
||||
...mapMutations(["editorRefresh"])
|
||||
}
|
||||
...mapMutations(["editorRefresh"]),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -1,49 +1,54 @@
|
||||
<template>
|
||||
<el-dialog title="提示" class="reset__dialog" :visible="showResetConfirm" @close="$emit('close')">
|
||||
<el-dialog
|
||||
title="提示"
|
||||
class="reset__dialog"
|
||||
:visible="showResetConfirm"
|
||||
@close="$emit('close')"
|
||||
>
|
||||
<div class="text">
|
||||
此操作将丢失本地缓存的文本和自定义样式,是否继续?
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :type="btnType" plain @click="$emit('close')">取 消</el-button>
|
||||
<el-button :type="btnType" @click="$emit('confirm')" plain>确 定</el-button>
|
||||
<el-button :type="btnType" plain @click="$emit('close')"
|
||||
>取 消</el-button
|
||||
>
|
||||
<el-button :type="btnType" @click="$emit('confirm')" plain
|
||||
>确 定</el-button
|
||||
>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex';
|
||||
export default {
|
||||
props: {
|
||||
showResetConfirm: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
import { mapState } from "vuex";
|
||||
export default {
|
||||
props: {
|
||||
showResetConfirm: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
computed: {
|
||||
btnType() {
|
||||
return this.nightMode ? 'default' : 'primary';
|
||||
},
|
||||
...mapState({
|
||||
nightMode: state => state.nightMode
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
btnType() {
|
||||
return this.nightMode ? "default" : "primary";
|
||||
},
|
||||
...mapState({
|
||||
nightMode: (state) => state.nightMode,
|
||||
}),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.reset__dialog {
|
||||
text-align: center;
|
||||
}
|
||||
.reset__dialog {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: center;
|
||||
}
|
||||
.text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,62 +1,70 @@
|
||||
<template>
|
||||
<ul v-show="value" id="menu" class="menu" :style="`left: ${left}px;top: ${top}px;`">
|
||||
<li v-for="item of list" :key="item.key" class="menu_item" @mousedown="onMouseDown(item.key)">
|
||||
<span>{{item.text}}</span>
|
||||
<ul
|
||||
v-show="value"
|
||||
id="menu"
|
||||
class="menu"
|
||||
:style="`left: ${left}px;top: ${top}px;`"
|
||||
>
|
||||
<li
|
||||
v-for="item of list"
|
||||
:key="item.key"
|
||||
class="menu_item"
|
||||
@mousedown="onMouseDown(item.key)"
|
||||
>
|
||||
<span>{{ item.text }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
uploadImgFile,
|
||||
} from '../../assets/scripts/uploadImageFile';
|
||||
import { uploadImgFile } from "../../assets/scripts/uploadImageFile";
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
top: {
|
||||
type: Number,
|
||||
default: 0
|
||||
default: 0,
|
||||
},
|
||||
left: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [
|
||||
{
|
||||
text: '上传图片',
|
||||
key: 'insertPic'
|
||||
text: "上传图片",
|
||||
key: "insertPic",
|
||||
},
|
||||
{
|
||||
text: '插入表格',
|
||||
key: 'insertTable'
|
||||
text: "插入表格",
|
||||
key: "insertTable",
|
||||
},
|
||||
{
|
||||
text: '页面重置',
|
||||
key: 'pageReset'
|
||||
text: "页面重置",
|
||||
key: "pageReset",
|
||||
},
|
||||
{
|
||||
text: '下载MD文档',
|
||||
key: 'downLoad'
|
||||
}
|
||||
]
|
||||
}
|
||||
text: "下载MD文档",
|
||||
key: "downLoad",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
closeCB() {
|
||||
this.$emit('input', false);
|
||||
this.$emit("input", false);
|
||||
},
|
||||
onMouseDown(key) {
|
||||
this.$emit("menuTick", key);
|
||||
this.$emit("closeMenu", false);
|
||||
},
|
||||
onMouseDown(key){
|
||||
this.$emit('menuTick', key)
|
||||
this.$emit('closeMenu', false)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@ -83,7 +91,8 @@ export default {
|
||||
color: white;
|
||||
background: rgb(139, 146, 148);
|
||||
}
|
||||
span,.btn-upload {
|
||||
span,
|
||||
.btn-upload {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
padding: 4px 0;
|
||||
@ -91,7 +100,7 @@ export default {
|
||||
}
|
||||
.btn-upload {
|
||||
margin: 0;
|
||||
border:none;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
}
|
||||
@ -104,7 +113,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
li:hover {
|
||||
background-color: #1790ff;
|
||||
color: white;
|
||||
@ -114,5 +122,4 @@ li {
|
||||
font-size: 15px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,323 +1,452 @@
|
||||
<template>
|
||||
<el-dialog title="本地上传" class="upload__dialog" :visible="value" @close="$emit('close')">
|
||||
<el-tabs type="card" :value="'upload'">
|
||||
<el-tab-pane class="upload-panel" label="选择上传" name="upload">
|
||||
<el-select v-model="imgHost" @change="changeImgHost" placeholder="请选择" size="small">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-upload drag action :headers="{'Content-Type': 'multipart/form-data'}" :show-file-list="false"
|
||||
:multiple="true" accept=".jpg, .jpeg, .png, .gif" name="file" :before-upload="beforeUpload"
|
||||
v-loading="uploadingImg">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">
|
||||
将图片拖到此处,或
|
||||
<em>点击上传</em>
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="GitHub 图床" name="github">
|
||||
<el-form class="setting-form" ref="form" :model="formGitHub" label-position="right" label-width="140px">
|
||||
<el-form-item label="GitHub 仓库" :required="true">
|
||||
<el-input v-model.trim="formGitHub.repo" placeholder="如:github.com/yanglbme/resource"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="分支">
|
||||
<el-input v-model.trim="formGitHub.branch" placeholder="如:release,可不填,默认 master"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Token" :required="true">
|
||||
<el-input v-model.trim="formGitHub.accessToken" show-password
|
||||
placeholder="如:cc1d0c1426d0fd0902bd2d7184b14da61b8abc46"></el-input>
|
||||
<el-link type="primary"
|
||||
href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token"
|
||||
target="_blank">如何获取 GitHub Token?</el-link>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="saveGitHubConfiguration">保存配置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="阿里云 OSS" name="aliOSS">
|
||||
<el-form class="setting-form" ref="form" :model="formAliOSS" label-position="right" label-width="140px">
|
||||
<el-form-item label="AccessKey ID" :required="true">
|
||||
<el-input v-model.trim="formAliOSS.accessKeyId" placeholder="如:LTAI4GdoocsmdoxUf13ylbaNHk"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="AccessKey Secret" :required="true">
|
||||
<el-input v-model.trim="formAliOSS.accessKeySecret" show-password
|
||||
placeholder="如:cc1d0c142doocs0902bd2d7md4b14da6ylbabc46"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket" :required="true">
|
||||
<el-input v-model.trim="formAliOSS.bucket"
|
||||
placeholder="如:doocs"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket 所在区域" :required="true">
|
||||
<el-input v-model.trim="formAliOSS.region"
|
||||
placeholder="如:oss-cn-shenzhen"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义 CDN 域名" :required="false">
|
||||
<el-input v-model.trim="formAliOSS.cdnHost"
|
||||
placeholder="如:https://imagecdn.alidaodao.com,可不填"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="存储路径">
|
||||
<el-input v-model.trim="formAliOSS.path"
|
||||
placeholder="如:img,可不填,默认为根目录"></el-input>
|
||||
<el-link type="primary"
|
||||
href="https://help.aliyun.com/document_detail/31883.html"
|
||||
target="_blank">如何使用阿里云 OSS?</el-link>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="saveAliOSSConfiguration">保存配置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="腾讯云 COS" name="txCOS">
|
||||
<el-form class="setting-form" ref="form" :model="formTxCOS" label-position="right" label-width="140px">
|
||||
<el-form-item label="SecretId" :required="true">
|
||||
<el-input v-model.trim="formTxCOS.secretId" placeholder="如:AKIDnQp1w3DOOCSs8F5MDp9tdoocsmdUPonW3"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="SecretKey" :required="true">
|
||||
<el-input v-model.trim="formTxCOS.secretKey" show-password
|
||||
placeholder="如:ukLmdtEJ9271f3DOocsMDsCXdS3YlbW0"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket" :required="true">
|
||||
<el-input v-model.trim="formTxCOS.bucket"
|
||||
placeholder="如:doocs-3212520134"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket 所在区域" :required="true">
|
||||
<el-input v-model.trim="formTxCOS.region"
|
||||
placeholder="如:ap-guangzhou"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义 CDN 域名" :required="false">
|
||||
<el-input v-model.trim="formTxCOS.cdnHost"
|
||||
placeholder="如:https://imagecdn.alidaodao.com,可不填"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="存储路径">
|
||||
<el-input v-model.trim="formTxCOS.path"
|
||||
placeholder="如:img,可不填,默认根目录"></el-input>
|
||||
<el-link type="primary"
|
||||
href="https://cloud.tencent.com/document/product/436/38484"
|
||||
target="_blank">如何使用腾讯云 COS?</el-link>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="saveTxCOSConfiguration">保存配置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
uploadImgFile
|
||||
} from "../../assets/scripts/uploadImageFile";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formGitHub: {
|
||||
repo: "",
|
||||
branch: "",
|
||||
accessToken: "",
|
||||
},
|
||||
formAliOSS: {
|
||||
accessKeyId: "",
|
||||
accessKeySecret: "",
|
||||
bucket: "",
|
||||
region: "",
|
||||
path: "",
|
||||
cdnHost: "",
|
||||
},
|
||||
formTxCOS: {
|
||||
secretId: "",
|
||||
secretKey: "",
|
||||
bucket: "",
|
||||
region: "",
|
||||
path: "",
|
||||
cdnHost: "",
|
||||
},
|
||||
options: [{
|
||||
value: "default",
|
||||
label: "默认图床",
|
||||
},
|
||||
{
|
||||
value: "github",
|
||||
label: "GitHub",
|
||||
},
|
||||
{
|
||||
value: "aliOSS",
|
||||
label: "阿里云"
|
||||
},
|
||||
{
|
||||
value: "txCOS",
|
||||
label: "腾讯云"
|
||||
}
|
||||
],
|
||||
imgHost: "default",
|
||||
uploadingImg: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (localStorage.getItem("githubConfig")) {
|
||||
this.formGitHub = JSON.parse(localStorage.getItem("githubConfig"));
|
||||
}
|
||||
if (localStorage.getItem("aliOSSConfig")) {
|
||||
this.formAliOSS = JSON.parse(localStorage.getItem("aliOSSConfig"));
|
||||
}
|
||||
if (localStorage.getItem("txCOSConfig")) {
|
||||
this.formTxCOS = JSON.parse(localStorage.getItem("txCOSConfig"));
|
||||
}
|
||||
if (localStorage.getItem("imgHost")) {
|
||||
this.imgHost = localStorage.getItem("imgHost");
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeImgHost() {
|
||||
localStorage.setItem("imgHost", this.imgHost);
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '已成功切换图床',
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
saveGitHubConfiguration() {
|
||||
if (!(this.formGitHub.repo && this.formGitHub.accessToken)) {
|
||||
const blankElement = this.formGitHub.repo ? "token" : "GitHub 仓库"
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `参数「${blankElement}」不能为空`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("githubConfig", JSON.stringify(this.formGitHub));
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
saveAliOSSConfiguration() {
|
||||
if (!(this.formAliOSS.accessKeyId && this.formAliOSS.accessKeySecret && this.formAliOSS.bucket && this.formAliOSS.region)) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `阿里云 OSS 参数配置不全`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("aliOSSConfig", JSON.stringify(this.formAliOSS));
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
|
||||
saveTxCOSConfiguration() {
|
||||
if (!(this.formTxCOS.secretId && this.formTxCOS.secretKey && this.formTxCOS.bucket && this.formTxCOS.region)) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `腾讯云 COS 参数配置不全`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("txCOSConfig", JSON.stringify(this.formTxCOS));
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
|
||||
// 图片上传前的处理
|
||||
beforeUpload(file) {
|
||||
if (!this.validateConfig()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.uploadingImg = true;
|
||||
uploadImgFile(file)
|
||||
.then(res => {
|
||||
this.$emit("uploaded", res);
|
||||
this.uploadingImg = false;
|
||||
})
|
||||
.catch(err => {
|
||||
this.uploadingImg = false;
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: err,
|
||||
type: "error",
|
||||
});
|
||||
});
|
||||
return false;
|
||||
},
|
||||
validateConfig() {
|
||||
let checkRes = true, errMessage = '';
|
||||
|
||||
switch (localStorage.getItem('imgHost')) {
|
||||
case 'github':
|
||||
checkRes = this.formGitHub.repo && this.formGitHub.accessToken;
|
||||
errMessage = checkRes ? '' : '请先配置 GitHub 图床参数';
|
||||
break;
|
||||
case 'aliOSS':
|
||||
checkRes = this.formAliOSS.accessKeyId && this.formAliOSS.accessKeySecret && this.formAliOSS.bucket && this.formAliOSS.region;
|
||||
errMessage = checkRes ? '' : '请先配置阿里云 OSS 参数';
|
||||
break;
|
||||
case 'txCOS':
|
||||
checkRes = this.formTxCOS.secretId && this.formTxCOS.secretKey && this.formTxCOS.bucket && this.formTxCOS.region;
|
||||
errMessage = checkRes ? '' : '请先配置腾讯云 COS 参数';
|
||||
break;
|
||||
}
|
||||
errMessage && this.$message.error(errMessage);
|
||||
return checkRes;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
/deep/ .el-dialog {
|
||||
width: 40%;
|
||||
}
|
||||
/deep/ .el-upload-dragger {
|
||||
width: 335px;
|
||||
}
|
||||
/deep/ .el-dialog__body {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.upload-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
.el-select {
|
||||
align-self: flex-end;
|
||||
margin: 0 67.75px 20px;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.github-panel {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.setting-form {
|
||||
width: 100%;
|
||||
|
||||
.el-form-item {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.el-form-item:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<template>
|
||||
<el-dialog
|
||||
title="本地上传"
|
||||
class="upload__dialog"
|
||||
:visible="value"
|
||||
@close="$emit('close')"
|
||||
>
|
||||
<el-tabs type="card" :value="'upload'">
|
||||
<el-tab-pane class="upload-panel" label="选择上传" name="upload">
|
||||
<el-select
|
||||
v-model="imgHost"
|
||||
@change="changeImgHost"
|
||||
placeholder="请选择"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-upload
|
||||
drag
|
||||
action
|
||||
:headers="{ 'Content-Type': 'multipart/form-data' }"
|
||||
:show-file-list="false"
|
||||
:multiple="true"
|
||||
accept=".jpg, .jpeg, .png, .gif"
|
||||
name="file"
|
||||
:before-upload="beforeUpload"
|
||||
v-loading="uploadingImg"
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">
|
||||
将图片拖到此处,或
|
||||
<em>点击上传</em>
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="GitHub 图床" name="github">
|
||||
<el-form
|
||||
class="setting-form"
|
||||
ref="form"
|
||||
:model="formGitHub"
|
||||
label-position="right"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-form-item label="GitHub 仓库" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formGitHub.repo"
|
||||
placeholder="如:github.com/yanglbme/resource"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="分支">
|
||||
<el-input
|
||||
v-model.trim="formGitHub.branch"
|
||||
placeholder="如:release,可不填,默认 master"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Token" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formGitHub.accessToken"
|
||||
show-password
|
||||
placeholder="如:cc1d0c1426d0fd0902bd2d7184b14da61b8abc46"
|
||||
></el-input>
|
||||
<el-link
|
||||
type="primary"
|
||||
href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token"
|
||||
target="_blank"
|
||||
>如何获取 GitHub Token?</el-link
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="saveGitHubConfiguration"
|
||||
>保存配置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="阿里云 OSS" name="aliOSS">
|
||||
<el-form
|
||||
class="setting-form"
|
||||
ref="form"
|
||||
:model="formAliOSS"
|
||||
label-position="right"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-form-item label="AccessKey ID" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formAliOSS.accessKeyId"
|
||||
placeholder="如:LTAI4GdoocsmdoxUf13ylbaNHk"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="AccessKey Secret" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formAliOSS.accessKeySecret"
|
||||
show-password
|
||||
placeholder="如:cc1d0c142doocs0902bd2d7md4b14da6ylbabc46"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formAliOSS.bucket"
|
||||
placeholder="如:doocs"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket 所在区域" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formAliOSS.region"
|
||||
placeholder="如:oss-cn-shenzhen"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义 CDN 域名" :required="false">
|
||||
<el-input
|
||||
v-model.trim="formAliOSS.cdnHost"
|
||||
placeholder="如:https://imagecdn.alidaodao.com,可不填"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="存储路径">
|
||||
<el-input
|
||||
v-model.trim="formAliOSS.path"
|
||||
placeholder="如:img,可不填,默认为根目录"
|
||||
></el-input>
|
||||
<el-link
|
||||
type="primary"
|
||||
href="https://help.aliyun.com/document_detail/31883.html"
|
||||
target="_blank"
|
||||
>如何使用阿里云 OSS?</el-link
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="saveAliOSSConfiguration"
|
||||
>保存配置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="腾讯云 COS" name="txCOS">
|
||||
<el-form
|
||||
class="setting-form"
|
||||
ref="form"
|
||||
:model="formTxCOS"
|
||||
label-position="right"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-form-item label="SecretId" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formTxCOS.secretId"
|
||||
placeholder="如:AKIDnQp1w3DOOCSs8F5MDp9tdoocsmdUPonW3"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="SecretKey" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formTxCOS.secretKey"
|
||||
show-password
|
||||
placeholder="如:ukLmdtEJ9271f3DOocsMDsCXdS3YlbW0"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formTxCOS.bucket"
|
||||
placeholder="如:doocs-3212520134"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket 所在区域" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formTxCOS.region"
|
||||
placeholder="如:ap-guangzhou"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义 CDN 域名" :required="false">
|
||||
<el-input
|
||||
v-model.trim="formTxCOS.cdnHost"
|
||||
placeholder="如:https://imagecdn.alidaodao.com,可不填"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="存储路径">
|
||||
<el-input
|
||||
v-model.trim="formTxCOS.path"
|
||||
placeholder="如:img,可不填,默认根目录"
|
||||
></el-input>
|
||||
<el-link
|
||||
type="primary"
|
||||
href="https://cloud.tencent.com/document/product/436/38484"
|
||||
target="_blank"
|
||||
>如何使用腾讯云 COS?</el-link
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="saveTxCOSConfiguration"
|
||||
>保存配置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadImgFile } from "../../assets/scripts/uploadImageFile";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formGitHub: {
|
||||
repo: "",
|
||||
branch: "",
|
||||
accessToken: "",
|
||||
},
|
||||
formAliOSS: {
|
||||
accessKeyId: "",
|
||||
accessKeySecret: "",
|
||||
bucket: "",
|
||||
region: "",
|
||||
path: "",
|
||||
cdnHost: "",
|
||||
},
|
||||
formTxCOS: {
|
||||
secretId: "",
|
||||
secretKey: "",
|
||||
bucket: "",
|
||||
region: "",
|
||||
path: "",
|
||||
cdnHost: "",
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: "default",
|
||||
label: "默认图床",
|
||||
},
|
||||
{
|
||||
value: "github",
|
||||
label: "GitHub",
|
||||
},
|
||||
{
|
||||
value: "aliOSS",
|
||||
label: "阿里云",
|
||||
},
|
||||
{
|
||||
value: "txCOS",
|
||||
label: "腾讯云",
|
||||
},
|
||||
],
|
||||
imgHost: "default",
|
||||
uploadingImg: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (localStorage.getItem("githubConfig")) {
|
||||
this.formGitHub = JSON.parse(localStorage.getItem("githubConfig"));
|
||||
}
|
||||
if (localStorage.getItem("aliOSSConfig")) {
|
||||
this.formAliOSS = JSON.parse(localStorage.getItem("aliOSSConfig"));
|
||||
}
|
||||
if (localStorage.getItem("txCOSConfig")) {
|
||||
this.formTxCOS = JSON.parse(localStorage.getItem("txCOSConfig"));
|
||||
}
|
||||
if (localStorage.getItem("imgHost")) {
|
||||
this.imgHost = localStorage.getItem("imgHost");
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeImgHost() {
|
||||
localStorage.setItem("imgHost", this.imgHost);
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "已成功切换图床",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
saveGitHubConfiguration() {
|
||||
if (!(this.formGitHub.repo && this.formGitHub.accessToken)) {
|
||||
const blankElement = this.formGitHub.repo
|
||||
? "token"
|
||||
: "GitHub 仓库";
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `参数「${blankElement}」不能为空`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem(
|
||||
"githubConfig",
|
||||
JSON.stringify(this.formGitHub)
|
||||
);
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
saveAliOSSConfiguration() {
|
||||
if (
|
||||
!(
|
||||
this.formAliOSS.accessKeyId &&
|
||||
this.formAliOSS.accessKeySecret &&
|
||||
this.formAliOSS.bucket &&
|
||||
this.formAliOSS.region
|
||||
)
|
||||
) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `阿里云 OSS 参数配置不全`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem(
|
||||
"aliOSSConfig",
|
||||
JSON.stringify(this.formAliOSS)
|
||||
);
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
|
||||
saveTxCOSConfiguration() {
|
||||
if (
|
||||
!(
|
||||
this.formTxCOS.secretId &&
|
||||
this.formTxCOS.secretKey &&
|
||||
this.formTxCOS.bucket &&
|
||||
this.formTxCOS.region
|
||||
)
|
||||
) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `腾讯云 COS 参数配置不全`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("txCOSConfig", JSON.stringify(this.formTxCOS));
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
|
||||
// 图片上传前的处理
|
||||
beforeUpload(file) {
|
||||
if (!this.validateConfig()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.uploadingImg = true;
|
||||
uploadImgFile(file)
|
||||
.then((res) => {
|
||||
this.$emit("uploaded", res);
|
||||
this.uploadingImg = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.uploadingImg = false;
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: err,
|
||||
type: "error",
|
||||
});
|
||||
});
|
||||
return false;
|
||||
},
|
||||
validateConfig() {
|
||||
let checkRes = true,
|
||||
errMessage = "";
|
||||
|
||||
switch (localStorage.getItem("imgHost")) {
|
||||
case "github":
|
||||
checkRes =
|
||||
this.formGitHub.repo && this.formGitHub.accessToken;
|
||||
errMessage = checkRes ? "" : "请先配置 GitHub 图床参数";
|
||||
break;
|
||||
case "aliOSS":
|
||||
checkRes =
|
||||
this.formAliOSS.accessKeyId &&
|
||||
this.formAliOSS.accessKeySecret &&
|
||||
this.formAliOSS.bucket &&
|
||||
this.formAliOSS.region;
|
||||
errMessage = checkRes ? "" : "请先配置阿里云 OSS 参数";
|
||||
break;
|
||||
case "txCOS":
|
||||
checkRes =
|
||||
this.formTxCOS.secretId &&
|
||||
this.formTxCOS.secretKey &&
|
||||
this.formTxCOS.bucket &&
|
||||
this.formTxCOS.region;
|
||||
errMessage = checkRes ? "" : "请先配置腾讯云 COS 参数";
|
||||
break;
|
||||
}
|
||||
errMessage && this.$message.error(errMessage);
|
||||
return checkRes;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
/deep/ .el-dialog {
|
||||
width: 40%;
|
||||
}
|
||||
/deep/ .el-upload-dragger {
|
||||
width: 335px;
|
||||
}
|
||||
/deep/ .el-dialog__body {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.upload-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
.el-select {
|
||||
align-self: flex-end;
|
||||
margin: 0 67.75px 20px;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.github-panel {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.setting-form {
|
||||
width: 100%;
|
||||
|
||||
.el-form-item {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.el-form-item:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -7,8 +7,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
<script></script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.loading-wrapper {
|
||||
@ -42,7 +41,7 @@
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: url('../assets/images/favicon.png') no-repeat;
|
||||
background: url("../assets/images/favicon.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="container" :class="{'container_night': nightMode}">
|
||||
<div class="container" :class="{ container_night: nightMode }">
|
||||
<el-container>
|
||||
<el-header class="editor__header">
|
||||
<editor-header
|
||||
@ -11,40 +11,72 @@
|
||||
@showAboutDialog="aboutDialogVisible = true"
|
||||
@showDialogForm="dialogFormVisible = true"
|
||||
@showDialogUploadImg="dialogUploadImgVisible = true"
|
||||
@startCopy="isCoping = true, backLight = true"
|
||||
@startCopy="(isCoping = true), (backLight = true)"
|
||||
@endCopy="endCopy"
|
||||
/>
|
||||
</el-header>
|
||||
<el-main class="main-body">
|
||||
<el-row class="main-section">
|
||||
<el-col :span="12" @contextmenu.prevent.native="openMenu($event)">
|
||||
<textarea id="editor" type="textarea" placeholder="Your markdown text here." v-model="source">
|
||||
<el-col
|
||||
:span="12"
|
||||
@contextmenu.prevent.native="openMenu($event)"
|
||||
>
|
||||
<textarea
|
||||
id="editor"
|
||||
type="textarea"
|
||||
placeholder="Your markdown text here."
|
||||
v-model="source"
|
||||
>
|
||||
</textarea>
|
||||
</el-col>
|
||||
<el-col :span="12" class="preview-wrapper" id="preview" ref="preview" :class="{'preview-wrapper_night': nightMode && isCoping}">
|
||||
<section id="output-wrapper" :class="{'output_night': nightMode && !backLight}">
|
||||
<el-col
|
||||
:span="12"
|
||||
class="preview-wrapper"
|
||||
id="preview"
|
||||
ref="preview"
|
||||
:class="{
|
||||
'preview-wrapper_night': nightMode && isCoping,
|
||||
}"
|
||||
>
|
||||
<section
|
||||
id="output-wrapper"
|
||||
:class="{ output_night: nightMode && !backLight }"
|
||||
>
|
||||
<div class="preview">
|
||||
<section id="output" v-html="output">
|
||||
</section>
|
||||
<div class="loading-mask" v-if="nightMode && isCoping">
|
||||
<section id="output" v-html="output"></section>
|
||||
<div
|
||||
class="loading-mask"
|
||||
v-if="nightMode && isCoping"
|
||||
>
|
||||
<div class="loading__img"></div>
|
||||
<span>正在生成</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</el-col>
|
||||
<transition name="custom-classes-transition" enter-active-class="bounceInRight">
|
||||
<transition
|
||||
name="custom-classes-transition"
|
||||
enter-active-class="bounceInRight"
|
||||
>
|
||||
<el-col id="cssBox" :span="12" v-show="showCssEditor">
|
||||
<textarea id="cssEditor" type="textarea" placeholder="Your custom css here.">
|
||||
</textarea>
|
||||
<textarea
|
||||
id="cssEditor"
|
||||
type="textarea"
|
||||
placeholder="Your custom css here."
|
||||
>
|
||||
</textarea>
|
||||
</el-col>
|
||||
</transition>
|
||||
</el-row>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<upload-img-dialog v-model="dialogUploadImgVisible" @close="dialogUploadImgVisible = false" @uploaded="uploaded" />
|
||||
<about-dialog v-model="aboutDialogVisible"/>
|
||||
<insert-form-dialog v-model="dialogFormVisible"/>
|
||||
<upload-img-dialog
|
||||
v-model="dialogUploadImgVisible"
|
||||
@close="dialogUploadImgVisible = false"
|
||||
@uploaded="uploaded"
|
||||
/>
|
||||
<about-dialog v-model="aboutDialogVisible" />
|
||||
<insert-form-dialog v-model="dialogFormVisible" />
|
||||
<right-click-menu
|
||||
v-model="rightClickMenuVisible"
|
||||
:left="mouseLeft"
|
||||
@ -55,23 +87,23 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import editorHeader from '../components/CodemirrorEditor/header';
|
||||
import aboutDialog from '../components/CodemirrorEditor/aboutDialog';
|
||||
import insertFormDialog from '../components/CodemirrorEditor/insertForm';
|
||||
import rightClickMenu from '../components/CodemirrorEditor/rightClickMenu';
|
||||
import uploadImgDialog from '../components/CodemirrorEditor/uploadImgDialog';
|
||||
import editorHeader from "../components/CodemirrorEditor/header";
|
||||
import aboutDialog from "../components/CodemirrorEditor/aboutDialog";
|
||||
import insertFormDialog from "../components/CodemirrorEditor/insertForm";
|
||||
import rightClickMenu from "../components/CodemirrorEditor/rightClickMenu";
|
||||
import uploadImgDialog from "../components/CodemirrorEditor/uploadImgDialog";
|
||||
|
||||
import {
|
||||
css2json,
|
||||
downLoadMD,
|
||||
setFontSize,
|
||||
saveEditorContent,
|
||||
customCssWithTemplate
|
||||
} from '../assets/scripts/util'
|
||||
import {uploadImgFile} from '../assets/scripts/uploadImageFile';
|
||||
customCssWithTemplate,
|
||||
} from "../assets/scripts/util";
|
||||
import { uploadImgFile } from "../assets/scripts/uploadImageFile";
|
||||
|
||||
require('codemirror/mode/javascript/javascript')
|
||||
import {mapState, mapMutations} from 'vuex';
|
||||
require("codemirror/mode/javascript/javascript");
|
||||
import { mapState, mapMutations } from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -84,29 +116,29 @@ export default {
|
||||
backLight: false,
|
||||
timeout: null,
|
||||
changeTimer: null,
|
||||
source: '',
|
||||
source: "",
|
||||
mouseLeft: 0,
|
||||
mouseTop: 0
|
||||
}
|
||||
mouseTop: 0,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
editorHeader,
|
||||
aboutDialog,
|
||||
insertFormDialog,
|
||||
rightClickMenu,
|
||||
uploadImgDialog
|
||||
uploadImgDialog,
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
wxRenderer: state => state.wxRenderer,
|
||||
output: state => state.output,
|
||||
editor: state => state.editor,
|
||||
cssEditor: state => state.cssEditor,
|
||||
currentSize: state => state.currentSize,
|
||||
currentColor: state => state.currentColor,
|
||||
nightMode: state => state.nightMode,
|
||||
rightClickMenuVisible: state => state.rightClickMenuVisible
|
||||
})
|
||||
wxRenderer: (state) => state.wxRenderer,
|
||||
output: (state) => state.output,
|
||||
editor: (state) => state.editor,
|
||||
cssEditor: (state) => state.cssEditor,
|
||||
currentSize: (state) => state.currentSize,
|
||||
currentColor: (state) => state.currentColor,
|
||||
nightMode: (state) => state.nightMode,
|
||||
rightClickMenuVisible: (state) => state.rightClickMenuVisible,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.initEditorState();
|
||||
@ -119,82 +151,94 @@ export default {
|
||||
methods: {
|
||||
initEditor() {
|
||||
this.initEditorEntity();
|
||||
this.editor.on('change', (cm, e) => {
|
||||
this.editor.on("change", (cm, e) => {
|
||||
if (this.changeTimer) clearTimeout(this.changeTimer);
|
||||
this.changeTimer = setTimeout(() => {
|
||||
this.onEditorRefresh();
|
||||
saveEditorContent(this.editor, '__editor_content');
|
||||
saveEditorContent(this.editor, "__editor_content");
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// 粘贴上传图片并插入
|
||||
this.editor.on('paste', (cm, e) => {
|
||||
if (!(e.clipboardData && e.clipboardData.items) || this.isImgLoading) {
|
||||
this.editor.on("paste", (cm, e) => {
|
||||
if (
|
||||
!(e.clipboardData && e.clipboardData.items) ||
|
||||
this.isImgLoading
|
||||
) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0, len = e.clipboardData.items.length; i < len; ++i) {
|
||||
for (
|
||||
let i = 0, len = e.clipboardData.items.length;
|
||||
i < len;
|
||||
++i
|
||||
) {
|
||||
let item = e.clipboardData.items[i];
|
||||
|
||||
if (item.kind === 'file') {
|
||||
if (item.kind === "file") {
|
||||
// 校验图床参数
|
||||
const imgHost = localStorage.getItem('imgHost') || 'default';
|
||||
if (imgHost != 'default' && !localStorage.getItem(`${imgHost}Config`)) {
|
||||
const imgHost =
|
||||
localStorage.getItem("imgHost") || "default";
|
||||
if (
|
||||
imgHost != "default" &&
|
||||
!localStorage.getItem(`${imgHost}Config`)
|
||||
) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '请先配置好图床参数',
|
||||
type: 'error'
|
||||
message: "请先配置好图床参数",
|
||||
type: "error",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
this.isImgLoading = true;
|
||||
const pasteFile = item.getAsFile()
|
||||
uploadImgFile(pasteFile).then(res => {
|
||||
this.uploaded(res)
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: err,
|
||||
type: 'error'
|
||||
const pasteFile = item.getAsFile();
|
||||
uploadImgFile(pasteFile)
|
||||
.then((res) => {
|
||||
this.uploaded(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: err,
|
||||
type: "error",
|
||||
});
|
||||
});
|
||||
});
|
||||
this.isImgLoading = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.editor.on('mousedown', () => {
|
||||
this.$store.commit('setRightClickMenuVisible', false);
|
||||
this.editor.on("mousedown", () => {
|
||||
this.$store.commit("setRightClickMenuVisible", false);
|
||||
});
|
||||
this.editor.on('blur', () => {
|
||||
this.editor.on("blur", () => {
|
||||
//!影响到右键菜单的点击事件,右键菜单的点击事件在组件内通过mousedown触发
|
||||
this.$store.commit('setRightClickMenuVisible', false);
|
||||
this.$store.commit("setRightClickMenuVisible", false);
|
||||
});
|
||||
this.editor.on('scroll', () => {
|
||||
this.$store.commit('setRightClickMenuVisible', false);
|
||||
this.editor.on("scroll", () => {
|
||||
this.$store.commit("setRightClickMenuVisible", false);
|
||||
});
|
||||
|
||||
},
|
||||
initCssEditor() {
|
||||
this.initCssEditorEntity();
|
||||
// 自动提示
|
||||
this.cssEditor.on('keyup', (cm, e) => {
|
||||
this.cssEditor.on("keyup", (cm, e) => {
|
||||
if ((e.keyCode >= 65 && e.keyCode <= 90) || e.keyCode === 189) {
|
||||
cm.showHint(e);
|
||||
}
|
||||
});
|
||||
this.cssEditor.on('update', (instance) => {
|
||||
this.cssEditor.on("update", (instance) => {
|
||||
this.cssChanged();
|
||||
saveEditorContent(this.cssEditor, '__css_content');
|
||||
})
|
||||
saveEditorContent(this.cssEditor, "__css_content");
|
||||
});
|
||||
},
|
||||
cssChanged() {
|
||||
let json = css2json(this.cssEditor.getValue(0));
|
||||
let theme = setFontSize(this.currentSize.replace('px', ''));
|
||||
let theme = setFontSize(this.currentSize.replace("px", ""));
|
||||
|
||||
theme = customCssWithTemplate(json, this.currentColor, theme);
|
||||
this.setWxRendererOptions({
|
||||
theme: theme
|
||||
theme: theme,
|
||||
});
|
||||
this.onEditorRefresh();
|
||||
},
|
||||
@ -203,8 +247,8 @@ export default {
|
||||
if (!response) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '上传图片未知异常',
|
||||
type: 'error'
|
||||
message: "上传图片未知异常",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -217,47 +261,66 @@ export default {
|
||||
this.editor.replaceSelection(`\n${markdownImage}\n`, cursor);
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '图片上传成功',
|
||||
type: 'success'
|
||||
message: "图片上传成功",
|
||||
type: "success",
|
||||
});
|
||||
this.onEditorRefresh();
|
||||
},
|
||||
// 左右滚动
|
||||
leftAndRightScroll() {
|
||||
const scrollCB = text => {
|
||||
const scrollCB = (text) => {
|
||||
let source, target;
|
||||
|
||||
clearTimeout(this.timeout);
|
||||
if (text === 'preview') {
|
||||
if (text === "preview") {
|
||||
source = this.$refs.preview.$el;
|
||||
target = document.getElementsByClassName('CodeMirror-scroll')[0];
|
||||
this.editor.off('scroll', editorScrollCB);
|
||||
target = document.getElementsByClassName(
|
||||
"CodeMirror-scroll"
|
||||
)[0];
|
||||
this.editor.off("scroll", editorScrollCB);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.editor.on('scroll', editorScrollCB);
|
||||
this.editor.on("scroll", editorScrollCB);
|
||||
}, 300);
|
||||
} else if (text === 'editor') {
|
||||
source = document.getElementsByClassName('CodeMirror-scroll')[0];
|
||||
} else if (text === "editor") {
|
||||
source = document.getElementsByClassName(
|
||||
"CodeMirror-scroll"
|
||||
)[0];
|
||||
target = this.$refs.preview.$el;
|
||||
target.removeEventListener("scroll", previewScrollCB, false);
|
||||
target.removeEventListener(
|
||||
"scroll",
|
||||
previewScrollCB,
|
||||
false
|
||||
);
|
||||
this.timeout = setTimeout(() => {
|
||||
target.addEventListener("scroll", previewScrollCB, false);
|
||||
target.addEventListener(
|
||||
"scroll",
|
||||
previewScrollCB,
|
||||
false
|
||||
);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
let percentage = source.scrollTop / (source.scrollHeight - source.offsetHeight);
|
||||
let height = percentage * (target.scrollHeight - target.offsetHeight);
|
||||
let percentage =
|
||||
source.scrollTop /
|
||||
(source.scrollHeight - source.offsetHeight);
|
||||
let height =
|
||||
percentage * (target.scrollHeight - target.offsetHeight);
|
||||
|
||||
target.scrollTo(0, height);
|
||||
};
|
||||
const editorScrollCB = () => {
|
||||
scrollCB('editor');
|
||||
scrollCB("editor");
|
||||
};
|
||||
const previewScrollCB = () => {
|
||||
scrollCB('preview');
|
||||
scrollCB("preview");
|
||||
};
|
||||
|
||||
this.$refs.preview.$el.addEventListener("scroll", previewScrollCB, false);
|
||||
this.editor.on('scroll', editorScrollCB);
|
||||
this.$refs.preview.$el.addEventListener(
|
||||
"scroll",
|
||||
previewScrollCB,
|
||||
false
|
||||
);
|
||||
this.editor.on("scroll", editorScrollCB);
|
||||
},
|
||||
// 更新编辑器
|
||||
onEditorRefresh() {
|
||||
@ -284,43 +347,43 @@ export default {
|
||||
const left = e.clientX - offsetLeft;
|
||||
this.mouseLeft = Math.min(maxLeft, left);
|
||||
this.mouseTop = e.clientY + 10;
|
||||
this.$store.commit('setRightClickMenuVisible', true);
|
||||
this.$store.commit("setRightClickMenuVisible", true);
|
||||
},
|
||||
closeRightClickMenu(){
|
||||
this.$store.commit('setRightClickMenuVisible', false);
|
||||
closeRightClickMenu() {
|
||||
this.$store.commit("setRightClickMenuVisible", false);
|
||||
},
|
||||
onMenuEvent(type, info = {}) {
|
||||
switch (type) {
|
||||
case 'pageReset':
|
||||
case "pageReset":
|
||||
this.$refs.header.showResetConfirm = true;
|
||||
break;
|
||||
case 'insertPic':
|
||||
this.dialogUploadImgVisible = true
|
||||
case "insertPic":
|
||||
this.dialogUploadImgVisible = true;
|
||||
break;
|
||||
case 'downLoad':
|
||||
case "downLoad":
|
||||
this.downloadEditorContent();
|
||||
break;
|
||||
case 'insertTable':
|
||||
case "insertTable":
|
||||
this.dialogFormVisible = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
...mapMutations([
|
||||
'initEditorState',
|
||||
'initEditorEntity',
|
||||
'setWxRendererOptions',
|
||||
'editorRefresh',
|
||||
'initCssEditorEntity'])
|
||||
"initEditorState",
|
||||
"initEditorEntity",
|
||||
"setWxRendererOptions",
|
||||
"editorRefresh",
|
||||
"initCssEditorEntity",
|
||||
]),
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this.leftAndRightScroll();
|
||||
PR.prettyPrint();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.main-body {
|
||||
@ -328,17 +391,17 @@ export default {
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-main {
|
||||
transition: all .3s;
|
||||
transition: all 0.3s;
|
||||
padding: 0;
|
||||
margin: 20px;
|
||||
margin-top: 0;
|
||||
}
|
||||
.container {
|
||||
transition: all .3s;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.preview {
|
||||
transition: background 0s;
|
||||
transition-delay: .2s;
|
||||
transition-delay: 0.2s;
|
||||
}
|
||||
.preview-wrapper_night {
|
||||
overflow-y: inherit;
|
||||
@ -369,7 +432,7 @@ export default {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
transform: translate(-50%, -50%);
|
||||
background: url('../assets/images/favicon.png') no-repeat;
|
||||
background: url("../assets/images/favicon.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
span {
|
||||
@ -385,30 +448,34 @@ export default {
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
@keyframes bounceInRight {
|
||||
0%,60%,75%,90%,100% {
|
||||
transition-timing-function: cubic-bezier(0.215,.610,.355,1.000)
|
||||
0%,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
100% {
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity:0;
|
||||
transform:translate3d(3000px,0,0)}
|
||||
opacity: 0;
|
||||
transform: translate3d(3000px, 0, 0);
|
||||
}
|
||||
60% {
|
||||
opacity:1;
|
||||
transform:translate3d(-25px,0,0)
|
||||
opacity: 1;
|
||||
transform: translate3d(-25px, 0, 0);
|
||||
}
|
||||
75% {
|
||||
transform:translate3d(10px,0,0)
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
90% {
|
||||
transform:translate3d(-5px,0,0)
|
||||
transform: translate3d(-5px, 0, 0);
|
||||
}
|
||||
100% {
|
||||
transform:none
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
@import url('../assets/less/app.less');
|
||||
@import url('../assets/less/style-mirror.css');
|
||||
@import url('../assets/less/github-v2.min.css');
|
||||
@import url("../assets/less/app.less");
|
||||
@import url("../assets/less/style-mirror.css");
|
||||
@import url("../assets/less/github-v2.min.css");
|
||||
</style>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user