123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- <template>
- <div>
- <textarea ref="codeMirrorRef"></textarea>
- </div>
- </template>
- <script>
- import { ref, onMounted, watch, markRaw, nextTick, computed } from 'vue'
- import { getUsingConfig, isJson } from '@cip/utils/util'
- import CodeMirror from 'codemirror'
- import 'codemirror/lib/codemirror.css'
- import 'codemirror/mode/javascript/javascript'
- import 'codemirror/mode/xml/xml'
- import 'codemirror/mode/sql/sql'
- import 'codemirror/addon/hint/show-hint'
- import 'codemirror/addon/hint/sql-hint'
- import 'codemirror/addon/hint/javascript-hint'
- import 'codemirror/addon/hint/show-hint.css'
- import 'codemirror/addon/edit/closebrackets'
- import 'codemirror/theme/dracula.css'
- import 'codemirror/theme/3024-day.css'
- export default {
- name: 'CipCodeMirror',
- props: {
- modelValue: [String, Object],
- /**
- * 可选值: false true 'nocursor'
- * nocursor: readonly状态并且不展示光标
- */
- readonly: {
- type: [Boolean, String],
- default: false
- },
- type: {
- type: String,
- default: 'json'
- },
- mode: String,
- height: {
- type: String,
- default: 'auto'
- },
- theme: { // 主题,需要额外引入
- type: String,
- default: 'dracula'
- },
- lineNumbers: {
- type: Boolean,
- default: true
- },
- indentUnit: {
- type: Number,
- default: 4
- }
- },
- emits: ['update:modelValue'],
- setup (props, { emit }) {
- const codeMirrorRef = ref()
- const codeMirror = ref()
- const _mode = computed(() => getUsingConfig(
- props.mode,
- props.type === 'json' ? 'application/json' : `text/${props.type}`))
- const getCodeMirrorInstance = () => {
- const instance = CodeMirror.fromTextArea(codeMirrorRef.value, {
- value: formatterValue(props.modelValue),
- mode: _mode.value,
- theme: props.theme,
- indentUnit: props.indentUnit,
- lineNumbers: props.lineNumbers,
- lineWrapping: false,
- readOnly: props.readonly,
- singleCursorHeightPerLine: false,
- extraKeys: {}
- })
- instance.setSize(props.width ?? '100%', props.height ?? 'auto')
- instance.on('change', (instance, obj) => {
- const { origin } = obj
- const value = instance.getValue()
- codeMirror.value.save()
- if (origin !== 'setValue') { // 非setValue导致的更新才emit
- emit('update:modelValue', value)
- }
- })
- instance.on('inputRead', function () {
- instance.showHint({
- completeSingle: false
- })
- })
- return instance
- }
- const formatterValue = (val) => {
- if (props.type === 'json' && val) {
- let data = val
- if (typeof val === 'string' && isJson(data)) {
- data = JSON.parse(data)
- }
- return JSON.stringify(data, null, 2) ?? ''
- } else {
- return val
- }
- }
- onMounted(() => {
- codeMirror.value = markRaw(getCodeMirrorInstance())
- watch(() => props.modelValue, (val, oldVal) => {
- const codeMirrorValue = codeMirror.value?.getValue?.()
- if (codeMirrorValue === val) return
- codeMirror.value.setValue(formatterValue(val) ?? '')
- nextTick(() => {
- codeMirror.value.refresh()
- })
- }, {
- immediate: true
- })
- })
- return {
- codeMirrorRef
- }
- }
- }
- </script>
|