mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	refactor: monaco编辑器按需加载
This commit is contained in:
		@@ -31,11 +31,11 @@
 | 
			
		||||
    "vue": "^3.3.4",
 | 
			
		||||
    "vue-clipboard3": "^1.0.1",
 | 
			
		||||
    "vue-router": "^4.2.4",
 | 
			
		||||
    "xterm": "^5.2.1",
 | 
			
		||||
    "xterm-addon-fit": "^0.7.0",
 | 
			
		||||
    "xterm-addon-search": "^0.12.0",
 | 
			
		||||
    "xterm-addon-web-links": "^0.8.0",
 | 
			
		||||
    "xterm-addon-webgl": "^0.15.0"
 | 
			
		||||
    "xterm": "^5.3.0",
 | 
			
		||||
    "xterm-addon-fit": "^0.8.0",
 | 
			
		||||
    "xterm-addon-search": "^0.13.0",
 | 
			
		||||
    "xterm-addon-web-links": "^0.9.0",
 | 
			
		||||
    "xterm-addon-webgl": "^0.16.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/lodash": "^4.14.178",
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,32 @@
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { ref, watch, toRefs, reactive, onMounted, onBeforeUnmount } from 'vue';
 | 
			
		||||
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
 | 
			
		||||
import * as monaco from 'monaco-editor';
 | 
			
		||||
// import * as monaco from 'monaco-editor';
 | 
			
		||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
 | 
			
		||||
// 相关语言
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/shell/shell.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/dockerfile/dockerfile.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/html/html.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/css/css.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/python/python.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/markdown/markdown.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/java/java.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/language/json/monaco.contribution';
 | 
			
		||||
// 右键菜单
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/contextmenu/browser/contextmenu.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/caretOperations/browser/caretOperations.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/clipboard//browser/clipboard.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/find/browser/findController.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/format//browser/formatActions.js';
 | 
			
		||||
// 提示
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestController.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestInlineCompletions.js';
 | 
			
		||||
 | 
			
		||||
import { editor, languages } from 'monaco-editor';
 | 
			
		||||
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
 | 
			
		||||
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
 | 
			
		||||
// 主题仓库 https://github.com/brijeshb42/monaco-themes
 | 
			
		||||
// 主题例子 https://editor.bitwiser.in/
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-row>
 | 
			
		||||
            <el-col :span="4">
 | 
			
		||||
                <el-button type="primary" icon="plus" @click="addQueryTab({ id: nowDbInst.id, dbs: nowDbInst.databases }, state.db)" size="small"
 | 
			
		||||
                <el-button type="primary" icon="plus" @click="addQueryTab({ id: nowDbInst.id, dbs: nowDbInst.databases.split(' ') }, state.db)" size="small"
 | 
			
		||||
                    >新建查询</el-button
 | 
			
		||||
                >
 | 
			
		||||
            </el-col>
 | 
			
		||||
@@ -98,11 +98,6 @@
 | 
			
		||||
import { defineAsyncComponent, onMounted, reactive, ref, toRefs } from 'vue';
 | 
			
		||||
import { ElMessage } from 'element-plus';
 | 
			
		||||
 | 
			
		||||
import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/mysql/mysql.js';
 | 
			
		||||
import { language as addSqlLanguage } from './lang/mysql.js';
 | 
			
		||||
import * as monaco from 'monaco-editor';
 | 
			
		||||
import { editor, languages, Position } from 'monaco-editor';
 | 
			
		||||
 | 
			
		||||
import { DbInst, TabInfo, TabType } from './db';
 | 
			
		||||
import { TagTreeNode } from '../component/tag';
 | 
			
		||||
import TagTree from '../component/TagTree.vue';
 | 
			
		||||
@@ -110,11 +105,6 @@ import { dbApi } from './api';
 | 
			
		||||
 | 
			
		||||
const Query = defineAsyncComponent(() => import('./component/tab/Query.vue'));
 | 
			
		||||
const TableData = defineAsyncComponent(() => import('./component/tab/TableData.vue'));
 | 
			
		||||
 | 
			
		||||
const sqlCompletionKeywords = [...sqlLanguage.keywords, ...addSqlLanguage.keywords];
 | 
			
		||||
const sqlCompletionOperators = [...sqlLanguage.operators, ...addSqlLanguage.operators];
 | 
			
		||||
const sqlCompletionBuiltinFunctions = [...sqlLanguage.builtinFunctions, ...addSqlLanguage.builtinFunctions];
 | 
			
		||||
const sqlCompletionBuiltinVariables = [...sqlLanguage.builtinVariables, ...addSqlLanguage.builtinVariables];
 | 
			
		||||
/**
 | 
			
		||||
 * 树节点类型
 | 
			
		||||
 */
 | 
			
		||||
@@ -217,6 +207,7 @@ const loadNode = async (node: any) => {
 | 
			
		||||
    // 点击数据库实例 -> 加载库列表
 | 
			
		||||
    if (nodeType === NodeType.DbInst) {
 | 
			
		||||
        const dbs = params.database.split(' ')?.sort();
 | 
			
		||||
        console.log(dbs);
 | 
			
		||||
        return dbs.map((x: any) => {
 | 
			
		||||
            return new TagTreeNode(`${data.key}.${x}`, x, NodeType.Db).withParams({
 | 
			
		||||
                tagPath: params.tagPath,
 | 
			
		||||
@@ -388,7 +379,6 @@ const addQueryTab = async (inst: any, db: string, sqlName: string = '') => {
 | 
			
		||||
        dbs: inst.dbs,
 | 
			
		||||
    };
 | 
			
		||||
    state.tabs.set(label, tab);
 | 
			
		||||
    registerSqlCompletionItemProvider();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onRemoveTab = (targetName: string) => {
 | 
			
		||||
@@ -443,309 +433,6 @@ const reloadTables = (nodeKey: string) => {
 | 
			
		||||
    state.reloadStatus = true;
 | 
			
		||||
    tagTreeRef.value.reloadNode(nodeKey);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const registerSqlCompletionItemProvider = () => {
 | 
			
		||||
    // 参考 https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
 | 
			
		||||
    self.completionItemProvider =
 | 
			
		||||
        self.completionItemProvider ||
 | 
			
		||||
        monaco.languages.registerCompletionItemProvider('sql', {
 | 
			
		||||
            triggerCharacters: ['.', ' '],
 | 
			
		||||
            provideCompletionItems: async (model: editor.ITextModel, position: Position): Promise<languages.CompletionList | null | undefined> => {
 | 
			
		||||
                let word = model.getWordUntilPosition(position);
 | 
			
		||||
                const nowTab = state.tabs.get(state.activeName);
 | 
			
		||||
                if (!nowTab) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                const { db, dbId } = nowTab;
 | 
			
		||||
                const dbInst = DbInst.getInst(dbId);
 | 
			
		||||
                const { lineNumber, column } = position;
 | 
			
		||||
                const { startColumn, endColumn } = word;
 | 
			
		||||
 | 
			
		||||
                // 当前行文本
 | 
			
		||||
                let lineContent = model.getLineContent(lineNumber);
 | 
			
		||||
                // 注释行不需要代码提示
 | 
			
		||||
                if (lineContent.startsWith('--')) {
 | 
			
		||||
                    return { suggestions: [] };
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let range = {
 | 
			
		||||
                    startLineNumber: lineNumber,
 | 
			
		||||
                    endLineNumber: lineNumber,
 | 
			
		||||
                    startColumn,
 | 
			
		||||
                    endColumn,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                //  光标前文本
 | 
			
		||||
                const textBeforePointer = model.getValueInRange({
 | 
			
		||||
                    startLineNumber: lineNumber,
 | 
			
		||||
                    startColumn: 0,
 | 
			
		||||
                    endLineNumber: lineNumber,
 | 
			
		||||
                    endColumn: column,
 | 
			
		||||
                });
 | 
			
		||||
                const textBeforePointerMulti = model.getValueInRange({
 | 
			
		||||
                    startLineNumber: 1,
 | 
			
		||||
                    startColumn: 0,
 | 
			
		||||
                    endLineNumber: lineNumber,
 | 
			
		||||
                    endColumn: column,
 | 
			
		||||
                });
 | 
			
		||||
                // 光标后文本
 | 
			
		||||
                const textAfterPointerMulti = model.getValueInRange({
 | 
			
		||||
                    startLineNumber: lineNumber,
 | 
			
		||||
                    startColumn: column,
 | 
			
		||||
                    endLineNumber: model.getLineCount(),
 | 
			
		||||
                    endColumn: model.getLineMaxColumn(model.getLineCount()),
 | 
			
		||||
                });
 | 
			
		||||
                // // const nextTokens = textAfterPointer.trim().split(/\s+/)
 | 
			
		||||
                // // const nextToken = nextTokens[0].toLowerCase()
 | 
			
		||||
                const tokens = textBeforePointer.trim().split(/\s+/);
 | 
			
		||||
                let lastToken = tokens[tokens.length - 1].toLowerCase();
 | 
			
		||||
                const secondToken = (tokens.length > 2 && tokens[tokens.length - 2].toLowerCase()) || '';
 | 
			
		||||
 | 
			
		||||
                // const dbs = nowTab.params?.dbs?.split(' ') || [];
 | 
			
		||||
                const dbs = (nowTab.params && nowTab.params.dbs && nowTab.params.dbs.split(' ')) || [];
 | 
			
		||||
                // console.log("光标前文本:=>" + textBeforePointerMulti)
 | 
			
		||||
                // console.log("最后输入的:=>" + lastToken)
 | 
			
		||||
 | 
			
		||||
                let suggestions: languages.CompletionItem[] = [];
 | 
			
		||||
                const tables = await dbInst.loadTables(db);
 | 
			
		||||
 | 
			
		||||
                async function hintTableColumns(tableName: any, db: any) {
 | 
			
		||||
                    let dbHits = await dbInst.loadDbHints(db);
 | 
			
		||||
                    let columns = dbHits[tableName];
 | 
			
		||||
                    let suggestions: languages.CompletionItem[] = [];
 | 
			
		||||
                    columns?.forEach((a: string, index: any) => {
 | 
			
		||||
                        // 字段数据格式  字段名 字段注释,  如: create_time  [datetime][创建时间]
 | 
			
		||||
                        const nameAndComment = a.split('  ');
 | 
			
		||||
                        const fieldName = nameAndComment[0];
 | 
			
		||||
                        suggestions.push({
 | 
			
		||||
                            label: {
 | 
			
		||||
                                label: a,
 | 
			
		||||
                                description: 'column',
 | 
			
		||||
                            },
 | 
			
		||||
                            kind: monaco.languages.CompletionItemKind.Property,
 | 
			
		||||
                            detail: '', // 不显示detail, 否则选中时备注等会被遮挡
 | 
			
		||||
                            insertText: fieldName, // create_time
 | 
			
		||||
                            range,
 | 
			
		||||
                            sortText: 100 + index + '', // 使用表字段声明顺序排序,排序需为字符串类型
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
                    return suggestions;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (lastToken.indexOf('.') > -1 || secondToken.indexOf('.') > -1) {
 | 
			
		||||
                    // 如果是.触发代码提示,则进行【 库.表名联想 】 或 【 表别名.表字段联想 】
 | 
			
		||||
                    let str = lastToken.substring(0, lastToken.lastIndexOf('.'));
 | 
			
		||||
                    if (lastToken.trim().startsWith('.')) {
 | 
			
		||||
                        str = secondToken;
 | 
			
		||||
                    }
 | 
			
		||||
                    // 如果字符串粘连起了如:'a.creator,a.',需要重新取出别名
 | 
			
		||||
                    let aliasArr = lastToken.split(',');
 | 
			
		||||
                    if (aliasArr.length > 1) {
 | 
			
		||||
                        lastToken = aliasArr[aliasArr.length - 1];
 | 
			
		||||
                        str = lastToken.substring(0, lastToken.lastIndexOf('.'));
 | 
			
		||||
                        if (lastToken.trim().startsWith('.')) {
 | 
			
		||||
                            str = secondToken;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // 库.表名联想
 | 
			
		||||
                    if (dbs && dbs.filter((a: any) => a === str)?.length > 0) {
 | 
			
		||||
                        let tables = await dbInst.loadTables(str);
 | 
			
		||||
                        let suggestions: languages.CompletionItem[] = [];
 | 
			
		||||
                        for (let item of tables) {
 | 
			
		||||
                            const { tableName, tableComment } = item;
 | 
			
		||||
                            suggestions.push({
 | 
			
		||||
                                label: {
 | 
			
		||||
                                    label: tableName + (tableComment ? ' - ' + tableComment : ''),
 | 
			
		||||
                                    description: 'table',
 | 
			
		||||
                                },
 | 
			
		||||
                                kind: monaco.languages.CompletionItemKind.File,
 | 
			
		||||
                                insertText: tableName,
 | 
			
		||||
                                range,
 | 
			
		||||
                            });
 | 
			
		||||
                        }
 | 
			
		||||
                        return { suggestions };
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    let sql = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1] + textAfterPointerMulti.split(';')[0];
 | 
			
		||||
                    // 表别名.表字段联想
 | 
			
		||||
                    let tableInfo = getTableByAlias(sql, db, str);
 | 
			
		||||
                    if (tableInfo.tableName) {
 | 
			
		||||
                        let tableName = tableInfo.tableName;
 | 
			
		||||
                        let db = tableInfo.dbName;
 | 
			
		||||
                        // 取出表名并提示
 | 
			
		||||
                        let suggestions = await hintTableColumns(tableName, db);
 | 
			
		||||
                        if (suggestions.length > 0) {
 | 
			
		||||
                            return { suggestions };
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    return { suggestions: [] };
 | 
			
		||||
                } else {
 | 
			
		||||
                    // 如果sql里含有表名,则提示表字段
 | 
			
		||||
                    let mat = textBeforePointerMulti.match(/[from|update]\n*\s+\n*(\w+)\n*\s+\n*/i);
 | 
			
		||||
                    if (mat && mat.length > 1) {
 | 
			
		||||
                        let tableName = mat[1];
 | 
			
		||||
                        // 取出表名并提示
 | 
			
		||||
                        let addSuggestions = await hintTableColumns(tableName, db);
 | 
			
		||||
                        if (addSuggestions.length > 0) {
 | 
			
		||||
                            suggestions = suggestions.concat(addSuggestions);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 表名联想
 | 
			
		||||
                tables.forEach((tableMeta: any) => {
 | 
			
		||||
                    const { tableName, tableComment } = tableMeta;
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: tableName + ' - ' + tableComment,
 | 
			
		||||
                            description: 'table',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.File,
 | 
			
		||||
                        detail: tableComment,
 | 
			
		||||
                        insertText: tableName + ' ',
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // mysql关键字
 | 
			
		||||
                sqlCompletionKeywords.forEach((item: any) => {
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item,
 | 
			
		||||
                            description: 'keyword',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Keyword,
 | 
			
		||||
                        insertText: item,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // 操作符
 | 
			
		||||
                sqlCompletionOperators.forEach((item: any) => {
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item,
 | 
			
		||||
                            description: 'opt',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Operator,
 | 
			
		||||
                        insertText: item,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                let replacedFunctions = [] as string[];
 | 
			
		||||
 | 
			
		||||
                // 添加的函数
 | 
			
		||||
                addSqlLanguage.replaceFunctions.forEach((item: any) => {
 | 
			
		||||
                    replacedFunctions.push(item.label);
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item.label,
 | 
			
		||||
                            description: item.description,
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Function,
 | 
			
		||||
                        insertText: item.insertText,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // 内置函数
 | 
			
		||||
                sqlCompletionBuiltinFunctions.forEach((item: any) => {
 | 
			
		||||
                    replacedFunctions.indexOf(item) < 0 &&
 | 
			
		||||
                        suggestions.push({
 | 
			
		||||
                            label: {
 | 
			
		||||
                                label: item,
 | 
			
		||||
                                description: 'func',
 | 
			
		||||
                            },
 | 
			
		||||
                            kind: monaco.languages.CompletionItemKind.Function,
 | 
			
		||||
                            insertText: item,
 | 
			
		||||
                            range,
 | 
			
		||||
                        });
 | 
			
		||||
                });
 | 
			
		||||
                // 内置变量
 | 
			
		||||
                sqlCompletionBuiltinVariables.forEach((item: string) => {
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item,
 | 
			
		||||
                            description: 'var',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Variable,
 | 
			
		||||
                        insertText: item,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // 库名提示
 | 
			
		||||
                if (dbs && dbs.length > 0) {
 | 
			
		||||
                    dbs.forEach((a: any) => {
 | 
			
		||||
                        suggestions.push({
 | 
			
		||||
                            label: {
 | 
			
		||||
                                label: a,
 | 
			
		||||
                                description: 'schema',
 | 
			
		||||
                            },
 | 
			
		||||
                            kind: monaco.languages.CompletionItemKind.Folder,
 | 
			
		||||
                            insertText: a,
 | 
			
		||||
                            range,
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 默认提示
 | 
			
		||||
                return {
 | 
			
		||||
                    suggestions: suggestions,
 | 
			
		||||
                };
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 根据别名获取sql里的表名
 | 
			
		||||
 * @param sql sql
 | 
			
		||||
 * @param db 默认数据库
 | 
			
		||||
 * @param alias 别名
 | 
			
		||||
 */
 | 
			
		||||
const getTableByAlias = (sql: string, db: string, alias: string): { dbName: string; tableName: string } => {
 | 
			
		||||
    // 表别名:表名
 | 
			
		||||
    let result = {};
 | 
			
		||||
    let defName = '';
 | 
			
		||||
    let defResult = {};
 | 
			
		||||
    // 正则匹配取出表名和表别名
 | 
			
		||||
    // 测试sql
 | 
			
		||||
    /*
 | 
			
		||||
 | 
			
		||||
    `select * from database.Outvisit l
 | 
			
		||||
left join patient p on l.patid=p.patientid
 | 
			
		||||
join patstatic c on   l.patid=c.patid inner join patphone  ph  on l.patid=ph.patid
 | 
			
		||||
where l.name='kevin' and exsits(select 1 from pharmacywestpas pw where p.outvisitid=l.outvisitid)
 | 
			
		||||
unit all
 | 
			
		||||
select * from invisit v where`.match(/(join|from)\s+(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)/gi)
 | 
			
		||||
     */
 | 
			
		||||
    let match = sql.match(/(join|from)\n*\s+\n*(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)\n*/gi);
 | 
			
		||||
    if (match && match.length > 0) {
 | 
			
		||||
        match.forEach((a) => {
 | 
			
		||||
            // 去掉前缀,取出
 | 
			
		||||
            let t = a
 | 
			
		||||
                .substring(5, a.length)
 | 
			
		||||
                .replaceAll(/\s+/g, ' ')
 | 
			
		||||
                .replaceAll(/\s+as\s+/gi, ' ')
 | 
			
		||||
                .replaceAll(/\r\n/g, ' ')
 | 
			
		||||
                .trim()
 | 
			
		||||
                .split(/\s+/);
 | 
			
		||||
            let withDb = t[0].split('.');
 | 
			
		||||
            // 表名是 db名.表名
 | 
			
		||||
            let tName = withDb.length > 1 ? withDb[1] : withDb[0];
 | 
			
		||||
            let dbName = withDb.length > 1 ? withDb[0] : db || '';
 | 
			
		||||
            if (t.length == 2) {
 | 
			
		||||
                // 表别名:表名
 | 
			
		||||
                result[t[1]] = { tableName: tName, dbName };
 | 
			
		||||
            } else {
 | 
			
		||||
                // 只有表名无别名 取第一个无别名的表为默认表
 | 
			
		||||
                !defName && (defResult = { tableName: tName, dbName: db });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    return result[alias] || defResult;
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
 
 | 
			
		||||
@@ -97,19 +97,38 @@ import { isTrue, notBlank } from '@/common/assert';
 | 
			
		||||
import { format as sqlFormatter } from 'sql-formatter';
 | 
			
		||||
import config from '@/common/config';
 | 
			
		||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
			
		||||
 | 
			
		||||
import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/mysql/mysql.js';
 | 
			
		||||
import { language as addSqlLanguage } from '../../lang/mysql.js';
 | 
			
		||||
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
 | 
			
		||||
import * as monaco from 'monaco-editor';
 | 
			
		||||
import { editor } from 'monaco-editor';
 | 
			
		||||
// import * as monaco from 'monaco-editor';
 | 
			
		||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
 | 
			
		||||
import { editor, languages, Position } from 'monaco-editor';
 | 
			
		||||
// 相关语言
 | 
			
		||||
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestController.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestInlineCompletions.js';
 | 
			
		||||
// 右键菜单
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/contextmenu/browser/contextmenu.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/caretOperations/browser/caretOperations.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/clipboard//browser/clipboard.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/find/browser/findController.js';
 | 
			
		||||
import 'monaco-editor/esm/vs/editor/contrib/format//browser/formatActions.js';
 | 
			
		||||
 | 
			
		||||
// 主题仓库 https://github.com/brijeshb42/monaco-themes
 | 
			
		||||
// 主题例子 https://editor.bitwiser.in/
 | 
			
		||||
import SolarizedLight from 'monaco-themes/themes/Solarized-light.json';
 | 
			
		||||
import DbTable from '../DbTable.vue';
 | 
			
		||||
import { TabInfo } from '../../db';
 | 
			
		||||
import { DbInst, TabInfo } from '../../db';
 | 
			
		||||
import { exportCsv } from '@/common/utils/export';
 | 
			
		||||
import { dateStrFormat } from '@/common/utils/date';
 | 
			
		||||
import { dbApi } from '../../api';
 | 
			
		||||
 | 
			
		||||
const sqlCompletionKeywords = [...sqlLanguage.keywords, ...addSqlLanguage.keywords];
 | 
			
		||||
const sqlCompletionOperators = [...sqlLanguage.operators, ...addSqlLanguage.operators];
 | 
			
		||||
const sqlCompletionBuiltinFunctions = [...sqlLanguage.builtinFunctions, ...addSqlLanguage.builtinFunctions];
 | 
			
		||||
const sqlCompletionBuiltinVariables = [...sqlLanguage.builtinVariables, ...addSqlLanguage.builtinVariables];
 | 
			
		||||
 | 
			
		||||
const emits = defineEmits(['saveSqlSuccess', 'deleteSqlSuccess']);
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
@@ -186,6 +205,8 @@ self.MonacoEnvironment = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const initMonacoEditor = () => {
 | 
			
		||||
    registerSqlCompletionItemProvider();
 | 
			
		||||
 | 
			
		||||
    let monacoTextarea = document.getElementById('MonacoTextarea-' + state.ti.key) as HTMLElement;
 | 
			
		||||
    // options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language
 | 
			
		||||
    // 初始化一些主题
 | 
			
		||||
@@ -490,15 +511,15 @@ const replaceSelection = (str: string, selection: any) => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onLimit = () => {
 | 
			
		||||
  let position = monacoEditor.getPosition() as monaco.Position;
 | 
			
		||||
  let newText = " limit 10";
 | 
			
		||||
  monacoEditor?.getModel().applyEdits([
 | 
			
		||||
    {
 | 
			
		||||
      range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
 | 
			
		||||
      text: newText
 | 
			
		||||
    }
 | 
			
		||||
  ]);
 | 
			
		||||
}
 | 
			
		||||
    let position = monacoEditor.getPosition() as monaco.Position;
 | 
			
		||||
    let newText = ' limit 10';
 | 
			
		||||
    monacoEditor?.getModel()?.applyEdits([
 | 
			
		||||
        {
 | 
			
		||||
            range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
 | 
			
		||||
            text: newText,
 | 
			
		||||
        },
 | 
			
		||||
    ]);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 导出当前页数据
 | 
			
		||||
@@ -563,6 +584,308 @@ const submitUpdateFields = () => {
 | 
			
		||||
const cancelUpdateFields = () => {
 | 
			
		||||
    dbTableRef.value.cancelUpdateFields();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const registerSqlCompletionItemProvider = () => {
 | 
			
		||||
    // 参考 https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
 | 
			
		||||
    self.completionItemProvider =
 | 
			
		||||
        self.completionItemProvider ||
 | 
			
		||||
        monaco.languages.registerCompletionItemProvider('sql', {
 | 
			
		||||
            triggerCharacters: ['.', ' '],
 | 
			
		||||
            provideCompletionItems: async (model: editor.ITextModel, position: Position): Promise<languages.CompletionList | null | undefined> => {
 | 
			
		||||
                let word = model.getWordUntilPosition(position);
 | 
			
		||||
                const nowTab = props.data;
 | 
			
		||||
                if (!nowTab) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                const { db, dbId } = nowTab;
 | 
			
		||||
                const dbInst = DbInst.getInst(dbId);
 | 
			
		||||
                const { lineNumber, column } = position;
 | 
			
		||||
                const { startColumn, endColumn } = word;
 | 
			
		||||
 | 
			
		||||
                // 当前行文本
 | 
			
		||||
                let lineContent = model.getLineContent(lineNumber);
 | 
			
		||||
                // 注释行不需要代码提示
 | 
			
		||||
                if (lineContent.startsWith('--')) {
 | 
			
		||||
                    return { suggestions: [] };
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let range = {
 | 
			
		||||
                    startLineNumber: lineNumber,
 | 
			
		||||
                    endLineNumber: lineNumber,
 | 
			
		||||
                    startColumn,
 | 
			
		||||
                    endColumn,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                //  光标前文本
 | 
			
		||||
                const textBeforePointer = model.getValueInRange({
 | 
			
		||||
                    startLineNumber: lineNumber,
 | 
			
		||||
                    startColumn: 0,
 | 
			
		||||
                    endLineNumber: lineNumber,
 | 
			
		||||
                    endColumn: column,
 | 
			
		||||
                });
 | 
			
		||||
                const textBeforePointerMulti = model.getValueInRange({
 | 
			
		||||
                    startLineNumber: 1,
 | 
			
		||||
                    startColumn: 0,
 | 
			
		||||
                    endLineNumber: lineNumber,
 | 
			
		||||
                    endColumn: column,
 | 
			
		||||
                });
 | 
			
		||||
                // 光标后文本
 | 
			
		||||
                const textAfterPointerMulti = model.getValueInRange({
 | 
			
		||||
                    startLineNumber: lineNumber,
 | 
			
		||||
                    startColumn: column,
 | 
			
		||||
                    endLineNumber: model.getLineCount(),
 | 
			
		||||
                    endColumn: model.getLineMaxColumn(model.getLineCount()),
 | 
			
		||||
                });
 | 
			
		||||
                // // const nextTokens = textAfterPointer.trim().split(/\s+/)
 | 
			
		||||
                // // const nextToken = nextTokens[0].toLowerCase()
 | 
			
		||||
                const tokens = textBeforePointer.trim().split(/\s+/);
 | 
			
		||||
                let lastToken = tokens[tokens.length - 1].toLowerCase();
 | 
			
		||||
                const secondToken = (tokens.length > 2 && tokens[tokens.length - 2].toLowerCase()) || '';
 | 
			
		||||
 | 
			
		||||
                const dbs = (nowTab.params && nowTab.params.dbs && nowTab.params.dbs) || [];
 | 
			
		||||
                // console.log("光标前文本:=>" + textBeforePointerMulti)
 | 
			
		||||
                // console.log("最后输入的:=>" + lastToken)
 | 
			
		||||
 | 
			
		||||
                let suggestions: languages.CompletionItem[] = [];
 | 
			
		||||
                const tables = await dbInst.loadTables(db);
 | 
			
		||||
 | 
			
		||||
                async function hintTableColumns(tableName: any, db: any) {
 | 
			
		||||
                    let dbHits = await dbInst.loadDbHints(db);
 | 
			
		||||
                    let columns = dbHits[tableName];
 | 
			
		||||
                    let suggestions: languages.CompletionItem[] = [];
 | 
			
		||||
                    columns?.forEach((a: string, index: any) => {
 | 
			
		||||
                        // 字段数据格式  字段名 字段注释,  如: create_time  [datetime][创建时间]
 | 
			
		||||
                        const nameAndComment = a.split('  ');
 | 
			
		||||
                        const fieldName = nameAndComment[0];
 | 
			
		||||
                        suggestions.push({
 | 
			
		||||
                            label: {
 | 
			
		||||
                                label: a,
 | 
			
		||||
                                description: 'column',
 | 
			
		||||
                            },
 | 
			
		||||
                            kind: monaco.languages.CompletionItemKind.Property,
 | 
			
		||||
                            detail: '', // 不显示detail, 否则选中时备注等会被遮挡
 | 
			
		||||
                            insertText: fieldName, // create_time
 | 
			
		||||
                            range,
 | 
			
		||||
                            sortText: 100 + index + '', // 使用表字段声明顺序排序,排序需为字符串类型
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
                    return suggestions;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (lastToken.indexOf('.') > -1 || secondToken.indexOf('.') > -1) {
 | 
			
		||||
                    // 如果是.触发代码提示,则进行【 库.表名联想 】 或 【 表别名.表字段联想 】
 | 
			
		||||
                    let str = lastToken.substring(0, lastToken.lastIndexOf('.'));
 | 
			
		||||
                    if (lastToken.trim().startsWith('.')) {
 | 
			
		||||
                        str = secondToken;
 | 
			
		||||
                    }
 | 
			
		||||
                    // 如果字符串粘连起了如:'a.creator,a.',需要重新取出别名
 | 
			
		||||
                    let aliasArr = lastToken.split(',');
 | 
			
		||||
                    if (aliasArr.length > 1) {
 | 
			
		||||
                        lastToken = aliasArr[aliasArr.length - 1];
 | 
			
		||||
                        str = lastToken.substring(0, lastToken.lastIndexOf('.'));
 | 
			
		||||
                        if (lastToken.trim().startsWith('.')) {
 | 
			
		||||
                            str = secondToken;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // 库.表名联想
 | 
			
		||||
                    if (dbs && dbs.filter((a: any) => a === str)?.length > 0) {
 | 
			
		||||
                        let tables = await dbInst.loadTables(str);
 | 
			
		||||
                        let suggestions: languages.CompletionItem[] = [];
 | 
			
		||||
                        for (let item of tables) {
 | 
			
		||||
                            const { tableName, tableComment } = item;
 | 
			
		||||
                            suggestions.push({
 | 
			
		||||
                                label: {
 | 
			
		||||
                                    label: tableName + (tableComment ? ' - ' + tableComment : ''),
 | 
			
		||||
                                    description: 'table',
 | 
			
		||||
                                },
 | 
			
		||||
                                kind: monaco.languages.CompletionItemKind.File,
 | 
			
		||||
                                insertText: tableName,
 | 
			
		||||
                                range,
 | 
			
		||||
                            });
 | 
			
		||||
                        }
 | 
			
		||||
                        return { suggestions };
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    let sql = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1] + textAfterPointerMulti.split(';')[0];
 | 
			
		||||
                    // 表别名.表字段联想
 | 
			
		||||
                    let tableInfo = getTableByAlias(sql, db, str);
 | 
			
		||||
                    if (tableInfo.tableName) {
 | 
			
		||||
                        let tableName = tableInfo.tableName;
 | 
			
		||||
                        let db = tableInfo.dbName;
 | 
			
		||||
                        // 取出表名并提示
 | 
			
		||||
                        let suggestions = await hintTableColumns(tableName, db);
 | 
			
		||||
                        if (suggestions.length > 0) {
 | 
			
		||||
                            return { suggestions };
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    return { suggestions: [] };
 | 
			
		||||
                } else {
 | 
			
		||||
                    // 如果sql里含有表名,则提示表字段
 | 
			
		||||
                    let mat = textBeforePointerMulti.match(/[from|update]\n*\s+\n*(\w+)\n*\s+\n*/i);
 | 
			
		||||
                    if (mat && mat.length > 1) {
 | 
			
		||||
                        let tableName = mat[1];
 | 
			
		||||
                        // 取出表名并提示
 | 
			
		||||
                        let addSuggestions = await hintTableColumns(tableName, db);
 | 
			
		||||
                        if (addSuggestions.length > 0) {
 | 
			
		||||
                            suggestions = suggestions.concat(addSuggestions);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 表名联想
 | 
			
		||||
                tables.forEach((tableMeta: any) => {
 | 
			
		||||
                    const { tableName, tableComment } = tableMeta;
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: tableName + ' - ' + tableComment,
 | 
			
		||||
                            description: 'table',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.File,
 | 
			
		||||
                        detail: tableComment,
 | 
			
		||||
                        insertText: tableName + ' ',
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // mysql关键字
 | 
			
		||||
                sqlCompletionKeywords.forEach((item: any) => {
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item,
 | 
			
		||||
                            description: 'keyword',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Keyword,
 | 
			
		||||
                        insertText: item,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // 操作符
 | 
			
		||||
                sqlCompletionOperators.forEach((item: any) => {
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item,
 | 
			
		||||
                            description: 'opt',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Operator,
 | 
			
		||||
                        insertText: item,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                let replacedFunctions = [] as string[];
 | 
			
		||||
 | 
			
		||||
                // 添加的函数
 | 
			
		||||
                addSqlLanguage.replaceFunctions.forEach((item: any) => {
 | 
			
		||||
                    replacedFunctions.push(item.label);
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item.label,
 | 
			
		||||
                            description: item.description,
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Function,
 | 
			
		||||
                        insertText: item.insertText,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // 内置函数
 | 
			
		||||
                sqlCompletionBuiltinFunctions.forEach((item: any) => {
 | 
			
		||||
                    replacedFunctions.indexOf(item) < 0 &&
 | 
			
		||||
                        suggestions.push({
 | 
			
		||||
                            label: {
 | 
			
		||||
                                label: item,
 | 
			
		||||
                                description: 'func',
 | 
			
		||||
                            },
 | 
			
		||||
                            kind: monaco.languages.CompletionItemKind.Function,
 | 
			
		||||
                            insertText: item,
 | 
			
		||||
                            range,
 | 
			
		||||
                        });
 | 
			
		||||
                });
 | 
			
		||||
                // 内置变量
 | 
			
		||||
                sqlCompletionBuiltinVariables.forEach((item: string) => {
 | 
			
		||||
                    suggestions.push({
 | 
			
		||||
                        label: {
 | 
			
		||||
                            label: item,
 | 
			
		||||
                            description: 'var',
 | 
			
		||||
                        },
 | 
			
		||||
                        kind: monaco.languages.CompletionItemKind.Variable,
 | 
			
		||||
                        insertText: item,
 | 
			
		||||
                        range,
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // 库名提示
 | 
			
		||||
                if (dbs && dbs.length > 0) {
 | 
			
		||||
                    dbs.forEach((a: any) => {
 | 
			
		||||
                        suggestions.push({
 | 
			
		||||
                            label: {
 | 
			
		||||
                                label: a,
 | 
			
		||||
                                description: 'schema',
 | 
			
		||||
                            },
 | 
			
		||||
                            kind: monaco.languages.CompletionItemKind.Folder,
 | 
			
		||||
                            insertText: a,
 | 
			
		||||
                            range,
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 默认提示
 | 
			
		||||
                return {
 | 
			
		||||
                    suggestions: suggestions,
 | 
			
		||||
                };
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 根据别名获取sql里的表名
 | 
			
		||||
 * @param sql sql
 | 
			
		||||
 * @param db 默认数据库
 | 
			
		||||
 * @param alias 别名
 | 
			
		||||
 */
 | 
			
		||||
const getTableByAlias = (sql: string, db: string, alias: string): { dbName: string; tableName: string } => {
 | 
			
		||||
    // 表别名:表名
 | 
			
		||||
    let result = {};
 | 
			
		||||
    let defName = '';
 | 
			
		||||
    let defResult = {};
 | 
			
		||||
    // 正则匹配取出表名和表别名
 | 
			
		||||
    // 测试sql
 | 
			
		||||
    /*
 | 
			
		||||
 | 
			
		||||
    `select * from database.Outvisit l
 | 
			
		||||
left join patient p on l.patid=p.patientid
 | 
			
		||||
join patstatic c on   l.patid=c.patid inner join patphone  ph  on l.patid=ph.patid
 | 
			
		||||
where l.name='kevin' and exsits(select 1 from pharmacywestpas pw where p.outvisitid=l.outvisitid)
 | 
			
		||||
unit all
 | 
			
		||||
select * from invisit v where`.match(/(join|from)\s+(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)/gi)
 | 
			
		||||
     */
 | 
			
		||||
    let match = sql.match(/(join|from)\n*\s+\n*(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)\n*/gi);
 | 
			
		||||
    if (match && match.length > 0) {
 | 
			
		||||
        match.forEach((a) => {
 | 
			
		||||
            // 去掉前缀,取出
 | 
			
		||||
            let t = a
 | 
			
		||||
                .substring(5, a.length)
 | 
			
		||||
                .replaceAll(/\s+/g, ' ')
 | 
			
		||||
                .replaceAll(/\s+as\s+/gi, ' ')
 | 
			
		||||
                .replaceAll(/\r\n/g, ' ')
 | 
			
		||||
                .trim()
 | 
			
		||||
                .split(/\s+/);
 | 
			
		||||
            let withDb = t[0].split('.');
 | 
			
		||||
            // 表名是 db名.表名
 | 
			
		||||
            let tName = withDb.length > 1 ? withDb[1] : withDb[0];
 | 
			
		||||
            let dbName = withDb.length > 1 ? withDb[0] : db || '';
 | 
			
		||||
            if (t.length == 2) {
 | 
			
		||||
                // 表别名:表名
 | 
			
		||||
                result[t[1]] = { tableName: tName, dbName };
 | 
			
		||||
            } else {
 | 
			
		||||
                // 只有表名无别名 取第一个无别名的表为默认表
 | 
			
		||||
                !defName && (defResult = { tableName: tName, dbName: db });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    return result[alias] || defResult;
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
 
 | 
			
		||||
@@ -68,11 +68,11 @@ const viteConfig: UserConfig = {
 | 
			
		||||
                            if (atRule.name === 'charset') {
 | 
			
		||||
                                atRule.remove();
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1944,30 +1944,30 @@ wrappy@1:
 | 
			
		||||
  resolved "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz"
 | 
			
		||||
  integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
 | 
			
		||||
 | 
			
		||||
xterm-addon-fit@^0.7.0:
 | 
			
		||||
  version "0.7.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-fit/-/xterm-addon-fit-0.7.0.tgz#b8ade6d96e63b47443862088f6670b49fb752c6a"
 | 
			
		||||
  integrity sha512-tQgHGoHqRTgeROPnvmtEJywLKoC/V9eNs4bLLz7iyJr1aW/QFzRwfd3MGiJ6odJd9xEfxcW36/xRU47JkD5NKQ==
 | 
			
		||||
 | 
			
		||||
xterm-addon-search@^0.12.0:
 | 
			
		||||
  version "0.12.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-search/-/xterm-addon-search-0.12.0.tgz#2ef8f56aecf699a3989223a1260f1e079d7c74e2"
 | 
			
		||||
  integrity sha512-hXAuO7Ts2+Jf9K8mZrUx8IFd7c/Flgks/jyqA1L4reymyfmXtcsd+WDLel8R9Tgy2CLyKABVBP09/Ua/FmXcvg==
 | 
			
		||||
 | 
			
		||||
xterm-addon-web-links@^0.8.0:
 | 
			
		||||
xterm-addon-fit@^0.8.0:
 | 
			
		||||
  version "0.8.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-web-links/-/xterm-addon-web-links-0.8.0.tgz#2cb1d57129271022569208578b0bf4774e7e6ea9"
 | 
			
		||||
  integrity sha512-J4tKngmIu20ytX9SEJjAP3UGksah7iALqBtfTwT9ZnmFHVplCumYQsUJfKuS+JwMhjsjH61YXfndenLNvjRrEw==
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz#48ca99015385141918f955ca7819e85f3691d35f"
 | 
			
		||||
  integrity sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==
 | 
			
		||||
 | 
			
		||||
xterm-addon-webgl@^0.15.0:
 | 
			
		||||
  version "0.15.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz#c10f93ca619524f5a470eaac44258bab0ae8e3c7"
 | 
			
		||||
  integrity sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg==
 | 
			
		||||
xterm-addon-search@^0.13.0:
 | 
			
		||||
  version "0.13.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-search/-/xterm-addon-search-0.13.0.tgz#21286f4db48aa949fbefce34bb8bc0c9d3cec627"
 | 
			
		||||
  integrity sha512-sDUwG4CnqxUjSEFh676DlS3gsh3XYCzAvBPSvJ5OPgF3MRL3iHLPfsb06doRicLC2xXNpeG2cWk8x1qpESWJMA==
 | 
			
		||||
 | 
			
		||||
xterm@^5.2.1:
 | 
			
		||||
  version "5.2.1"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm/-/xterm-5.2.1.tgz#b3fea7bdb55b9be1d4b31f4cd1091f26ac42afb8"
 | 
			
		||||
  integrity sha512-cs5Y1fFevgcdoh2hJROMVIWwoBHD80P1fIP79gopLHJIE4kTzzblanoivxTiQ4+92YM9IxS36H1q0MxIJXQBcA==
 | 
			
		||||
xterm-addon-web-links@^0.9.0:
 | 
			
		||||
  version "0.9.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-web-links/-/xterm-addon-web-links-0.9.0.tgz#c65b18588d1f613e703eb6feb7f129e7ff1c63e7"
 | 
			
		||||
  integrity sha512-LIzi4jBbPlrKMZF3ihoyqayWyTXAwGfu4yprz1aK2p71e9UKXN6RRzVONR0L+Zd+Ik5tPVI9bwp9e8fDTQh49Q==
 | 
			
		||||
 | 
			
		||||
xterm-addon-webgl@^0.16.0:
 | 
			
		||||
  version "0.16.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0.tgz#9872d08a64136f893b27ef9a6412136d3bf563c4"
 | 
			
		||||
  integrity sha512-E8cq1AiqNOv0M/FghPT+zPAEnvIQRDbAbkb04rRYSxUym69elPWVJ4sv22FCLBqM/3LcrmBLl/pELnBebVFKgA==
 | 
			
		||||
 | 
			
		||||
xterm@^5.3.0:
 | 
			
		||||
  version "5.3.0"
 | 
			
		||||
  resolved "https://registry.npmmirror.com/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46"
 | 
			
		||||
  integrity sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==
 | 
			
		||||
 | 
			
		||||
yallist@^4.0.0:
 | 
			
		||||
  version "4.0.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ import (
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/jsonx"
 | 
			
		||||
	"mayfly-go/pkg/utils/stringx"
 | 
			
		||||
	"mayfly-go/pkg/ws"
 | 
			
		||||
	"os"
 | 
			
		||||
@@ -85,7 +86,7 @@ func (m *Machine) ChangeStatus(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	id := uint64(ginx.PathParamInt(g, "machineId"))
 | 
			
		||||
	status := int8(ginx.PathParamInt(g, "status"))
 | 
			
		||||
	rc.ReqParam = fmt.Sprintf("id: %d -- status: %d", id, status)
 | 
			
		||||
	rc.ReqParam = jsonx.Kvs("id", id, "status", status)
 | 
			
		||||
	m.MachineApp.ChangeStatus(id, status)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user