<template> <div class="jeecg-editor-ty" :class="fullCoder?'jeecg-editor-max':'jeecg-editor-min'"> <a-icon v-if="fullScreen" class="full-screen-icon" :type="iconType" @click="()=>fullCoder=!fullCoder"/> <textarea :id="dynamicId" /> <span @click="nullTipClick" class="null-tip" :class="{'null-tip-hidden': hasCode}" :style="nullTipStyle">{{ placeholderShow }}</span> </div> </template> <script> import load from './load' import '@/assets/less/codemirror_idea.css' import './cm_sql_hint.js' import { sql_keyword } from './Resource' export default { name: 'JSqlCodeEditorDyn', props:{ id: { type: String, default: function() { return 'vue-editor-' + new Date() + ((Math.random() * 1000).toFixed(0) + '') } }, value: { type: String, default: '' }, // 显示行号 lineNumbers: { type: Boolean, default: true }, placeholder: { type: String, default: '' }, zIndex: { type: [Number, String], default: 999 }, autoHeight: { type: [String, Boolean], default: true }, // 不自适应高度的情况下生效的固定高度 height: { type: [String, Number], default: '240px' }, autoHeight: { type: [String, Boolean], default: true }, // 是否显示全屏按钮 fullScreen: { type: Boolean, default: false }, autoHint:{ type: Boolean, default: true } }, data(){ return { dynamicId: this.id, coder: '', hasCode: false, code: '', // code 编辑器 是否全屏 fullCoder: false, iconType: 'fullscreen', } }, computed:{ placeholderShow() { if (this.placeholder == null) { return `请在此输入javascript代码` } else { return this.placeholder } }, nullTipStyle(){ if (this.lineNumbers) { return { left: '36px' } } else { return { left: '12px' } } }, isAutoHeight() { let {autoHeight} = this if (typeof autoHeight === 'string' && autoHeight.toLowerCase().trim() === '!ie') { autoHeight = !(isIE() || isIE11()) } else { autoHeight = true } return autoHeight }, fullScreenParentProps() { let props = { class: { 'full-screen-parent': true, 'full-screen': this.fullCoder, 'auto-height': this.isAutoHeight }, style: {} } if (this.fullCoder) { props.style['z-index'] = this.zIndex } if (!this.isAutoHeight) { props.style['height'] = (typeof this.height === 'number' ? this.height + 'px' : this.height) } return props } }, watch: { fullCoder:{ handler(value) { if(value){ this.iconType="fullscreen-exit" }else{ this.iconType="fullscreen" } } } }, mounted() { this.init() }, methods:{ init(){ this.main(); }, main(){ let obj = document.getElementById(this.dynamicId); const that = this; let editor = CodeMirror.fromTextArea(obj,{ theme:'idea', lineNumbers: this.lineNumbers, lineWrapping: true, mode: "sql", indentUnit: 1, indentWithTabs: true, styleActiveLine: true, /* styleSelectedText: false, */ extraKeys: { "F11": function(cm) { that.fullCoder = !that.fullCoder cm.setOption("fullScreen", !cm.getOption("fullScreen")); }, "Esc": function(cm) { that.fullCoder = false if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false); }, "Alt-/": function(cm) { cm.showHint(); }, "Tab": (cm) => { if (cm.somethingSelected()) { cm.indentSelection('add'); } else { //cm.indentLine(cm.getCursor().line, "add"); //走两格 第三格输入 cm.replaceSelection(Array(3).join(" "), "end", "+input"); } }, "Shift-Tab": (cm) => { if (cm.somethingSelected()) { cm.indentSelection('subtract'); } else { // cm.indentLine(cm.getCursor().line, "subtract"); const cursor = cm.getCursor(); // 光标回退 indexUnit 字符 cm.setCursor({line: cursor.line, ch: cursor.ch - 4}); } return ; } } }) this.coder = editor this.addEvent(); this.setCoderValue(); this.addSystemHint(); }, setCoderValue(){ if(this.value||this.code){ this.hasCode=true this.setCodeContent(this.value || this.code) }else{ this.coder.setValue('') this.hasCode=false } }, getCodeContent(){ return this.code }, setCodeContent(val){ setTimeout(()=>{ if(!val){ this.coder.setValue('') }else{ this.coder.setValue(val) } },300) }, addSystemHint(){ this.coder.setOption('hintOptions', { completeSingle: false, tables: sql_keyword }); }, addEvent(){ if(this.autoHint){ this.coder.on('cursorActivity', ()=>{ this.coder.showHint(); }); } this.coder.on('change', (coder) => { this.code = coder.getValue() if(this.code){ this.hasCode=true }else{ this.hasCode=false } if (this.$emit) { this.$emit('input', this.code) } }); this.coder.on('focus', () => { this.hasCode=true }); this.coder.on('blur', () => { if(this.code){ this.hasCode=true }else{ this.hasCode=false } }); }, loadResource(src,type){ return new Promise((resolve,reject)=>{ load(src,type,(msg)=>{ if(!msg){ resolve(); }else{ reject(msg) } }) }) }, nullTipClick(){ this.coder.focus() }, fullToggle(){ this.fullCoder = !this.fullCoder this.coder.setOption("fullScreen", this.fullCoder); } } } </script> <style lang="less" > .jeecg-editor-ty{ position: relative; .full-screen-icon { opacity: 0; color: black; width: 20px; height: 20px; line-height: 24px; background-color: white; position: absolute; top: 4px; right: 2px; z-index: 9; cursor: pointer; transition: opacity 0.3s; } &:hover { .full-screen-icon { opacity: 1; &:hover { background-color: rgba(255, 255, 255, 0.88); } } } .null-tip{ position: absolute; top: 4px; left: 36px; z-index: 10; font-size:16px; color: #acaaaac9; line-height: initial; } .null-tip-hidden{ display: none; } } .jeecg-editor-max{ position: fixed; left: 0; top: 0; z-index: 999; height: 100%; width: 100% !important; .CodeMirror{ position: inherit !important; width: 100%; height: 100%; } .full-screen-icon{ z-index:9999; } } </style>