Merge pull request #32 from doocs/feature-update

Feature update
This commit is contained in:
Yang Libin 2020-10-13 11:20:14 +08:00 committed by GitHub
commit ee4ad8dcae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 241 additions and 226 deletions

View File

@ -3,13 +3,14 @@ import fileApi from '../../api/file';
export function uploadImgFile(file) {
return new Promise((resolve, reject) => {
const checkImageResult = isImageIllegal(file);
if (checkImageResult) {
reject(checkImageResult);
return;
}
const base64Reader = new FileReader();
base64Reader.readAsDataURL(file);
base64Reader.readAsDataURL(file);
base64Reader.onload = function () {
const base64Content = this.result.split(',').pop();
fileApi.fileUpload(base64Content, file).then(res => {
@ -17,7 +18,7 @@ export function uploadImgFile(file) {
}).catch(err => {
reject(err);
})
}
};
});
}

View File

@ -216,3 +216,28 @@ export function downLoadMD(doc) {
downLink.click();
document.body.removeChild(downLink);
}
/**
* 生成列表字符串
* @param {*} data 对应内容集合
* @param {*} rows
* @param {*} cols
*/
export function createTable({data, rows, cols}) {
let table = "";
let currRow = [];
for (let i = 0; i < rows + 2; ++i) {
table += "|\t";
currRow = [];
for (let j = 0; j < cols; ++j) {
const rowIdx = i > 1 ? i - 1 : i;
i === 1 ?
currRow.push("---\t") :
currRow.push(data[`k_${rowIdx}_${j}`] || "");
}
table += currRow.join("\t|\t");
table += "\t|\n";
}
return table;
}

View File

@ -24,7 +24,7 @@ export default {
},
methods: {
onRedirect(url) {
window.open(url)
window.open(url);
}
}
}

View File

@ -120,9 +120,9 @@ export default {
fontChanged(fonts) {
this.setWxRendererOptions({
fonts: fonts
})
});
this.setCurrentFont(fonts);
this.$emit('refresh')
this.$emit('refresh');
},
sizeChanged(size) {
let theme = setFontSize(size.replace('px', ''))
@ -130,26 +130,27 @@ export default {
this.setWxRendererOptions({
size: size,
theme: theme
})
});
this.setCurrentSize(size);
this.$emit('refresh')
this.$emit('refresh');
},
colorChanged(color) {
let theme = setFontSize(this.currentSize.replace('px', ''))
theme = setColorWithCustomTemplate(theme, color)
let theme = setFontSize(this.currentSize.replace('px', ''));
theme = setColorWithCustomTemplate(theme, color);
this.setWxRendererOptions({
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.setCiteStatus(val);
this.$emit('refresh');
},
//
copy(e) {
@ -167,7 +168,7 @@ export default {
range.setEndAfter(clipboardDiv.lastChild);
window.getSelection().addRange(range);
document.execCommand('copy');
window.getSelection().removeAllRanges()
window.getSelection().removeAllRanges();
fixCodeWhiteSpace('normal');
clipboardDiv.innerHTML = this.output;
@ -189,16 +190,16 @@ export default {
this.$emit('showCssEditor');
this.$nextTick(() => {
if(!this.cssEditor) {
this.cssEditor.refresh()
this.cssEditor.refresh();
}
})
setTimeout(() => {
this.cssEditor.refresh()
this.cssEditor.refresh();
},50)
let flag = await localStorage.getItem('__css_content')
let flag = await localStorage.getItem('__css_content');
if (!flag) {
this.setCssEditorValue(DEFAULT_CSS_CONTENT)
this.setCssEditorValue(DEFAULT_CSS_CONTENT);
}
},
//

View File

@ -1,118 +1,102 @@
<template>
<el-dialog
title="插入表格"
class="insert__dialog"
:visible="value"
@close="$emit('input', false)"
border
>
<el-dialog
title="插入表格"
class="insert__dialog"
:visible="value"
@close="$emit('input', false)"
border
>
<el-row class="tb-options" type="flex" align="middle" :gutter="10">
<el-col :span="6">
行数
<el-input-number
v-model="rowNum"
controls-position="right"
@change="handleChange($event,'row')"
:min="1"
:max="100"
size="small"
></el-input-number>
</el-col>
<el-col :span="6">
列数
<el-input-number
v-model="colNum"
controls-position="right"
@change="handleChange($event,'col')"
:min="1"
:max="100"
size="small"
></el-input-number>
</el-col>
<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-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>
<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>
<el-button :type="btnType" plain @click="$emit('input', false)"> </el-button>
<el-button :type="btnType" @click="insertTable" plain> </el-button>
</div>
</el-dialog>
</el-dialog>
</template>
<script>
import config from "../../assets/scripts/config";
import {
mapState,
mapMutations
} from "vuex";
export default {
props: {
value: {
type: Boolean,
default: false
}
},
data() {
return {
config: config,
rowNum: 1,
colNum: 1,
tableData: {}
};
},
computed: {
btnType() {
return this.nightMode ? "default" : "primary";
},
...mapState({
nightMode: state => state.nightMode,
editor: state => state.editor
})
},
methods: {
//
insertTable() {
const cursor = this.editor.getCursor();
const rows = this.rowNum;
const cols = this.colNum;
let table = "";
let currRow = [];
for (let i = 0; i < rows + 2; ++i) {
table += "|\t";
currRow = [];
for (let j = 0; j < cols; ++j) {
const rowIdx = i > 1 ? i - 1 : i;
i === 1 ?
currRow.push("---\t") :
currRow.push(this.tableData[`k_${rowIdx}_${j}`] || "");
}
table += currRow.join("\t|\t");
table += "\t|\n";
}
this.tableData = {};
this.rowNum = 1;
this.colNum = 1;
this.editor.replaceSelection(`\n${table}\n`, "end");
this.$emit('input', false);
this.editorRefresh();
},
...mapMutations(["editorRefresh"]),
handleChange(val, type) {}
import config from "../../assets/scripts/config";
import {createTable} from '../../assets/scripts/util';
import {
mapState,
mapMutations
} from "vuex";
export default {
props: {
value: {
type: Boolean,
default: false
}
};
},
data() {
return {
config: config,
rowNum: 3,
colNum: 3,
tableData: {}
};
},
computed: {
btnType() {
return this.nightMode ? "default" : "primary";
},
...mapState({
nightMode: state => state.nightMode,
editor: state => state.editor
})
},
methods: {
//
insertTable() {
const cursor = this.editor.getCursor();
const table = createTable({
data: this.tableData,
rows: this.rowNum,
cols: this.colNum
});
this.tableData = {};
this.rowNum = 3;
this.colNum = 3;
this.editor.replaceSelection(`\n${table}\n`, "end");
this.$emit('input', false);
this.editorRefresh();
},
...mapMutations(["editorRefresh"])
}
};
</script>
<style lang="less" scoped>
@ -124,7 +108,7 @@
border-radius: 0;
}
.head-style .el-input__inner {
.head-style /deep/ .el-input__inner {
background-color: #f2f2f2;
}
</style>

View File

@ -11,33 +11,39 @@
</template>
<script>
import {mapState} from 'vuex';
export default {
props: {
showResetConfirm: {
type: Boolean,
default: false
}
},
computed: {
btnType() {
return this.nightMode ? 'default' : 'primary';
import {
mapState
} from 'vuex';
export default {
props: {
showResetConfirm: {
type: Boolean,
default: false
}
},
...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;
}
.text {
text-align: center;
}
.dialog-footer {
text-align: center;
}
</style>
.reset__dialog {
text-align: center;
}
.text {
text-align: center;
}
.dialog-footer {
text-align: center;
}
</style>

View File

@ -246,29 +246,24 @@ export default {
return false;
},
validateConfig() {
let checkRes = true, errMessage = '';
switch (localStorage.getItem('imgHost')) {
case "github":
if (!(this.formGitHub.repo && this.formGitHub.accessToken)) {
this.$message.error("请先配置 GitHub 图床参数");
return false;
}
case 'github':
checkRes = this.formGitHub.repo && this.formGitHub.accessToken;
errMessage = checkRes ? '' : '请先配置 GitHub 图床参数';
break;
case 'aliOSS':
if (!(this.formAliOSS.accessKeyId && this.formAliOSS.accessKeySecret && this.formAliOSS.bucket && this.formAliOSS.region)) {
this.$message.error("请先配置阿里云 OSS 参数");
return false;
}
checkRes = this.formAliOSS.accessKeyId && this.formAliOSS.accessKeySecret && this.formAliOSS.bucket && this.formAliOSS.region;
errMessage = checkRes ? '' : '请先配置阿里云 OSS 参数';
break;
case 'txCOS':
if (!(this.formTxCOS.secretId && this.formTxCOS.secretKey && this.formTxCOS.bucket && this.formTxCOS.region)) {
this.$message.error("请先配置腾讯云 COS 参数");
return false;
}
checkRes = this.formTxCOS.secretId && this.formTxCOS.secretKey && this.formTxCOS.bucket && this.formTxCOS.region;
errMessage = checkRes ? '' : '请先配置腾讯云 COS 参数';
break;
default:
return true;
}
return true;
errMessage && this.$message.error(errMessage);
return checkRes;
},
},
};

View File

@ -19,23 +19,23 @@ import {
Message
} from 'element-ui'
Vue.use(Container)
Vue.use(Header)
Vue.use(Upload)
Vue.use(Tooltip)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Select)
Vue.use(Option)
Vue.use(ColorPicker)
Vue.use(Switch)
Vue.use(Button)
Vue.use(Main)
Vue.use(Col)
Vue.use(Row)
Vue.use(Dialog)
Vue.use(Loading)
Vue.component(Message.name, Message)
Vue.use(Container);
Vue.use(Header);
Vue.use(Upload);
Vue.use(Tooltip);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Select);
Vue.use(Option);
Vue.use(ColorPicker);
Vue.use(Switch);
Vue.use(Button);
Vue.use(Main);
Vue.use(Col);
Vue.use(Row);
Vue.use(Dialog);
Vue.use(Loading);
Vue.component(Message.name, Message);
Vue.prototype.$loading = Loading.service
Vue.prototype.$message = Message
Vue.prototype.$loading = Loading.service;
Vue.prototype.$message = Message;

View File

@ -29,54 +29,54 @@ const state = {
};
const mutations = {
setEditorValue(state, data) {
state.editor.setValue(data)
state.editor.setValue(data);
},
setCssEditorValue(state, data) {
state.cssEditor.setValue(data)
state.cssEditor.setValue(data);
},
setWxRendererOptions(state, data) {
state.wxRenderer.setOptions(data);
},
setCiteStatus(state, data) {
state.citeStatus = data;
localStorage.setItem('citeStatus', data)
localStorage.setItem('citeStatus', data);
},
setCurrentFont(state, data) {
state.currentFont = data;
localStorage.setItem('fonts', data)
localStorage.setItem('fonts', data);
},
setCurrentSize(state, data) {
state.currentSize = data;
localStorage.setItem('size', data)
localStorage.setItem('size', data);
},
setCurrentColor(state, data) {
state.currentColor = data;
localStorage.setItem('color', data)
localStorage.setItem('color', data);
},
setCurrentCodeTheme(state, data) {
state.codeTheme = data;
localStorage.setItem('codeTheme', data)
localStorage.setItem('codeTheme', data);
},
setRightClickMenuVisible(state, data) {
state.rightClickMenuVisible = data;
},
themeChanged(state) {
state.nightMode = !state.nightMode;
localStorage.setItem('nightMode', state.nightMode)
localStorage.setItem('nightMode', state.nightMode);
},
initEditorState(state) {
state.currentFont = localStorage.getItem('fonts') || config.builtinFonts[0].value
state.currentColor = localStorage.getItem('color') || config.colorOption[1].value
state.currentSize = localStorage.getItem('size') || config.sizeOption[2].value
state.codeTheme = localStorage.getItem('codeTheme') || config.codeThemeOption[0].value
state.citeStatus = localStorage.getItem('citeStatus') === 'true'
state.nightMode = localStorage.getItem('nightMode') === 'true'
state.currentFont = localStorage.getItem('fonts') || config.builtinFonts[0].value;
state.currentColor = localStorage.getItem('color') || config.colorOption[1].value;
state.currentSize = localStorage.getItem('size') || config.sizeOption[2].value;
state.codeTheme = localStorage.getItem('codeTheme') || config.codeThemeOption[0].value;
state.citeStatus = localStorage.getItem('citeStatus') === 'true';
state.nightMode = localStorage.getItem('nightMode') === 'true';
state.wxRenderer = new WxRenderer({
theme: setColor(state.currentColor),
fonts: state.currentFont,
size: state.currentSize,
status: state.citeStatus
})
});
},
initEditorEntity(state) {
state.editor = CodeMirror.fromTextArea(
@ -97,7 +97,7 @@ const mutations = {
'Ctrl-S': function save(editor) {}
}
}
)
);
// 如果有编辑器内容被保存则读取,否则加载默认内容
state.editor.setValue(localStorage.getItem('__editor_content') || formatDoc(DEFAULT_CONTENT))
@ -114,18 +114,19 @@ const mutations = {
autofocus: true,
extraKeys: {
'Ctrl-F': function autoFormat(editor) {
const totalLines = editor.lineCount()
const totalLines = editor.lineCount();
editor.autoFormatRange({
line: 0,
ch: 0
}, {
line: totalLines
})
});
},
'Ctrl-S': function save(editor) {}
}
}
)
);
// 如果有编辑器内容被保存则读取,否则加载默认内容
state.cssEditor.setValue(localStorage.getItem('__css_content') || DEFAULT_CSS_CONTENT)
@ -133,21 +134,23 @@ const mutations = {
editorRefresh(state) {
let output = marked(state.editor.getValue(0), {
renderer: state.wxRenderer.getRenderer(state.citeStatus)
})
});
// 去除第一行的 margin-top
output = output.replace(/(style=".*?)"/, '$1;margin-top: 0"')
output = output.replace(/(style=".*?)"/, '$1;margin-top: 0"');
if (state.citeStatus) {
// 引用脚注
output += state.wxRenderer.buildFootnotes()
output += state.wxRenderer.buildFootnotes();
// 附加的一些 style
output += state.wxRenderer.buildAddition()
output += state.wxRenderer.buildAddition();
}
state.output = output
state.output = output;
},
clearEditorToDefault(state) {
const doc = formatDoc(DEFAULT_CONTENT)
state.editor.setValue(doc)
state.cssEditor.setValue(DEFAULT_CSS_CONTENT)
const doc = formatDoc(DEFAULT_CONTENT);
state.editor.setValue(doc);
state.cssEditor.setValue(DEFAULT_CSS_CONTENT);
}
}
@ -155,4 +158,4 @@ export default new Vuex.Store({
state,
mutations,
actions: {}
})
});

View File

@ -109,12 +109,12 @@ export default {
})
},
created() {
this.initEditorState()
this.initEditorState();
this.$nextTick(() => {
this.initEditor()
this.initCssEditor()
this.onEditorRefresh()
})
this.initEditor();
this.initCssEditor();
this.onEditorRefresh();
});
},
methods: {
initEditor() {
@ -122,8 +122,8 @@ export default {
this.editor.on('change', (cm, e) => {
if (this.changeTimer) clearTimeout(this.changeTimer);
this.changeTimer = setTimeout(() => {
this.onEditorRefresh()
saveEditorContent(this.editor, '__editor_content')
this.onEditorRefresh();
saveEditorContent(this.editor, '__editor_content');
}, 300);
});
@ -133,9 +133,9 @@ export default {
return;
}
for (let i = 0, len = e.clipboardData.items.length; i < len; ++i) {
let item = e.clipboardData.items[i]
if (item.kind === 'file') {
let item = e.clipboardData.items[i];
if (item.kind === 'file') {
//
const imgHost = localStorage.getItem('imgHost') || 'default';
if (imgHost != 'default' && !localStorage.getItem(`${imgHost}Config`)) {
@ -180,19 +180,19 @@ export default {
//
this.cssEditor.on('keyup', (cm, e) => {
if ((e.keyCode >= 65 && e.keyCode <= 90) || e.keyCode === 189) {
cm.showHint(e)
cm.showHint(e);
}
});
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', ''));
theme = customCssWithTemplate(json, this.currentColor, theme)
theme = customCssWithTemplate(json, this.currentColor, theme);
this.setWxRendererOptions({
theme: theme
});
@ -208,7 +208,7 @@ export default {
});
return;
}
this.dialogUploadImgVisible = false
this.dialogUploadImgVisible = false;
//
const cursor = this.editor.getCursor();
const imageUrl = response;
@ -316,7 +316,7 @@ export default {
mounted() {
setTimeout(() => {
this.leftAndRightScroll();
PR.prettyPrint()
PR.prettyPrint();
}, 300);
}
}