feat: 新增文本文件编辑功能
This commit is contained in:
parent
1ab8a19f8e
commit
36989ce5ff
168
resources/assets/js/components/AceEditor.vue
Normal file
168
resources/assets/js/components/AceEditor.vue
Normal file
@ -0,0 +1,168 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'AceEditor',
|
||||
model: {
|
||||
prop: 'code',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
code: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: 'json'
|
||||
},
|
||||
height: {
|
||||
type: Number || null,
|
||||
default: null
|
||||
},
|
||||
width: {
|
||||
type: Number || null,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('div')
|
||||
},
|
||||
data: () => ({
|
||||
editor: null,
|
||||
cursorPosition: {
|
||||
row: 0,
|
||||
column: 0
|
||||
}
|
||||
}),
|
||||
mounted() {
|
||||
$A.loadScriptS([
|
||||
'js/ace/ace.js',
|
||||
'js/ace/mode-json.js',
|
||||
], () => {
|
||||
// set init editor size
|
||||
this.setSize(this.$el, {height: this.height, width: this.width})
|
||||
|
||||
// init ace editor
|
||||
this.editor = window.ace.edit(this.$el)
|
||||
this.editor.session.setMode(`ace/mode/${this.language || 'json'}`)
|
||||
|
||||
// emit 'mounted' event
|
||||
this.$emit('mounted', this.editor)
|
||||
|
||||
// official syntax validation workers include 'coffee', 'css', 'html'
|
||||
// 'javascript', 'json', 'lua', 'php', 'xml' and 'xquery'
|
||||
if (this.editor.session.$worker) {
|
||||
this.editor.session.$worker.addEventListener('annotate', this.workerMessage, false)
|
||||
}
|
||||
|
||||
// set value and clear selection
|
||||
this.editor.setValue(this.code)
|
||||
this.editor.clearSelection()
|
||||
|
||||
// set ace editor options and theme
|
||||
this.editor.setOptions(this.options)
|
||||
this.theme && this.editor.setTheme(`ace/theme/${this.theme}`)
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* listening lint events from worker
|
||||
* @param data
|
||||
*/
|
||||
workerMessage({data}) {
|
||||
// record current cursor position
|
||||
this.cursorPosition = this.editor.selection.getCursor()
|
||||
const [validationInfo] = data
|
||||
if (validationInfo && validationInfo.type === 'error') {
|
||||
this.$emit('validationFailed', validationInfo)
|
||||
} else {
|
||||
this.$emit('change', this.editor.getValue())
|
||||
}
|
||||
},
|
||||
/**
|
||||
* set editor size
|
||||
* @param dom
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
setSize(dom, {width = this.width, height = this.height}) {
|
||||
dom.style.width = width && typeof width === 'number' ? `${width}px` : '100%'
|
||||
dom.style.height = height && typeof height === 'number' ? `${height}px` : '100%'
|
||||
this.$nextTick(() => this.editor && this.editor.resize())
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
/**
|
||||
* watching and set options
|
||||
* @param newOptions ace editor options
|
||||
*/
|
||||
options(newOptions) {
|
||||
if (newOptions && typeof newOptions === 'object') {
|
||||
this.editor && this.editor.setOptions(newOptions)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* watching and set theme
|
||||
* @param newTheme
|
||||
*/
|
||||
theme(newTheme) {
|
||||
if (newTheme && typeof newTheme === 'string') {
|
||||
this.editor && this.editor.setTheme(`ace/theme/${this.theme}`)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* watching and set language
|
||||
* @param newLanguage
|
||||
*/
|
||||
language(newLanguage) {
|
||||
if (newLanguage && typeof newLanguage === 'string') {
|
||||
this.editor && this.editor.session.setMode(`ace/mode/${newLanguage}`)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* watching and set width
|
||||
* @param newWidth
|
||||
*/
|
||||
width(newWidth) {
|
||||
this.setSize(this.el, {width: newWidth})
|
||||
},
|
||||
/**
|
||||
* watching and set height
|
||||
* @param newHeight
|
||||
*/
|
||||
height(newHeight) {
|
||||
this.setSize(this.el, {height: newHeight})
|
||||
},
|
||||
/**
|
||||
* watching and set code
|
||||
* @param newCode
|
||||
*/
|
||||
code(newCode) {
|
||||
if (!this.editor) {
|
||||
return
|
||||
}
|
||||
this.editor.setValue(newCode)
|
||||
this.editor.clearSelection()
|
||||
const {row, column} = this.cursorPosition
|
||||
// move cursor to current position
|
||||
this.editor.selection.moveCursorTo(row, column)
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.editor) {
|
||||
if (this.editor.session.$worker) {
|
||||
this.editor.session.$worker.removeEventListener('message', this.workerMessage, false)
|
||||
}
|
||||
this.editor.destroy()
|
||||
this.editor.container.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
17
resources/assets/statics/public/js/ace/ace.js
vendored
Normal file
17
resources/assets/statics/public/js/ace/ace.js
vendored
Normal file
File diff suppressed because one or more lines are too long
8
resources/assets/statics/public/js/ace/mode-json.js
vendored
Normal file
8
resources/assets/statics/public/js/ace/mode-json.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user