4df1c799创建于 2023年1月17日历史提交
<script setup lang="ts">
import * as monaco from "monaco-editor";
import { format } from "sql-formatter";
import { uuid } from "../shared";

const id = 'monaco_' + uuid()
const props = withDefaults(
    defineProps<{
        modelValue: string;
        /**
         * enable editor readOnly
         */
        readOnly?: boolean;
        sqlFormatter?: boolean;
        height?: number | string;
        /**
         * enable editor to resize height
         */
        resize?: boolean;
    }>(),
    {
        readOnly: true,
        sqlFormatter: true,
        height: '100%',
    }
);
const myEmit = defineEmits<{(event: 'update:modelValue', text: string): void}>()

let editor:monaco.editor.IStandaloneCodeEditor;
const queryText = ref(props.modelValue)
if (props.sqlFormatter && props.modelValue) {
    let text = format(props.modelValue);
    let index = 0;
    while ((index = text.indexOf("$", index + 1)) > -1) {
        text =
          text.slice(0, index).trimEnd() +
          "$" +
          text.slice(index + 1).trimStart();
    }
    queryText.value = text;
}
watch(() => props.modelValue, v => {
    const pos = editor.getPosition()!
    editor.setValue(v)
    editor.setPosition(pos)
})
onMounted(() => {
    nextTick(() => {
        editor = monaco.editor.create(
          document.getElementById(id) as HTMLElement,
          {
              value: queryText.value,
              language: "sql",
              readOnly: props.readOnly,
              wordWrap: "on",
              lineNumbersMinChars: 3,
              rulers: [0],
              overviewRulerBorder: false,
              scrollbar: {
                  useShadows: false,
                  verticalScrollbarSize: 5,
              },
              renderLineHighlight: "gutter",
              scrollBeyondLastLine: false,
              autoIndent: 'keep',
              folding: true,
              foldingStrategy: "indentation",
              minimap: {
                  enabled: false,
              },
              formatOnType: true,
              fontSize: 12,
              theme: 'vs-dark',
          }
        );
        editor.onDidChangeModelContent(() => {
            myEmit('update:modelValue', editor.getValue())
        })
        if (props.resize && window && 'ResizeObserver' in window) {
            const resizeObserver = new ResizeObserver(entries => {
                for (const entry of entries) {
                    editor?.layout({ ...editor?.getLayoutInfo(), height: entry.contentRect.height })
                }
            })
            resizeObserver.observe(document.getElementById(id)!)
        }
    })
})
watch(() => props.height, height => {
    editor?.layout({ ...editor?.getLayoutInfo(), height: Number.parseFloat(`${height}`) })
})
</script>

<template>
    <div
        class="monaco-container"
        :id="id"
        :style="{
            height: ['%', 'px'].includes(`${props.height}`) ? props.height : `${props.height}px`,
            width: '100%',
            resize: props.resize ? 'vertical' : 'none',
        }"
    ></div>
</template>

<style scoped lang="scss">

.monaco-container {
    border: none !important;
    overflow: hidden;
    margin: 0!important;
}
:deep(.monaco-editor .view-ruler) {
    display: none;
}
:deep(.monaco-editor .margin) {
    width: 1px;
    background-color: var(--el-bg-color-og);
}

:deep(.monaco-editor .margin-view-overlays) {
    background-color: var(--el-bg-color-og);
    border-right: 1px solid var(--el-color--col-border-color);
    width: 34px !important;
}

:deep(.monaco-editor .margin-view-overlays div) {
    color: var(--el-text-color-og);
}

:deep(.monaco-editor .monaco-editor-background) {
    background-color: var(--el-bg-color-og);
}

:deep(.monaco-editor .current-line-margin) {
    border: none !important;
}

:deep(.monaco-editor .view-lines .mtk1) {
    color: var(--el-text-color-og);
}
</style>