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) { export function uploadImgFile(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const checkImageResult = isImageIllegal(file); const checkImageResult = isImageIllegal(file);
if (checkImageResult) { if (checkImageResult) {
reject(checkImageResult); reject(checkImageResult);
return; return;
} }
const base64Reader = new FileReader(); const base64Reader = new FileReader();
base64Reader.readAsDataURL(file);
base64Reader.readAsDataURL(file);
base64Reader.onload = function () { base64Reader.onload = function () {
const base64Content = this.result.split(',').pop(); const base64Content = this.result.split(',').pop();
fileApi.fileUpload(base64Content, file).then(res => { fileApi.fileUpload(base64Content, file).then(res => {
@ -17,7 +18,7 @@ export function uploadImgFile(file) {
}).catch(err => { }).catch(err => {
reject(err); reject(err);
}) })
} };
}); });
} }

View File

@ -216,3 +216,28 @@ export function downLoadMD(doc) {
downLink.click(); downLink.click();
document.body.removeChild(downLink); 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: { methods: {
onRedirect(url) { onRedirect(url) {
window.open(url) window.open(url);
} }
} }
} }

View File

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

View File

@ -7,30 +7,27 @@
border border
> >
<el-row class="tb-options" type="flex" align="middle" :gutter="10"> <el-row class="tb-options" type="flex" align="middle" :gutter="10">
<el-col :span="6"> <el-col>
行数 行数
<el-input-number <el-input-number
v-model="rowNum" v-model="rowNum"
controls-position="right" controls-position="right"
@change="handleChange($event,'row')"
:min="1" :min="1"
:max="100" :max="100"
size="small" size="small"
></el-input-number> ></el-input-number>
</el-col> </el-col>
<el-col :span="6"> <el-col>
列数 列数
<el-input-number <el-input-number
v-model="colNum" v-model="colNum"
controls-position="right" controls-position="right"
@change="handleChange($event,'col')"
:min="1" :min="1"
:max="100" :max="100"
size="small" size="small"
></el-input-number> ></el-input-number>
</el-col> </el-col>
</el-row> </el-row>
<!-- -->
<table style="border-collapse: collapse" class="input-table"> <table style="border-collapse: collapse" class="input-table">
<tr :class="{ 'head-style': row === 1 }" v-for="row in rowNum+1" :key="row"> <tr :class="{ 'head-style': row === 1 }" v-for="row in rowNum+1" :key="row">
<td v-for="col in colNum" :key="col"> <td v-for="col in colNum" :key="col">
@ -42,7 +39,6 @@
</td> </td>
</tr> </tr>
</table> </table>
<!-- -->
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button :type="btnType" plain @click="$emit('input', false)"> </el-button> <el-button :type="btnType" plain @click="$emit('input', false)"> </el-button>
<el-button :type="btnType" @click="insertTable" plain> </el-button> <el-button :type="btnType" @click="insertTable" plain> </el-button>
@ -52,6 +48,7 @@
<script> <script>
import config from "../../assets/scripts/config"; import config from "../../assets/scripts/config";
import {createTable} from '../../assets/scripts/util';
import { import {
mapState, mapState,
mapMutations mapMutations
@ -66,8 +63,8 @@
data() { data() {
return { return {
config: config, config: config,
rowNum: 1, rowNum: 3,
colNum: 1, colNum: 3,
tableData: {} tableData: {}
}; };
}, },
@ -84,35 +81,22 @@
// //
insertTable() { insertTable() {
const cursor = this.editor.getCursor(); const cursor = this.editor.getCursor();
const rows = this.rowNum; const table = createTable({
const cols = this.colNum; data: this.tableData,
rows: this.rowNum,
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.tableData = {};
this.rowNum = 1; this.rowNum = 3;
this.colNum = 1; this.colNum = 3;
this.editor.replaceSelection(`\n${table}\n`, "end"); this.editor.replaceSelection(`\n${table}\n`, "end");
this.$emit('input', false); this.$emit('input', false);
this.editorRefresh(); this.editorRefresh();
}, },
...mapMutations(["editorRefresh"]), ...mapMutations(["editorRefresh"])
handleChange(val, type) {}
} }
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@ -124,7 +108,7 @@
border-radius: 0; border-radius: 0;
} }
.head-style .el-input__inner { .head-style /deep/ .el-input__inner {
background-color: #f2f2f2; background-color: #f2f2f2;
} }
</style> </style>

View File

@ -11,7 +11,9 @@
</template> </template>
<script> <script>
import {mapState} from 'vuex'; import {
mapState
} from 'vuex';
export default { export default {
props: { props: {
showResetConfirm: { showResetConfirm: {
@ -28,16 +30,20 @@ export default {
}) })
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.reset__dialog { .reset__dialog {
text-align: center; text-align: center;
} }
.text { .text {
text-align: center; text-align: center;
} }
.dialog-footer { .dialog-footer {
text-align: center; text-align: center;
} }
</style> </style>

View File

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

View File

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

View File

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

View File

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