mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	feat: 初步移除codemirror
This commit is contained in:
		@@ -10,7 +10,6 @@
 | 
				
			|||||||
    "@element-plus/icons-vue": "^2.0.9",
 | 
					    "@element-plus/icons-vue": "^2.0.9",
 | 
				
			||||||
    "asciinema-player": "^3.0.1",
 | 
					    "asciinema-player": "^3.0.1",
 | 
				
			||||||
    "axios": "^1.1.2",
 | 
					    "axios": "^1.1.2",
 | 
				
			||||||
    "codemirror": "^5.65.5",
 | 
					 | 
				
			||||||
    "countup.js": "^2.0.7",
 | 
					    "countup.js": "^2.0.7",
 | 
				
			||||||
    "cropperjs": "^1.5.11",
 | 
					    "cropperjs": "^1.5.11",
 | 
				
			||||||
    "echarts": "^5.3.3",
 | 
					    "echarts": "^5.3.3",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								mayfly_go_web/shim.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								mayfly_go_web/shim.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@ declare module '*.vue' {
 | 
				
			|||||||
	const component: DefineComponent<{}, {}, any>;
 | 
						const component: DefineComponent<{}, {}, any>;
 | 
				
			||||||
	export default component;
 | 
						export default component;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
declare module 'codemirror';
 | 
					 | 
				
			||||||
declare module 'sql-formatter';
 | 
					declare module 'sql-formatter';
 | 
				
			||||||
declare module 'jsoneditor';
 | 
					declare module 'jsoneditor';
 | 
				
			||||||
declare module 'asciinema-player';
 | 
					declare module 'asciinema-player';
 | 
				
			||||||
 | 
					declare module 'monaco-editor';
 | 
				
			||||||
@@ -1,360 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="in-coder-panel">
 | 
					 | 
				
			||||||
        <textarea ref="textarea"></textarea>
 | 
					 | 
				
			||||||
        <el-select v-if="canChangeMode" class="code-mode-select" v-model="mode" @change="changeMode">
 | 
					 | 
				
			||||||
            <el-option v-for="mode in modes" :key="mode.value" :label="mode.label" :value="mode.value"> </el-option>
 | 
					 | 
				
			||||||
        </el-select>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script lang="ts">
 | 
					 | 
				
			||||||
import { ref, nextTick, toRefs, reactive, watch, onMounted, defineComponent } from 'vue';
 | 
					 | 
				
			||||||
// 引入全局实例
 | 
					 | 
				
			||||||
import _CodeMirror from 'codemirror';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 核心样式
 | 
					 | 
				
			||||||
import 'codemirror/lib/codemirror.css';
 | 
					 | 
				
			||||||
// 引入主题后还需要在 options 中指定主题才会生效
 | 
					 | 
				
			||||||
import 'codemirror/theme/cobalt.css';
 | 
					 | 
				
			||||||
import 'codemirror/addon/selection/active-line.js';
 | 
					 | 
				
			||||||
// 匹配括号
 | 
					 | 
				
			||||||
import 'codemirror/addon/edit/matchbrackets.js';
 | 
					 | 
				
			||||||
import 'codemirror/addon/selection/active-line';
 | 
					 | 
				
			||||||
import 'codemirror/addon/comment/comment';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
 | 
					 | 
				
			||||||
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
 | 
					 | 
				
			||||||
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ,所以此处才把对应的 JS 提前引入
 | 
					 | 
				
			||||||
import 'codemirror/mode/yaml/yaml.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/dockerfile/dockerfile.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/nginx/nginx.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/javascript/javascript.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/css/css.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/xml/xml.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/markdown/markdown.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/python/python.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/shell/shell.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/sql/sql.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/vue/vue.js';
 | 
					 | 
				
			||||||
import 'codemirror/mode/textile/textile.js';
 | 
					 | 
				
			||||||
import 'codemirror/addon/hint/show-hint.css';
 | 
					 | 
				
			||||||
import 'codemirror/addon/hint/show-hint.js';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { ElOption, ElSelect } from 'element-plus';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 尝试获取全局实例
 | 
					 | 
				
			||||||
const CodeMirror = (window as any).CodeMirror || _CodeMirror;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default defineComponent({
 | 
					 | 
				
			||||||
    name: 'CodeMirror',
 | 
					 | 
				
			||||||
    components: {
 | 
					 | 
				
			||||||
        ElOption,
 | 
					 | 
				
			||||||
        ElSelect,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    props: {
 | 
					 | 
				
			||||||
        modelValue: {
 | 
					 | 
				
			||||||
            type: String,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        language: {
 | 
					 | 
				
			||||||
            type: String,
 | 
					 | 
				
			||||||
            default: null,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        height: {
 | 
					 | 
				
			||||||
            type: String,
 | 
					 | 
				
			||||||
            default: '500px',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        width: {
 | 
					 | 
				
			||||||
            type: String,
 | 
					 | 
				
			||||||
            default: 'auto',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        canChangeMode: {
 | 
					 | 
				
			||||||
            type: Boolean,
 | 
					 | 
				
			||||||
            default: false,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        options: {
 | 
					 | 
				
			||||||
            type: Object,
 | 
					 | 
				
			||||||
            default: null,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    setup(props: any, { emit }) {
 | 
					 | 
				
			||||||
        let { modelValue, language } = toRefs(props);
 | 
					 | 
				
			||||||
        const textarea: any = ref(null);
 | 
					 | 
				
			||||||
        // 编辑器实例
 | 
					 | 
				
			||||||
        let coder = null as any;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const state = reactive({
 | 
					 | 
				
			||||||
            coder: null as any,
 | 
					 | 
				
			||||||
            content: '',
 | 
					 | 
				
			||||||
            // 默认的语法类型
 | 
					 | 
				
			||||||
            mode: 'x-sh',
 | 
					 | 
				
			||||||
            // 默认配置
 | 
					 | 
				
			||||||
            options: {
 | 
					 | 
				
			||||||
                // 缩进格式
 | 
					 | 
				
			||||||
                tabSize: 2,
 | 
					 | 
				
			||||||
                // 主题,对应主题库 JS 需要提前引入
 | 
					 | 
				
			||||||
                theme: 'cobalt',
 | 
					 | 
				
			||||||
                // 显示行号
 | 
					 | 
				
			||||||
                lineNumbers: true,
 | 
					 | 
				
			||||||
                line: true,
 | 
					 | 
				
			||||||
                indentWithTabs: true,
 | 
					 | 
				
			||||||
                smartIndent: true,
 | 
					 | 
				
			||||||
                matchBrackets: true,
 | 
					 | 
				
			||||||
                autofocus: true,
 | 
					 | 
				
			||||||
                styleSelectedText: true,
 | 
					 | 
				
			||||||
                styleActiveLine: true, // 高亮选中行
 | 
					 | 
				
			||||||
                foldGutter: true, // 块槽
 | 
					 | 
				
			||||||
                // extraKeys: { Tab: 'autocomplete' }, // 自定义快捷键
 | 
					 | 
				
			||||||
                hintOptions: {
 | 
					 | 
				
			||||||
                    // 当匹配只有一项的时候是否自动补全
 | 
					 | 
				
			||||||
                    completeSingle: false,
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            // 支持切换的语法高亮类型,对应 JS 已经提前引入
 | 
					 | 
				
			||||||
            // 使用的是 MIME-TYPE ,不过作为前缀的 text/ 在后面指定时写死了
 | 
					 | 
				
			||||||
            modes: [
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-sh',
 | 
					 | 
				
			||||||
                    label: 'Shell',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-yaml',
 | 
					 | 
				
			||||||
                    label: 'Yaml',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-dockerfile',
 | 
					 | 
				
			||||||
                    label: 'Dockerfile',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-nginx-conf',
 | 
					 | 
				
			||||||
                    label: 'Nginx',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'html',
 | 
					 | 
				
			||||||
                    label: 'XML/HTML',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-python',
 | 
					 | 
				
			||||||
                    label: 'Python',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-sql',
 | 
					 | 
				
			||||||
                    label: 'SQL',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'css',
 | 
					 | 
				
			||||||
                    label: 'CSS',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'javascript',
 | 
					 | 
				
			||||||
                    label: 'Javascript',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-java',
 | 
					 | 
				
			||||||
                    label: 'Java',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'x-vue',
 | 
					 | 
				
			||||||
                    label: 'Vue',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'markdown',
 | 
					 | 
				
			||||||
                    label: 'Markdown',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    value: 'text/x-textile',
 | 
					 | 
				
			||||||
                    label: 'text',
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        onMounted(() => {
 | 
					 | 
				
			||||||
            init();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        watch(
 | 
					 | 
				
			||||||
            () => props.modelValue,
 | 
					 | 
				
			||||||
            (newValue) => {
 | 
					 | 
				
			||||||
                handerCodeChange(newValue);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // watch(
 | 
					 | 
				
			||||||
        //     () => props.options,
 | 
					 | 
				
			||||||
        //     (newValue, oldValue) => {
 | 
					 | 
				
			||||||
        //         for (const key in newValue) {
 | 
					 | 
				
			||||||
        //             coder.setOption(key, newValue[key]);
 | 
					 | 
				
			||||||
        //         }
 | 
					 | 
				
			||||||
        //     }
 | 
					 | 
				
			||||||
        // );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const init = () => {
 | 
					 | 
				
			||||||
            if (props.options) {
 | 
					 | 
				
			||||||
                state.options = props.options;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置
 | 
					 | 
				
			||||||
            coder = CodeMirror.fromTextArea(textarea.value, state.options);
 | 
					 | 
				
			||||||
            coder.setValue(modelValue.value || state.content);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // 支持双向绑定
 | 
					 | 
				
			||||||
            coder.on('change', (coder: any) => {
 | 
					 | 
				
			||||||
                state.content = coder.getDoc().getValue();
 | 
					 | 
				
			||||||
                emit('update:modelValue', state.content);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            coder.on('inputRead', (instance: any, changeObj: any) => {
 | 
					 | 
				
			||||||
                if (/^[a-zA-Z]/.test(changeObj.text[0])) {
 | 
					 | 
				
			||||||
                    instance.showHint();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            coder.setSize(props.width, props.height);
 | 
					 | 
				
			||||||
            // editor.setSize('width','height');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // 修改编辑器的语法配置
 | 
					 | 
				
			||||||
            setMode(language.value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                'scroll',
 | 
					 | 
				
			||||||
                'changes',
 | 
					 | 
				
			||||||
                'beforeChange',
 | 
					 | 
				
			||||||
                'cursorActivity',
 | 
					 | 
				
			||||||
                'keyHandled',
 | 
					 | 
				
			||||||
                'inputRead',
 | 
					 | 
				
			||||||
                'electricInput',
 | 
					 | 
				
			||||||
                'beforeSelectionChange',
 | 
					 | 
				
			||||||
                'viewportChange',
 | 
					 | 
				
			||||||
                'swapDoc',
 | 
					 | 
				
			||||||
                'gutterClick',
 | 
					 | 
				
			||||||
                'gutterContextMenu',
 | 
					 | 
				
			||||||
                'focus',
 | 
					 | 
				
			||||||
                'blur',
 | 
					 | 
				
			||||||
                'refresh',
 | 
					 | 
				
			||||||
                'optionChange',
 | 
					 | 
				
			||||||
                'scrollCursorIntoView',
 | 
					 | 
				
			||||||
                'update',
 | 
					 | 
				
			||||||
            ].forEach((event) => {
 | 
					 | 
				
			||||||
                // 循环事件,并兼容 run-time 事件命名
 | 
					 | 
				
			||||||
                coder.on(event, (...args: any) => {
 | 
					 | 
				
			||||||
                    // console.log('当有事件触发了', event, args);
 | 
					 | 
				
			||||||
                    emit(event, ...args);
 | 
					 | 
				
			||||||
                    const lowerCaseEvent = event.replace(/([A-Z])/g, '-$1').toLowerCase();
 | 
					 | 
				
			||||||
                    if (lowerCaseEvent !== event) {
 | 
					 | 
				
			||||||
                        emit(lowerCaseEvent, ...args);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            state.coder = coder;
 | 
					 | 
				
			||||||
            // 不加无法显示内容,需点击后才可显示
 | 
					 | 
				
			||||||
            refresh();
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const refresh = () => {
 | 
					 | 
				
			||||||
            nextTick(() => {
 | 
					 | 
				
			||||||
                coder.refresh();
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 设置模式
 | 
					 | 
				
			||||||
        const setMode = (val: string) => {
 | 
					 | 
				
			||||||
            if (val) {
 | 
					 | 
				
			||||||
                // 获取具体的语法类型对象
 | 
					 | 
				
			||||||
                let modeObj = getLanguage(val);
 | 
					 | 
				
			||||||
                // 判断父容器传入的语法是否被支持
 | 
					 | 
				
			||||||
                if (modeObj) {
 | 
					 | 
				
			||||||
                    state.mode = modeObj.value;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // 修改编辑器的语法配置
 | 
					 | 
				
			||||||
            coder.setOption('mode', `text/${state.mode}`);
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 获取当前语法类型
 | 
					 | 
				
			||||||
        const getLanguage = (language: string) => {
 | 
					 | 
				
			||||||
            // 在支持的语法类型列表中寻找传入的语法类型
 | 
					 | 
				
			||||||
            return state.modes.find((mode: any) => {
 | 
					 | 
				
			||||||
                // 所有的值都忽略大小写,方便比较
 | 
					 | 
				
			||||||
                let currentLanguage = language.toLowerCase();
 | 
					 | 
				
			||||||
                let currentLabel = mode.label.toLowerCase();
 | 
					 | 
				
			||||||
                let currentValue = mode.value.toLowerCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // 由于真实值可能不规范,例如 java 的真实值是 x-java ,所以讲 value 和 label 同时和传入语法进行比较
 | 
					 | 
				
			||||||
                return currentLabel === currentLanguage || currentValue === currentLanguage;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 更改模式
 | 
					 | 
				
			||||||
        const changeMode = (val: string) => {
 | 
					 | 
				
			||||||
            setMode(val);
 | 
					 | 
				
			||||||
            // 获取修改后的语法
 | 
					 | 
				
			||||||
            let label = (getLanguage(val) as any).label.toLowerCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // 允许父容器通过以下函数监听当前的语法值
 | 
					 | 
				
			||||||
            emit('language-change', label);
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const handerCodeChange = (newVal: string) => {
 | 
					 | 
				
			||||||
            const cm_value = coder.getValue();
 | 
					 | 
				
			||||||
            if (newVal !== cm_value) {
 | 
					 | 
				
			||||||
                const scrollInfo = coder.getScrollInfo();
 | 
					 | 
				
			||||||
                coder.setValue(newVal);
 | 
					 | 
				
			||||||
                state.content = newVal;
 | 
					 | 
				
			||||||
                coder.scrollTo(scrollInfo.left, scrollInfo.top);
 | 
					 | 
				
			||||||
                refresh();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            ...toRefs(state),
 | 
					 | 
				
			||||||
            textarea,
 | 
					 | 
				
			||||||
            changeMode,
 | 
					 | 
				
			||||||
            refresh,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style lang="scss">
 | 
					 | 
				
			||||||
.in-coder-panel {
 | 
					 | 
				
			||||||
    flex-grow: 1;
 | 
					 | 
				
			||||||
    display: flex;
 | 
					 | 
				
			||||||
    position: relative;
 | 
					 | 
				
			||||||
    .CodeMirror {
 | 
					 | 
				
			||||||
        flex-grow: 1;
 | 
					 | 
				
			||||||
        z-index: 1;
 | 
					 | 
				
			||||||
        .CodeMirror-code {
 | 
					 | 
				
			||||||
            line-height: 19px;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        font-family: 'JetBrainsMono';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .code-mode-select {
 | 
					 | 
				
			||||||
        position: absolute;
 | 
					 | 
				
			||||||
        z-index: 2;
 | 
					 | 
				
			||||||
        right: 10px;
 | 
					 | 
				
			||||||
        top: 10px;
 | 
					 | 
				
			||||||
        max-width: 130px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.CodeMirror-hints {
 | 
					 | 
				
			||||||
    position: absolute;
 | 
					 | 
				
			||||||
    z-index: 10000;
 | 
					 | 
				
			||||||
    overflow: hidden;
 | 
					 | 
				
			||||||
    list-style: none;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    margin: 0;
 | 
					 | 
				
			||||||
    padding: 2px;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    -webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
    -moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
    box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
    border-radius: 3px;
 | 
					 | 
				
			||||||
    border: 1px solid silver;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    background: white;
 | 
					 | 
				
			||||||
    font-size: 90%;
 | 
					 | 
				
			||||||
    font-family: 'JetBrainsMono';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    max-height: 20em;
 | 
					 | 
				
			||||||
    overflow-y: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
import _CodeMirror from 'codemirror'
 | 
					 | 
				
			||||||
import codemirror from './codemirror.vue'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const CodeMirror = window.CodeMirror || _CodeMirror
 | 
					 | 
				
			||||||
const install = (Vue, config) => {
 | 
					 | 
				
			||||||
  if (config) {
 | 
					 | 
				
			||||||
    if (config.options) {
 | 
					 | 
				
			||||||
      codemirror.props.globalOptions.default = () => config.options
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (config.events) {
 | 
					 | 
				
			||||||
      codemirror.props.globalEvents.default = () => config.events
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  Vue.component(codemirror.name, codemirror)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const VueCodemirror = { CodeMirror, codemirror, install }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default VueCodemirror
 | 
					 | 
				
			||||||
export { CodeMirror, codemirror, install }
 | 
					 | 
				
			||||||
							
								
								
									
										209
									
								
								mayfly_go_web/src/components/monaco/MonacoEditor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								mayfly_go_web/src/components/monaco/MonacoEditor.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <div class="monaco-editor">
 | 
				
			||||||
 | 
					        <div ref="monacoTextarea" :style="{ height: height }"></div>
 | 
				
			||||||
 | 
					        <el-select v-if="canChangeMode" class="code-mode-select" v-model="languageMode" @change="changeLanguage">
 | 
				
			||||||
 | 
					            <el-option v-for="mode in languages" :key="mode.value" :label="mode.label" :value="mode.value"> </el-option>
 | 
				
			||||||
 | 
					        </el-select>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
				
			||||||
 | 
					import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
 | 
				
			||||||
 | 
					import * as monaco from 'monaco-editor';
 | 
				
			||||||
 | 
					import { editor } from 'monaco-editor';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 主题仓库 https://github.com/brijeshb42/monaco-themes 
 | 
				
			||||||
 | 
					// 主题例子 https://editor.bitwiser.in/
 | 
				
			||||||
 | 
					// import Monokai from 'monaco-themes/themes/Monokai.json'
 | 
				
			||||||
 | 
					// import Active4D from 'monaco-themes/themes/Active4D.json'
 | 
				
			||||||
 | 
					// import ahe from 'monaco-themes/themes/All Hallows Eve.json'
 | 
				
			||||||
 | 
					// import bop from 'monaco-themes/themes/Birds of Paradise.json'
 | 
				
			||||||
 | 
					// import krTheme from 'monaco-themes/themes/krTheme.json'
 | 
				
			||||||
 | 
					// import Dracula from 'monaco-themes/themes/Dracula.json'
 | 
				
			||||||
 | 
					import SolarizedLight from 'monaco-themes/themes/Solarized-light.json'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ElOption, ElSelect } from 'element-plus';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
					    modelValue: {
 | 
				
			||||||
 | 
					        type: String,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    language: {
 | 
				
			||||||
 | 
					        type: String,
 | 
				
			||||||
 | 
					        default: null,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    height: {
 | 
				
			||||||
 | 
					        type: String,
 | 
				
			||||||
 | 
					        default: '500px',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    width: {
 | 
				
			||||||
 | 
					        type: String,
 | 
				
			||||||
 | 
					        default: 'auto',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    canChangeMode: {
 | 
				
			||||||
 | 
					        type: Boolean,
 | 
				
			||||||
 | 
					        default: false,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    options: {
 | 
				
			||||||
 | 
					        type: Object,
 | 
				
			||||||
 | 
					        default: null,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//定义事件
 | 
				
			||||||
 | 
					const emit = defineEmits(['update:modelValue'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const languages = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'shell',
 | 
				
			||||||
 | 
					        label: 'Shell',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'yaml',
 | 
				
			||||||
 | 
					        label: 'Yaml',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'dockerfile',
 | 
				
			||||||
 | 
					        label: 'Dockerfile',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'x-nginx-conf',
 | 
				
			||||||
 | 
					        label: 'Nginx',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'html',
 | 
				
			||||||
 | 
					        label: 'XML/HTML',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'python',
 | 
				
			||||||
 | 
					        label: 'Python',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'sql',
 | 
				
			||||||
 | 
					        label: 'SQL',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'css',
 | 
				
			||||||
 | 
					        label: 'CSS',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'javascript',
 | 
				
			||||||
 | 
					        label: 'Javascript',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'json',
 | 
				
			||||||
 | 
					        label: 'Json',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'java',
 | 
				
			||||||
 | 
					        label: 'Java',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'markdown',
 | 
				
			||||||
 | 
					        label: 'Markdown',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'text',
 | 
				
			||||||
 | 
					        label: 'text',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const state = reactive({
 | 
				
			||||||
 | 
					    languageMode: 'shell',
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
					    languageMode,
 | 
				
			||||||
 | 
					} = toRefs(state)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onMounted(() => {
 | 
				
			||||||
 | 
					    state.languageMode = props.language
 | 
				
			||||||
 | 
					    initMonacoEditor();
 | 
				
			||||||
 | 
					    setEditorValue(props.modelValue)
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const monacoTextarea: any = ref(null);
 | 
				
			||||||
 | 
					let monacoEditor: editor.IStandaloneCodeEditor = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					self.MonacoEnvironment = {
 | 
				
			||||||
 | 
					    getWorker() {
 | 
				
			||||||
 | 
					        return new EditorWorker();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const initMonacoEditor = () => {
 | 
				
			||||||
 | 
					    console.log('初始化monaco编辑器')
 | 
				
			||||||
 | 
					    // options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language
 | 
				
			||||||
 | 
					    // 初始化一些主题
 | 
				
			||||||
 | 
					    monaco.editor.defineTheme('SolarizedLight', SolarizedLight);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('Monokai', Monokai);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('Active4D', Active4D);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('ahe', ahe);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('bop', bop);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('krTheme', krTheme);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('Dracula', Dracula);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('TextmateMac', TextmateMac);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    monacoEditor = monaco.editor.create(monacoTextarea.value, {
 | 
				
			||||||
 | 
					        language: state.languageMode,
 | 
				
			||||||
 | 
					        theme: 'SolarizedLight',
 | 
				
			||||||
 | 
					        automaticLayout: true, //自适应宽高布局
 | 
				
			||||||
 | 
					        foldingStrategy: 'indentation',//代码可分小段折叠
 | 
				
			||||||
 | 
					        roundedSelection: false, // 禁用选择文本背景的圆角
 | 
				
			||||||
 | 
					        matchBrackets: 'near',
 | 
				
			||||||
 | 
					        linkedEditing: true,
 | 
				
			||||||
 | 
					        cursorBlinking: 'smooth',// 光标闪烁样式
 | 
				
			||||||
 | 
					        mouseWheelZoom: true, // 在按住Ctrl键的同时使用鼠标滚轮时,在编辑器中缩放字体
 | 
				
			||||||
 | 
					        overviewRulerBorder: false, // 不要滚动条的边框
 | 
				
			||||||
 | 
					        tabSize: 2, // tab 缩进长度
 | 
				
			||||||
 | 
					        fontFamily: 'JetBrainsMono', // 字体 暂时不要设置,否则光标容易错位
 | 
				
			||||||
 | 
					        fontWeight: 'bold',
 | 
				
			||||||
 | 
					        // fontSize: 12,
 | 
				
			||||||
 | 
					        // letterSpacing: 1, 字符间距
 | 
				
			||||||
 | 
					        // quickSuggestions:false, // 禁用代码提示
 | 
				
			||||||
 | 
					        minimap: {
 | 
				
			||||||
 | 
					            enabled: false, // 不要小地图
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 监听内容改变,双向绑定
 | 
				
			||||||
 | 
					    monacoEditor.onDidChangeModelContent(() => {
 | 
				
			||||||
 | 
					        emit('update:modelValue', monacoEditor.getModel().getValue());
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 动态设置主题
 | 
				
			||||||
 | 
					    // monaco.editor.setTheme('hc-black');
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const changeLanguage = (value: any) => {
 | 
				
			||||||
 | 
					    console.log('change lan');
 | 
				
			||||||
 | 
					    // 获取当前的文档模型
 | 
				
			||||||
 | 
					    let oldModel = monacoEditor.getModel()
 | 
				
			||||||
 | 
					    // 创建一个新的文档模型
 | 
				
			||||||
 | 
					    let newModel = monaco.editor.createModel(oldModel.getValue(), value)
 | 
				
			||||||
 | 
					    // 设置成新的
 | 
				
			||||||
 | 
					    monacoEditor.setModel(newModel)
 | 
				
			||||||
 | 
					    // 销毁旧的模型
 | 
				
			||||||
 | 
					    if (oldModel) {
 | 
				
			||||||
 | 
					        oldModel.dispose()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const setEditorValue = (value: any) => {
 | 
				
			||||||
 | 
					    monacoEditor.getModel().setValue(value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
					.monaco-editor {
 | 
				
			||||||
 | 
					    .code-mode-select {
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        z-index: 2;
 | 
				
			||||||
 | 
					        right: 10px;
 | 
				
			||||||
 | 
					        top: 10px;
 | 
				
			||||||
 | 
					        max-width: 130px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@@ -87,10 +87,11 @@
 | 
				
			|||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                <div style="float: right" class="fl">
 | 
					                                <div style="float: right" class="fl">
 | 
				
			||||||
                                    <el-select v-model="monacoOptions.theme" placeholder="切换编辑器主题" @change="changeEditorTheme"
 | 
					                                    <el-select v-model="monacoOptions.theme" placeholder="切换编辑器主题"
 | 
				
			||||||
                                               filterable allow-create default-first-option size="small" class="mr10">
 | 
					                                        @change="changeEditorTheme" filterable allow-create default-first-option
 | 
				
			||||||
                                        <el-option v-for="item in monacoOptions.defaultThemes as string" :key="item" :label="item"
 | 
					                                        size="small" class="mr10">
 | 
				
			||||||
                                                   :value="item">
 | 
					                                        <el-option v-for="item in monacoOptions.defaultThemes as string" :key="item"
 | 
				
			||||||
 | 
					                                            :label="item" :value="item">
 | 
				
			||||||
                                            {{ item }}
 | 
					                                            {{ item }}
 | 
				
			||||||
                                        </el-option>
 | 
					                                        </el-option>
 | 
				
			||||||
                                    </el-select>
 | 
					                                    </el-select>
 | 
				
			||||||
@@ -114,7 +115,9 @@
 | 
				
			|||||||
                            <div ref="monacoTextarea" :style="{ height: monacoOptions.height }"></div>
 | 
					                            <div ref="monacoTextarea" :style="{ height: monacoOptions.height }"></div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="editor-move-resize" @mousedown="onDragSetHeight">
 | 
					                        <div class="editor-move-resize" @mousedown="onDragSetHeight">
 | 
				
			||||||
                            <el-icon><Minus /></el-icon>
 | 
					                            <el-icon>
 | 
				
			||||||
 | 
					                                <Minus />
 | 
				
			||||||
 | 
					                            </el-icon>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="mt5">
 | 
					                        <div class="mt5">
 | 
				
			||||||
                            <el-row>
 | 
					                            <el-row>
 | 
				
			||||||
@@ -129,8 +132,8 @@
 | 
				
			|||||||
                            </el-row>
 | 
					                            </el-row>
 | 
				
			||||||
                            <el-table @cell-dblclick="cellClick" @selection-change="onDataSelectionChange"
 | 
					                            <el-table @cell-dblclick="cellClick" @selection-change="onDataSelectionChange"
 | 
				
			||||||
                                :data="queryTab.execRes.data" v-loading="queryTab.loading" element-loading-text="查询中..."
 | 
					                                :data="queryTab.execRes.data" v-loading="queryTab.loading" element-loading-text="查询中..."
 | 
				
			||||||
                                size="small" :max-height="monacoOptions.tableMaxHeight" empty-text="tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改"
 | 
					                                size="small" :max-height="monacoOptions.tableMaxHeight"
 | 
				
			||||||
                                stripe border class="mt5">
 | 
					                                empty-text="tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改" stripe border class="mt5">
 | 
				
			||||||
                                <el-table-column v-if="queryTab.execRes.tableColumn.length > 0 && queryTab.nowTableName"
 | 
					                                <el-table-column v-if="queryTab.execRes.tableColumn.length > 0 && queryTab.nowTableName"
 | 
				
			||||||
                                    type="selection" width="35" />
 | 
					                                    type="selection" width="35" />
 | 
				
			||||||
                                <el-table-column min-width="100" :width="flexColumnWidth(item, queryTab.execRes.data)"
 | 
					                                <el-table-column min-width="100" :width="flexColumnWidth(item, queryTab.execRes.data)"
 | 
				
			||||||
@@ -271,23 +274,23 @@ import {editor, languages, Position} from 'monaco-editor';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 主题仓库 https://github.com/brijeshb42/monaco-themes 
 | 
					// 主题仓库 https://github.com/brijeshb42/monaco-themes 
 | 
				
			||||||
// 主题例子 https://editor.bitwiser.in/
 | 
					// 主题例子 https://editor.bitwiser.in/
 | 
				
			||||||
import Monokai from 'monaco-themes/themes/Monokai.json'
 | 
					// import Monokai from 'monaco-themes/themes/Monokai.json'
 | 
				
			||||||
import Active4D from 'monaco-themes/themes/Active4D.json'
 | 
					// import Active4D from 'monaco-themes/themes/Active4D.json'
 | 
				
			||||||
import ahe from 'monaco-themes/themes/All Hallows Eve.json'
 | 
					// import ahe from 'monaco-themes/themes/All Hallows Eve.json'
 | 
				
			||||||
import bop from 'monaco-themes/themes/Birds of Paradise.json'
 | 
					// import bop from 'monaco-themes/themes/Birds of Paradise.json'
 | 
				
			||||||
import krTheme from 'monaco-themes/themes/krTheme.json'
 | 
					// import krTheme from 'monaco-themes/themes/krTheme.json'
 | 
				
			||||||
import Dracula from 'monaco-themes/themes/Dracula.json'
 | 
					// import Dracula from 'monaco-themes/themes/Dracula.json'
 | 
				
			||||||
import TextmateMac from 'monaco-themes/themes/Textmate (Mac Classic).json'
 | 
					import SolarizedLight from 'monaco-themes/themes/Solarized-light.json'
 | 
				
			||||||
 | 
					// import TextmateMac from 'monaco-themes/themes/Textmate (Mac Classic).json'
 | 
				
			||||||
import { Minus } from '@element-plus/icons-vue';
 | 
					import { Minus } from '@element-plus/icons-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const store = useStore();
 | 
					const store = useStore();
 | 
				
			||||||
const monacoTextarea: any = ref(null);
 | 
					const monacoTextarea: any = ref(null);
 | 
				
			||||||
const token = getSession('token');
 | 
					const token = getSession('token');
 | 
				
			||||||
const tableMap = new Map();
 | 
					const tableMap = new Map();
 | 
				
			||||||
 | 
					 | 
				
			||||||
const defalutLimit = 20
 | 
					const defalutLimit = 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type TableMeta = {
 | 
					type TableMeta = {
 | 
				
			||||||
    // 表名
 | 
					    // 表名
 | 
				
			||||||
    tableName: string,
 | 
					    tableName: string,
 | 
				
			||||||
    // 表注释
 | 
					    // 表注释
 | 
				
			||||||
@@ -346,8 +349,8 @@ const state = reactive({
 | 
				
			|||||||
        height: '',
 | 
					        height: '',
 | 
				
			||||||
        tableMaxHeight: 250,
 | 
					        tableMaxHeight: 250,
 | 
				
			||||||
        dbTables: {},
 | 
					        dbTables: {},
 | 
				
			||||||
        theme:'',
 | 
					        theme: 'SolarizedLight',
 | 
				
			||||||
        defaultThemes:[ 'vs' ,'vs-dark', 'hc-black', 'hc-light', 'Monokai', 'Active4D', 'ahe', 'bop', 'krTheme', 'Dracula', 'TextmateMac'],
 | 
					        defaultThemes: ['SolarizedLight', 'vs', 'vs-dark'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
const {
 | 
					const {
 | 
				
			||||||
@@ -383,12 +386,20 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
    console.log('初始化编辑器')
 | 
					    console.log('初始化编辑器')
 | 
				
			||||||
    // options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language
 | 
					    // options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let defVal = `-- monaco editor`;
 | 
					    // 初始化一些主题
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    monaco.editor.defineTheme('SolarizedLight', SolarizedLight);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('Monokai', Monokai);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('Active4D', Active4D);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('ahe', ahe);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('bop', bop);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('krTheme', krTheme);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('Dracula', Dracula);
 | 
				
			||||||
 | 
					    // monaco.editor.defineTheme('TextmateMac', TextmateMac);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monacoEditor = monaco.editor.create(monacoTextarea.value, {
 | 
					    monacoEditor = monaco.editor.create(monacoTextarea.value, {
 | 
				
			||||||
        value: defVal,
 | 
					 | 
				
			||||||
        language: 'sql',
 | 
					        language: 'sql',
 | 
				
			||||||
        theme: 'vs',
 | 
					        theme: state.monacoOptions.theme,
 | 
				
			||||||
        automaticLayout: true, //自适应宽高布局
 | 
					        automaticLayout: true, //自适应宽高布局
 | 
				
			||||||
        foldingStrategy: 'indentation',//代码可分小段折叠
 | 
					        foldingStrategy: 'indentation',//代码可分小段折叠
 | 
				
			||||||
        roundedSelection: false, // 禁用选择文本背景的圆角
 | 
					        roundedSelection: false, // 禁用选择文本背景的圆角
 | 
				
			||||||
@@ -398,7 +409,8 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
        mouseWheelZoom: true, // 在按住Ctrl键的同时使用鼠标滚轮时,在编辑器中缩放字体
 | 
					        mouseWheelZoom: true, // 在按住Ctrl键的同时使用鼠标滚轮时,在编辑器中缩放字体
 | 
				
			||||||
        overviewRulerBorder: false, // 不要滚动条的边框
 | 
					        overviewRulerBorder: false, // 不要滚动条的边框
 | 
				
			||||||
        tabSize: 2, // tab 缩进长度
 | 
					        tabSize: 2, // tab 缩进长度
 | 
				
			||||||
        // fontFamily:'consolas', // 字体 暂时不要设置,否则光标容易错位
 | 
					        fontFamily: 'JetBrainsMono', // 字体 暂时不要设置,否则光标容易错位
 | 
				
			||||||
 | 
					        fontWeight: 'bold',
 | 
				
			||||||
        // letterSpacing: 1, 字符间距
 | 
					        // letterSpacing: 1, 字符间距
 | 
				
			||||||
        // quickSuggestions:false, // 禁用代码提示
 | 
					        // quickSuggestions:false, // 禁用代码提示
 | 
				
			||||||
        minimap: {
 | 
					        minimap: {
 | 
				
			||||||
@@ -406,15 +418,6 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 初始化一些主题
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('Monokai', Monokai);
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('Active4D', Active4D);
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('ahe', ahe);
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('bop', bop);
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('krTheme', krTheme);
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('Dracula', Dracula);
 | 
					 | 
				
			||||||
    monaco.editor.defineTheme('TextmateMac', TextmateMac);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // 动态设置主题
 | 
					    // 动态设置主题
 | 
				
			||||||
    // monaco.editor.setTheme('hc-black');
 | 
					    // monaco.editor.setTheme('hc-black');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -466,9 +469,9 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
            const tokens = textBeforePointer.trim().split(/\s+/)
 | 
					            const tokens = textBeforePointer.trim().split(/\s+/)
 | 
				
			||||||
            const lastToken = tokens[tokens.length - 1].toLowerCase()
 | 
					            const lastToken = tokens[tokens.length - 1].toLowerCase()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            console.log("光标前文本:=>" + textBeforePointerMulti)
 | 
					            // console.log("光标前文本:=>" + textBeforePointerMulti)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            console.log("最后输入的:=>" + lastToken)
 | 
					            // console.log("最后输入的:=>" + lastToken)
 | 
				
			||||||
            if (lastToken.endsWith('.')) {
 | 
					            if (lastToken.endsWith('.')) {
 | 
				
			||||||
                // 如果是.触发代码提示,则进行【 库.表名联想 】 或 【 表别名.表字段联想 】
 | 
					                // 如果是.触发代码提示,则进行【 库.表名联想 】 或 【 表别名.表字段联想 】
 | 
				
			||||||
                let str = lastToken.substring(0, lastToken.lastIndexOf('.'))
 | 
					                let str = lastToken.substring(0, lastToken.lastIndexOf('.'))
 | 
				
			||||||
@@ -496,29 +499,27 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
                    let db = tableInfo.dbName
 | 
					                    let db = tableInfo.dbName
 | 
				
			||||||
                    // 取出表名并提示
 | 
					                    // 取出表名并提示
 | 
				
			||||||
                    let dbs = state.monacoOptions.dbTables[db]
 | 
					                    let dbs = state.monacoOptions.dbTables[db]
 | 
				
			||||||
                    let tables = dbs ? (dbs[table] || []) : [];
 | 
					                    let columns = dbs ? (dbs[table] || []) : [];
 | 
				
			||||||
                    if((!tables || tables.length === 0) && db){
 | 
					                    if ((!columns || columns.length === 0) && db) {
 | 
				
			||||||
                        state.monacoOptions.dbTables[db] = await loadHintTables(db)
 | 
					                        state.monacoOptions.dbTables[db] = await loadHintTables(db)
 | 
				
			||||||
                        dbs = state.monacoOptions.dbTables[db]
 | 
					                        dbs = state.monacoOptions.dbTables[db]
 | 
				
			||||||
                        tables = dbs ? (dbs[table] || []) : [];
 | 
					                        columns = dbs ? (dbs[table] || []) : [];
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    tables.sort()
 | 
					 | 
				
			||||||
                    let suggestions: languages.CompletionItem[] = []
 | 
					                    let suggestions: languages.CompletionItem[] = []
 | 
				
			||||||
                    tables.forEach((a:string)=>{
 | 
					                    columns.forEach((a: string, index: any) => {
 | 
				
			||||||
                        // 字段数据格式  字段名 字段注释,  如: create_time  [datetime][创建时间]
 | 
					                        // 字段数据格式  字段名 字段注释,  如: create_time  [datetime][创建时间]
 | 
				
			||||||
                        let fieldName = a.substring(0,a.indexOf(" "))
 | 
					                        const nameAndComment = a.split("  ")
 | 
				
			||||||
                        let comment = a.replace(eval(`/${fieldName}\\s+/`), '')
 | 
					                        const fieldName = nameAndComment[0]
 | 
				
			||||||
                        let detail = fieldName + ( comment?' - ' + comment :'' )
 | 
					 | 
				
			||||||
                        suggestions.push({
 | 
					                        suggestions.push({
 | 
				
			||||||
                            label: detail,
 | 
					                            label: a,  // [datetime][创建时间]
 | 
				
			||||||
                            kind: monaco.languages.CompletionItemKind.Property,
 | 
					                            kind: monaco.languages.CompletionItemKind.Property,
 | 
				
			||||||
                            detail: detail,
 | 
					                            detail: '', // 不显示detail, 否则选中时备注等会被遮挡
 | 
				
			||||||
                            insertText: fieldName,
 | 
					                            insertText: fieldName + ' ', // create_time 
 | 
				
			||||||
                            range
 | 
					                            range,
 | 
				
			||||||
 | 
					                            sortText: 100 + index + '' // 使用表字段声明顺序排序
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    return { suggestions }
 | 
					                    return { suggestions }
 | 
				
			||||||
                    // 
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return { suggestions: [] }
 | 
					                return { suggestions: [] }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -580,7 +581,7 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
                    label: tableName + ' - ' + tableComment,
 | 
					                    label: tableName + ' - ' + tableComment,
 | 
				
			||||||
                    kind: monaco.languages.CompletionItemKind.File,
 | 
					                    kind: monaco.languages.CompletionItemKind.File,
 | 
				
			||||||
                    detail: tableComment,
 | 
					                    detail: tableComment,
 | 
				
			||||||
                    insertText: tableName,
 | 
					                    insertText: tableName + ' ',
 | 
				
			||||||
                    range
 | 
					                    range
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
@@ -591,7 +592,6 @@ const initMonacoEditor = () => {
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -652,7 +652,7 @@ onMounted(() => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 设置codemirror高度和数据表高度
 | 
					 * 设置editor高度和数据表高度
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const setHeight = () => {
 | 
					const setHeight = () => {
 | 
				
			||||||
    // 默认300px
 | 
					    // 默认300px
 | 
				
			||||||
@@ -663,7 +663,7 @@ const setHeight = () => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * 拖拽改变sql编辑区和查询结果区高度
 | 
					 * 拖拽改变sql编辑区和查询结果区高度
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const onDragSetHeight = (e: any) => {
 | 
					const onDragSetHeight = () => {
 | 
				
			||||||
    document.onmousemove = (e) => {
 | 
					    document.onmousemove = (e) => {
 | 
				
			||||||
        e.preventDefault();
 | 
					        e.preventDefault();
 | 
				
			||||||
        //得到鼠标拖动的宽高距离:取绝对值
 | 
					        //得到鼠标拖动的宽高距离:取绝对值
 | 
				
			||||||
@@ -1195,6 +1195,7 @@ const onTableSortChange = async (sort: any) => {
 | 
				
			|||||||
const changeSqlTemplate = () => {
 | 
					const changeSqlTemplate = () => {
 | 
				
			||||||
    getUserSql();
 | 
					    getUserSql();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const changeEditorTheme = () => {
 | 
					const changeEditorTheme = () => {
 | 
				
			||||||
    monaco.editor.setTheme(state.monacoOptions.theme);
 | 
					    monaco.editor.setTheme(state.monacoOptions.theme);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -1217,10 +1218,6 @@ const setSqlEditorValue = (value: string) => {
 | 
				
			|||||||
    monacoEditor.getModel()?.setValue(value);
 | 
					    monacoEditor.getModel()?.setValue(value);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getCodermirrorValue = () => {
 | 
					 | 
				
			||||||
    return codemirror.getValue();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 获取用户保存的sql模板名称
 | 
					 * 获取用户保存的sql模板名称
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -1466,13 +1463,49 @@ const addRow = async () => {
 | 
				
			|||||||
 * 格式化sql
 | 
					 * 格式化sql
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const formatSql = () => {
 | 
					const formatSql = () => {
 | 
				
			||||||
    let selectSql = getSql();
 | 
					    let selection = monacoEditor.getSelection()
 | 
				
			||||||
    if(selectSql){
 | 
					    let sql = monacoEditor.getModel()?.getValueInRange(selection)
 | 
				
			||||||
        monacoEditor.getModel()?.setValue(sqlFormatter(selectSql))
 | 
					    // 有选中sql则格式化并替换选中sql, 否则格式化编辑器所有内容
 | 
				
			||||||
 | 
					    if (sql) {
 | 
				
			||||||
 | 
					        replaceSelection(sqlFormatter(sql), selection)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    monacoEditor.getModel()?.setValue(sqlFormatter(monacoEditor.getValue()));
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 替换选中的内容
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const replaceSelection = (str: string, selection: any) => {
 | 
				
			||||||
 | 
					    if (!selection) {
 | 
				
			||||||
 | 
					        monacoEditor.getModel().setValue(str);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const { startLineNumber, endLineNumber, startColumn, endColumn } = selection
 | 
				
			||||||
 | 
					    const model = monacoEditor.getModel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const textBeforeSelection = model.getValueInRange({
 | 
				
			||||||
 | 
					        startLineNumber: 1,
 | 
				
			||||||
 | 
					        startColumn: 0,
 | 
				
			||||||
 | 
					        endLineNumber: startLineNumber,
 | 
				
			||||||
 | 
					        endColumn: startColumn,
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const textAfterSelection = model.getValueInRange({
 | 
				
			||||||
 | 
					        startLineNumber: endLineNumber,
 | 
				
			||||||
 | 
					        startColumn: endColumn,
 | 
				
			||||||
 | 
					        endLineNumber: model.getLineCount(),
 | 
				
			||||||
 | 
					        endColumn: model.getLineMaxColumn(model.getLineCount()),
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    monacoEditor.setValue(textBeforeSelection + str + textAfterSelection)
 | 
				
			||||||
 | 
					    monacoEditor.focus()
 | 
				
			||||||
 | 
					    monacoEditor.setPosition({
 | 
				
			||||||
 | 
					        lineNumber: startLineNumber,
 | 
				
			||||||
 | 
					        column: 0,
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    const res = await dbApi.dbs.request(state.params);
 | 
					    const res = await dbApi.dbs.request(state.params);
 | 
				
			||||||
    state.dbs = res.list;
 | 
					    state.dbs = res.list;
 | 
				
			||||||
@@ -1515,17 +1548,6 @@ watch(store.state.sqlExecInfo, async (newValue) => {
 | 
				
			|||||||
    font-size: 8pt;
 | 
					    font-size: 8pt;
 | 
				
			||||||
    font-weight: 600;
 | 
					    font-weight: 600;
 | 
				
			||||||
    border: 1px solid #ccc;
 | 
					    border: 1px solid #ccc;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    .CodeMirror {
 | 
					 | 
				
			||||||
        flex-grow: 1;
 | 
					 | 
				
			||||||
        z-index: 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        .CodeMirror-code {
 | 
					 | 
				
			||||||
            line-height: 19px;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        font-family: 'JetBrainsMono';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.editor-move-resize {
 | 
					.editor-move-resize {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,7 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <el-dialog title="待执行SQL" v-model="dialogVisible" :show-close="false" width="600px" @close="cancel">
 | 
					        <el-dialog :destroy-on-close="true" title="待执行SQL" v-model="dialogVisible" :show-close="false" width="600px" @close="cancel">
 | 
				
			||||||
            <codemirror height="350px" class="codesql" ref="cmEditor" language="sql" v-model="sqlValue"
 | 
					            <monaco-editor height="300px" class="codesql" language="sql" v-model="sqlValue" />
 | 
				
			||||||
                :options="cmOptions" />
 | 
					 | 
				
			||||||
            <el-input ref="remarkInputRef" v-model="remark" placeholder="请输入执行备注" class="mt5" />
 | 
					            <el-input ref="remarkInputRef" v-model="remark" placeholder="请输入执行备注" class="mt5" />
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <span class="dialog-footer">
 | 
					                <span class="dialog-footer">
 | 
				
			||||||
@@ -19,11 +18,7 @@ import { toRefs, ref, nextTick, reactive } from 'vue';
 | 
				
			|||||||
import { dbApi } from '../api';
 | 
					import { dbApi } from '../api';
 | 
				
			||||||
import { ElDialog, ElButton, ElInput, ElMessage, InputInstance } from 'element-plus';
 | 
					import { ElDialog, ElButton, ElInput, ElMessage, InputInstance } from 'element-plus';
 | 
				
			||||||
// import base style
 | 
					// import base style
 | 
				
			||||||
import 'codemirror/lib/codemirror.css';
 | 
					import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
 | 
				
			||||||
// 引入主题后还需要在 options 中指定主题才会生效
 | 
					 | 
				
			||||||
import 'codemirror/theme/base16-light.css';
 | 
					 | 
				
			||||||
import 'codemirror/addon/selection/active-line';
 | 
					 | 
				
			||||||
import { codemirror } from '@/components/codemirror';
 | 
					 | 
				
			||||||
import { format as sqlFormatter } from 'sql-formatter';
 | 
					import { format as sqlFormatter } from 'sql-formatter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { SqlExecProps } from './SqlExecBox';
 | 
					import { SqlExecProps } from './SqlExecBox';
 | 
				
			||||||
@@ -43,19 +38,6 @@ const props = defineProps({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const cmOptions = {
 | 
					 | 
				
			||||||
    tabSize: 4,
 | 
					 | 
				
			||||||
    mode: 'text/x-sql',
 | 
					 | 
				
			||||||
    lineNumbers: true,
 | 
					 | 
				
			||||||
    line: true,
 | 
					 | 
				
			||||||
    indentWithTabs: true,
 | 
					 | 
				
			||||||
    smartIndent: true,
 | 
					 | 
				
			||||||
    matchBrackets: true,
 | 
					 | 
				
			||||||
    theme: 'base16-light',
 | 
					 | 
				
			||||||
    autofocus: true,
 | 
					 | 
				
			||||||
    extraKeys: { Tab: 'autocomplete' }, // 自定义快捷键
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const remarkInputRef = ref<InputInstance>();
 | 
					const remarkInputRef = ref<InputInstance>();
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    dialogVisible: false,
 | 
					    dialogVisible: false,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,11 +148,10 @@
 | 
				
			|||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <el-dialog :destroy-on-close="true" :title="fileContent.dialogTitle" v-model="fileContent.contentVisible"
 | 
					        <el-dialog :destroy-on-close="true" :title="fileContent.dialogTitle" v-model="fileContent.contentVisible" :close-on-click-modal="false"
 | 
				
			||||||
            :close-on-click-modal="false" top="5vh" width="70%">
 | 
					            top="5vh" width="70%">
 | 
				
			||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
                <codemirror :can-change-mode="true" ref="cmEditor" v-model="fileContent.content"
 | 
					                <monaco-editor :can-change-mode="true" v-model="fileContent.content" :language="fileContent.type" />
 | 
				
			||||||
                    :language="fileContent.type" />
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
@@ -170,7 +169,7 @@ import { ref, toRefs, reactive, watch } from 'vue';
 | 
				
			|||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import { machineApi } from './api';
 | 
					import { machineApi } from './api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { codemirror } from '@/components/codemirror';
 | 
					import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
 | 
				
			||||||
import { getSession } from '@/common/utils/storage';
 | 
					import { getSession } from '@/common/utils/storage';
 | 
				
			||||||
import enums from './enums';
 | 
					import enums from './enums';
 | 
				
			||||||
import config from '@/common/config';
 | 
					import config from '@/common/config';
 | 
				
			||||||
@@ -343,14 +342,17 @@ const getFileType = (path: string) => {
 | 
				
			|||||||
    if (path.endsWith('.sh')) {
 | 
					    if (path.endsWith('.sh')) {
 | 
				
			||||||
        return 'shell';
 | 
					        return 'shell';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (path.endsWith('js') || path.endsWith('json')) {
 | 
					    if (path.endsWith('js')) {
 | 
				
			||||||
        return 'javascript';
 | 
					        return 'javascript';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (path.endsWith('json')) {
 | 
				
			||||||
 | 
					        return 'json';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (path.endsWith('Dockerfile')) {
 | 
					    if (path.endsWith('Dockerfile')) {
 | 
				
			||||||
        return 'dockerfile';
 | 
					        return 'dockerfile';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (path.endsWith('nginx.conf')) {
 | 
					    if (path.endsWith('nginx.conf')) {
 | 
				
			||||||
        return 'nginx';
 | 
					        return 'shell';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (path.endsWith('sql')) {
 | 
					    if (path.endsWith('sql')) {
 | 
				
			||||||
        return 'sql';
 | 
					        return 'sql';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,9 +45,7 @@
 | 
				
			|||||||
                    </el-row>
 | 
					                    </el-row>
 | 
				
			||||||
                </el-form-item>
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <el-form-item prop="script" label="内容" id="content">
 | 
					                <monaco-editor v-model="form.script" language="shell" height="300px" />
 | 
				
			||||||
                    <codemirror ref="cmEditor" v-model="form.script" language="shell" width="700px" />
 | 
					 | 
				
			||||||
                </el-form-item>
 | 
					 | 
				
			||||||
            </el-form>
 | 
					            </el-form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
@@ -67,8 +65,7 @@ import { ElMessage } from 'element-plus';
 | 
				
			|||||||
import { machineApi } from './api';
 | 
					import { machineApi } from './api';
 | 
				
			||||||
import enums from './enums';
 | 
					import enums from './enums';
 | 
				
			||||||
import { notEmpty } from '@/common/assert';
 | 
					import { notEmpty } from '@/common/assert';
 | 
				
			||||||
 | 
					import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
 | 
				
			||||||
import { codemirror } from '@/components/codemirror';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
    visible: {
 | 
					    visible: {
 | 
				
			||||||
@@ -176,9 +173,5 @@ const cancel = () => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<style lang="scss">
 | 
					<style lang="scss">
 | 
				
			||||||
#content {
 | 
					
 | 
				
			||||||
    .CodeMirror {
 | 
					 | 
				
			||||||
        height: 300px !important;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,7 +54,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, watch, defineComponent } from 'vue';
 | 
					import { ref, toRefs, reactive, watch } from 'vue';
 | 
				
			||||||
import { configApi } from '../api';
 | 
					import { configApi } from '../api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,6 +96,11 @@
 | 
				
			|||||||
  resolved "https://registry.npmmirror.com/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz"
 | 
					  resolved "https://registry.npmmirror.com/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz"
 | 
				
			||||||
  integrity sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==
 | 
					  integrity sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/antlr4@4.7.0":
 | 
				
			||||||
 | 
					  version "4.7.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/@types/antlr4/-/antlr4-4.7.0.tgz#e6300119bddff6e23f5bbd299f5cf3c722a6249b"
 | 
				
			||||||
 | 
					  integrity sha512-WdyHH4PHxBQkeWoRTbuC/dvf0QErJpJE4UpESQSRmKoMER15DCLFHAHQjkwevMKQie0kqawS/eTY563GGMbz/g==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/json-schema@^7.0.7":
 | 
					"@types/json-schema@^7.0.7":
 | 
				
			||||||
  version "7.0.9"
 | 
					  version "7.0.9"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/@types/json-schema/download/@types/json-schema-7.0.9.tgz?cache=0&sync_timestamp=1637266073261&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fjson-schema%2Fdownload%2F%40types%2Fjson-schema-7.0.9.tgz"
 | 
					  resolved "https://registry.npmmirror.com/@types/json-schema/download/@types/json-schema-7.0.9.tgz?cache=0&sync_timestamp=1637266073261&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fjson-schema%2Fdownload%2F%40types%2Fjson-schema-7.0.9.tgz"
 | 
				
			||||||
@@ -435,6 +440,11 @@ ansi-styles@^4.1.0:
 | 
				
			|||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    color-convert "^2.0.1"
 | 
					    color-convert "^2.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					antlr4@4.7.2:
 | 
				
			||||||
 | 
					  version "4.7.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/antlr4/-/antlr4-4.7.2.tgz#9d0b5987bb63660de658055ee9149141b4d9b462"
 | 
				
			||||||
 | 
					  integrity sha512-vZA1xYufXLe3LX+ja9rIVxjRmILb1x3k7KYZHltRbfJtXjJ1DlFIqt+CbPYmghx0EuzY9DajiDw+MdyEt1qAsQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
anymatch@~3.1.2:
 | 
					anymatch@~3.1.2:
 | 
				
			||||||
  version "3.1.2"
 | 
					  version "3.1.2"
 | 
				
			||||||
  resolved "https://registry.nlark.com/anymatch/download/anymatch-3.1.2.tgz"
 | 
					  resolved "https://registry.nlark.com/anymatch/download/anymatch-3.1.2.tgz"
 | 
				
			||||||
@@ -542,11 +552,6 @@ clipboard@^2.0.6:
 | 
				
			|||||||
    select "^1.1.2"
 | 
					    select "^1.1.2"
 | 
				
			||||||
    tiny-emitter "^2.0.0"
 | 
					    tiny-emitter "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
codemirror@^5.65.5:
 | 
					 | 
				
			||||||
  version "5.65.5"
 | 
					 | 
				
			||||||
  resolved "https://registry.npmmirror.com/codemirror/-/codemirror-5.65.5.tgz"
 | 
					 | 
				
			||||||
  integrity sha512-HNyhvGLnYz5c+kIsB9QKVitiZUevha3ovbIYaQiGzKo7ECSL/elWD9RXt3JgNr0NdnyqE9/Rc/7uLfkJQL638w==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
color-convert@^2.0.1:
 | 
					color-convert@^2.0.1:
 | 
				
			||||||
  version "2.0.1"
 | 
					  version "2.0.1"
 | 
				
			||||||
  resolved "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz"
 | 
					  resolved "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz"
 | 
				
			||||||
@@ -646,6 +651,14 @@ dotenv@^10.0.0:
 | 
				
			|||||||
  resolved "https://registry.nlark.com/dotenv/download/dotenv-10.0.0.tgz"
 | 
					  resolved "https://registry.nlark.com/dotenv/download/dotenv-10.0.0.tgz"
 | 
				
			||||||
  integrity sha1-PUInuPuV+BCWzdK2ZlP7LHCFuoE=
 | 
					  integrity sha1-PUInuPuV+BCWzdK2ZlP7LHCFuoE=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dt-sql-parser@^4.0.0-beta.2.2:
 | 
				
			||||||
 | 
					  version "4.0.0-beta.2.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/dt-sql-parser/-/dt-sql-parser-4.0.0-beta.2.2.tgz#84fbed385afc19ca6464cd266889e3f52e73083a"
 | 
				
			||||||
 | 
					  integrity sha512-LLAE659zgizdokkDniHFPk0PsLPV3cXFOQPW+QT+3W1/TQJ2h8yzKCBBufXmKAHMpAr+KjTRTa71VJRzWJx8Zg==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@types/antlr4" "4.7.0"
 | 
				
			||||||
 | 
					    antlr4 "4.7.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echarts@^5.3.3:
 | 
					echarts@^5.3.3:
 | 
				
			||||||
  version "5.3.3"
 | 
					  version "5.3.3"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.3.tgz"
 | 
					  resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.3.tgz"
 | 
				
			||||||
@@ -982,6 +995,11 @@ fast-levenshtein@^2.0.6:
 | 
				
			|||||||
  resolved "https://registry.nlark.com/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz"
 | 
					  resolved "https://registry.nlark.com/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz"
 | 
				
			||||||
  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 | 
					  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fast-plist@^0.1.2:
 | 
				
			||||||
 | 
					  version "0.1.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/fast-plist/-/fast-plist-0.1.2.tgz#a45aff345196006d406ca6cdcd05f69051ef35b8"
 | 
				
			||||||
 | 
					  integrity sha512-2HxzrqJhmMoxVzARjYFvkzkL2dCBB8sogU5sD8gqcZWv5UCivK9/cXM9KIPDRwU+eD3mbRDN/GhW8bO/4dtMfg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fastq@^1.6.0:
 | 
					fastq@^1.6.0:
 | 
				
			||||||
  version "1.13.0"
 | 
					  version "1.13.0"
 | 
				
			||||||
  resolved "https://registry.nlark.com/fastq/download/fastq-1.13.0.tgz"
 | 
					  resolved "https://registry.nlark.com/fastq/download/fastq-1.13.0.tgz"
 | 
				
			||||||
@@ -1342,6 +1360,25 @@ mobius1-selectr@^2.4.13:
 | 
				
			|||||||
  resolved "https://registry.npmmirror.com/mobius1-selectr/-/mobius1-selectr-2.4.13.tgz"
 | 
					  resolved "https://registry.npmmirror.com/mobius1-selectr/-/mobius1-selectr-2.4.13.tgz"
 | 
				
			||||||
  integrity sha512-Mk9qDrvU44UUL0EBhbAA1phfQZ7aMZPjwtL7wkpiBzGh8dETGqfsh50mWoX9EkjDlkONlErWXArHCKfoxVg0Bw==
 | 
					  integrity sha512-Mk9qDrvU44UUL0EBhbAA1phfQZ7aMZPjwtL7wkpiBzGh8dETGqfsh50mWoX9EkjDlkONlErWXArHCKfoxVg0Bw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					monaco-editor@^0.34.1:
 | 
				
			||||||
 | 
					  version "0.34.1"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.34.1.tgz#1b75c4ad6bc4c1f9da656d740d98e0b850a22f87"
 | 
				
			||||||
 | 
					  integrity sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					monaco-sql-languages@^0.9.5:
 | 
				
			||||||
 | 
					  version "0.9.5"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/monaco-sql-languages/-/monaco-sql-languages-0.9.5.tgz#075ffe947e66f0dc7a53f92cb99c2d4649632a34"
 | 
				
			||||||
 | 
					  integrity sha512-IBIKQVIoW1Q90pJ/0Qi0sWMgbvho5ug17wx64hVid/XCr+L7ngJaTdaRnveOMPwg9qj+PQqOt1Ga0q0AwG85wA==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    dt-sql-parser "^4.0.0-beta.2.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					monaco-themes@^0.4.2:
 | 
				
			||||||
 | 
					  version "0.4.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmmirror.com/monaco-themes/-/monaco-themes-0.4.2.tgz#6939339cb2f0bfb743f6e454de4136971834f16a"
 | 
				
			||||||
 | 
					  integrity sha512-T3kp6SC5MPJvwYGXZENCd0UOIKVgUVV5SjsiXLBhgEZBnScY+6gEbwNRK1oYmfwbf+dGVqF1bSLN5YcrFu3HmA==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    fast-plist "^0.1.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ms@2.1.2:
 | 
					ms@2.1.2:
 | 
				
			||||||
  version "2.1.2"
 | 
					  version "2.1.2"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/ms/download/ms-2.1.2.tgz"
 | 
					  resolved "https://registry.npmmirror.com/ms/download/ms-2.1.2.tgz"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package api
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"mayfly-go/pkg/biz"
 | 
						"mayfly-go/pkg/biz"
 | 
				
			||||||
	"mayfly-go/pkg/ctx"
 | 
						"mayfly-go/pkg/ctx"
 | 
				
			||||||
 | 
						"mayfly-go/pkg/global"
 | 
				
			||||||
	"mayfly-go/pkg/ws"
 | 
						"mayfly-go/pkg/ws"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
@@ -17,9 +18,12 @@ func (s *System) ConnectWs(g *gin.Context) {
 | 
				
			|||||||
	wsConn, err := ws.Upgrader.Upgrade(g.Writer, g.Request, nil)
 | 
						wsConn, err := ws.Upgrader.Upgrade(g.Writer, g.Request, nil)
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		if err := recover(); err != nil {
 | 
							if err := recover(); err != nil {
 | 
				
			||||||
 | 
								global.Log.Error(err.(error).Error())
 | 
				
			||||||
 | 
								if wsConn != nil {
 | 
				
			||||||
				wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error()))
 | 
									wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error()))
 | 
				
			||||||
				wsConn.Close()
 | 
									wsConn.Close()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user