2025-12-28 00:20:10 +08:00

104 lines
2.1 KiB
Vue

<template>
<Codemirror
v-model="query"
placeholder="在此输入代码..."
:style="{ height: '280px' }"
:autofocus="true"
:indent-with-tab="true"
:tab-size="2"
:extensions="extensions"
@ready="handleReady"
/>
</template>
<script>
import { MySQL, sql } from '@codemirror/lang-sql';
import { autocompletion } from '@codemirror/autocomplete';
import { Codemirror } from 'vue-codemirror';
import { shallowRef } from 'vue';
export default {
name: 'SQLCodeEditor',
components: {
Codemirror
},
props: ['schema'],
emits: ['update:query', 'codeSelected', 'codeUnselected'],
computed: {
query: {
get() {
return this.$props.query;
},
set(value) {
this.$emit('update:query', value);
}
},
extensions() {
if (!this.schema) {
return [
sql({
dialect: MySQL,
upperCaseKeywords: true
}),
autocompletion({
activateOnTyping: true,
closeOnBlur: false,
maxRenderedOptions: 10,
icons: false
})
];
}
return [
sql({
dialect: MySQL,
upperCaseKeywords: true,
schema: this.schema
}),
autocompletion({
activateOnTyping: true,
closeOnBlur: false,
maxRenderedOptions: 10,
icons: false
})
];
}
},
setup(props, { emit }) {
// Codemirror EditorView instance ref
const view = shallowRef();
const handleReady = payload => {
view.value = payload.view;
view.value.dom.addEventListener('mouseup', handleSelectionChange);
};
const handleSelectionChange = () => {
if (!view.value) return;
const { state } = view.value;
const selection = state.selection.main;
// Get the selected text
if (!selection.empty) {
const selectedText = state.pg.sliceString(
selection.from,
selection.to
);
if ((selectedText ?? '').trim() === '') {
emit('codeUnselected');
return;
}
emit('codeSelected', selectedText);
} else {
emit('codeUnselected');
}
};
return {
handleReady
};
}
};
</script>
<style>
.cm-focused {
outline: none !important;
}
</style>