一、本codeMirror代码段实现功能有:
1. 实例化
2. 动态设置实例的宽度、高度
editor.setSize(width,height)
3. 获取编辑器输入值
editor.getValue()
4. 获取鼠标选中区域的代码
editor.getSelection()
5. 设置编辑器的值
editor.setValue(val)
6. 输入的关键字统一变成大写字母
7. 用户实时输入监听:支持db.table动态获取点后参数列表提示功能(动态设置词库并提示)
eg.
8. 获取当前位置 之前/之后 的sql语句(截至到上一个/下一个分号)
editor.getRange({line,ch},{line,ch}) //获取指定范围内的文本内容第一个对象是起始坐标,第二个是结束坐标
二、以上功能具体实现代码如下(vue):
<template>
<textarea ref="txt" class="txt">
</textarea>
</template>
<script>
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/solarized.css'
import 'codemirror/addon/edit/closebrackets.js'
import 'codemirror/mode/sql/sql.js'
import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/hint/show-hint.css'
// import '@/vendor/codemirror/addon/hint/sql-hint.js'
import 'codemirror/addon/hint/sql-hint.js'
import Config from '@/config/sysconfig'
import { mapGetters, mapActions } from 'vuex'
import { queryDatabaseTips } from '@/api/list'
export default {
name: 'SqlEditor',
props: {
height: {
type: Number,
default: () => 250
}
},
data() {
return {
code: '',
editor: null,
isRealTimeTip: false // 是否是实时的提示
}
},
computed: {
...mapGetters({
idbLexicon: 'getIdbLexicon'
})
},
mounted() {
this.init()
},
methods: {
...mapActions({
setIdbLexicon: 'setIdbLexicon'
}),
init() {
const _this = this
// 实例初始化
this.editor = CodeMirror.fromTextArea(this.$refs.txt, {
tabSize: 4,
mode: 'text/x-mysql',
theme: 'solarized',
autoCloseBrackets: true, // 在键入时自动关闭括号和引号
styleActiveLine: true,
lineNumbers: true,
line: true,
lineWrapping: true,
hintOptions: {
completeSingle: false,
tables: _this.idbLexicon
},
extraKeys: {
'Ctrl-Space': editor => {
editor.showHint()
}
}
})
this.editor.setSize('100%', this.height + 'px')
this.editor.on('keypress', editor => {
const __Cursor = editor.getDoc().getCursor()
const __Token = editor.getTokenAt(__Cursor)
if (
__Token.type &&
__Token.type !== 'string' &&
__Token.type !== 'punctuation' &&
__Token.string.indexOf('.') === -1
) {
// 把输入的关键字统一变成大写字母
editor.replaceRange(
__Token.string.toUpperCase(),
{
line: __Cursor.line,
ch: __Token.start
},
{
line: __Cursor.line,
ch: __Token.end
},
__Token.string
)
}
editor.showHint()
})
// 用户实时输入监听
this.editor.on('cursorActivity', function(editor) {
const __Cursor = editor.getDoc().getCursor()
const __Token = editor.getTokenAt(__Cursor)
const { string } = __Token
// console.log(__Cursor, __Token, string)
if (string.charAt(string.length - 1) === '.') {
// 当输入点时
_this.loading = _this.$loading(Config.loading)
const curIndex = __Token.start
const curLine = _this.editor.getLine(__Cursor.line)
const key = curLine.slice(curLine.slice(0, curIndex).lastIndexOf(' ') + 1, curIndex) // 点前的关键字
const res = _this.idbLexicon[key]
if (res && res.length) {
// store中是否已有该词库数据
_this.loading.close()
} else {
const last = _this.getLast(__Cursor)
const next = _this.getNext(__Cursor)
const sql = last + next
_this.getLexiconList({
key,
sql
})
}
}
})
},
// 获取当前位置之前的sql语句(截至到上一个分号)
getLast(__Cursor) {
let sql = ''
const s = this.editor.getRange({ line: 0, ch: 0 }, { line: __Cursor.line, ch: __Cursor.ch })
const i = s.lastIndexOf(';')
if (i === -1) {
sql = s
} else {
sql = s.slice(i + 1)
}
return sql
},
// 获取当前位置之后的sql语句(截至到下一个分号)
getNext(__Cursor) {
let sql = ''
const lastLine = this.editor.lastLine()
const n = this.editor.getRange(
{ line: __Cursor.line, ch: __Cursor.ch },
{ line: lastLine, ch: this.editor.getLine(lastLine).length }
)
const i = n.indexOf(';')
if (i === -1) {
sql += n
} else {
sql += n.slice(0, i + 1)
}
return sql
},
// 设置value
setValue(val) {
this.editor.setValue(val)
},
// 获取value
getValue() {
return this.editor.getValue()
},
// 获取选中内容
getSelection() {
return this.editor.getSelection()
},
// http:获取词库List
getLexiconList(params) {
var _this = this
queryDatabaseTips({
...params,
databaseConfigId: this.$route.params.authId
}).then(
response => {
const result = _this.zMethod.validateResponse(response, _this)
if (!!result && JSON.stringify(result) !== '{}') {
const key = Object.keys(result)[0]
this.isRealTimeTip = true
// dbName(dbUser).表名 & alias.字段名 --补全提示
this.setIdbLexicon({
key,
value: result[key] // eg.['abc', 'dce', Math.random() + '']
})
}
_this.loading.close()
},
() => {
_this.loading.close()
}
)
}
},
watch: {
height(newVal) {
this.editor.setSize('100%', newVal + 'px')
},
idbLexicon(tables) {
// 现有实例参数
const hintOptions = this.editor.getOption('hintOptions')
// 动态设置tables参数
this.editor.setOption('hintOptions', {
...hintOptions,
tables: {
...hintOptions.tables,
...tables
}
})
if (this.isRealTimeTip) {
// 显示提示
this.editor.showHint()
}
this.isRealTimeTip = false
}
}
}
</script>
<style>
.cm-s-solarized.cm-s-dark,
.cm-s-solarized.cm-s-dark .CodeMirror-gutters {
background-color: #000;
text-shadow: #000 0 1px;
}
</style>
转载于:https://my.oschina.net/SZQing/blog/3016029