2021-06-07 17:22:07 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div>
|
2023-02-15 21:28:01 +08:00
|
|
|
|
<el-row>
|
|
|
|
|
|
<el-col :span="4">
|
|
|
|
|
|
<el-button type="primary" icon="plus" @click="addQueryTab({ id: nowDbInst.id }, state.db)"
|
2023-02-13 21:11:16 +08:00
|
|
|
|
size="small">新建查询</el-button>
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</el-col>
|
2023-02-15 21:28:01 +08:00
|
|
|
|
<el-col :span="20" v-if="state.db">
|
|
|
|
|
|
<el-descriptions :column="4" size="small" border style="height: 10px">
|
|
|
|
|
|
<el-descriptions-item label-align="right" label="tag">{{ nowDbInst.tagPath }}</el-descriptions-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-descriptions-item label="实例" label-align="right">
|
|
|
|
|
|
{{ nowDbInst.id }}
|
|
|
|
|
|
<el-divider direction="vertical" border-style="dashed" />
|
|
|
|
|
|
{{ nowDbInst.type }}
|
|
|
|
|
|
<el-divider direction="vertical" border-style="dashed" />
|
|
|
|
|
|
{{ nowDbInst.name }}
|
|
|
|
|
|
</el-descriptions-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-descriptions-item label="库名" label-align="right">{{ state.db }}</el-descriptions-item>
|
|
|
|
|
|
</el-descriptions>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
<el-row type="flex">
|
2023-02-06 17:14:16 +08:00
|
|
|
|
<el-col :span="4" style="border-left: 1px solid #eee; margin-top: 10px">
|
2023-04-05 22:41:53 +08:00
|
|
|
|
<tag-tree ref="tagTreeRef" @node-click="nodeClick" :load="loadNode" :load-contextmenu-items="getContextmenuItems" @current-contextmenu-click="onCurrentContextmenuClick"
|
|
|
|
|
|
:height="state.tagTreeHeight">
|
2023-02-18 23:02:14 +08:00
|
|
|
|
<template #prefix="{ data }">
|
|
|
|
|
|
<span v-if="data.type == NodeType.DbInst">
|
|
|
|
|
|
<el-popover placement="right-start" title="数据库实例信息" trigger="hover" :width="210">
|
|
|
|
|
|
<template #reference>
|
2023-03-16 16:40:57 +08:00
|
|
|
|
<SvgIcon v-if="data.params.type === 'mysql'" name="iconfont icon-op-mysql" :size="18" />
|
2023-04-05 22:41:53 +08:00
|
|
|
|
<SvgIcon v-if="data.params.type === 'postgres'" name="iconfont icon-op-postgres"
|
|
|
|
|
|
:size="18" />
|
2023-02-20 18:41:45 +08:00
|
|
|
|
|
2023-03-16 16:40:57 +08:00
|
|
|
|
<SvgIcon name="InfoFilled" v-else />
|
2023-02-18 23:02:14 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
<template #default>
|
|
|
|
|
|
<el-form class="instances-pop-form" label-width="55px" :size="'small'">
|
|
|
|
|
|
<el-form-item label="类型:">{{ data.params.type }}</el-form-item>
|
|
|
|
|
|
<el-form-item label="链接:">{{ data.params.host }}:{{
|
|
|
|
|
|
data.params.port
|
|
|
|
|
|
}}</el-form-item>
|
|
|
|
|
|
<el-form-item label="用户:">{{ data.params.username }}</el-form-item>
|
|
|
|
|
|
<el-form-item v-if="data.params.remark" label="备注:">{{
|
|
|
|
|
|
data.params.remark
|
|
|
|
|
|
}}</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-popover>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
2023-03-16 16:40:57 +08:00
|
|
|
|
<SvgIcon v-if="data.type == NodeType.Db" name="Coin" color="#67c23a" />
|
|
|
|
|
|
|
|
|
|
|
|
<SvgIcon name="Calendar" v-if="data.type == NodeType.TableMenu" color="#409eff" />
|
2023-02-18 23:02:14 +08:00
|
|
|
|
|
|
|
|
|
|
<el-tooltip v-if="data.type == NodeType.Table" effect="customized"
|
|
|
|
|
|
:content="data.params.tableComment" placement="top-end">
|
2023-04-05 22:41:53 +08:00
|
|
|
|
<SvgIcon name="Calendar" color="#409eff" />
|
2023-02-18 23:02:14 +08:00
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
|
2023-04-05 22:41:53 +08:00
|
|
|
|
<SvgIcon name="Files" v-if="data.type == NodeType.SqlMenu || data.type == NodeType.Sql"
|
|
|
|
|
|
color="#f56c6c" />
|
2023-03-28 15:22:05 +08:00
|
|
|
|
</template>
|
2023-02-18 23:02:14 +08:00
|
|
|
|
</tag-tree>
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="20">
|
|
|
|
|
|
<el-container id="data-exec" style="border-left: 1px solid #eee; margin-top: 10px">
|
2023-02-15 21:28:01 +08:00
|
|
|
|
<el-tabs @tab-remove="onRemoveTab" @tab-change="onTabChange" style="width: 100%"
|
2023-02-06 17:14:16 +08:00
|
|
|
|
v-model="state.activeName">
|
|
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
<el-tab-pane closable v-for="dt in state.tabs.values()" :key="dt.key" :label="dt.key"
|
2023-02-06 17:14:16 +08:00
|
|
|
|
:name="dt.key">
|
2023-02-13 21:11:16 +08:00
|
|
|
|
<table-data v-if="dt.type === TabType.TableData" @gen-insert-sql="onGenerateInsertSql"
|
|
|
|
|
|
:data="dt" :table-height="state.dataTabsTableHeight"></table-data>
|
2022-08-26 20:15:36 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
<query v-else @save-sql-success="reloadSqls" @delete-sql-success="deleteSqlScript(dt)"
|
|
|
|
|
|
:data="dt" :editor-height="state.editorHeight">
|
|
|
|
|
|
</query>
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
</el-tabs>
|
|
|
|
|
|
</el-container>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog @close="state.genSqlDialog.visible = false" v-model="state.genSqlDialog.visible" title="SQL"
|
|
|
|
|
|
width="1000px">
|
2023-01-31 10:37:40 +08:00
|
|
|
|
<el-input v-model="state.genSqlDialog.sql" type="textarea" rows="20" />
|
2022-07-27 15:36:56 +08:00
|
|
|
|
</el-dialog>
|
2021-06-07 17:22:07 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
2022-10-29 20:08:15 +08:00
|
|
|
|
<script lang="ts" setup>
|
2023-03-15 11:41:03 +08:00
|
|
|
|
import { defineAsyncComponent, onMounted, reactive, ref, toRefs } from 'vue';
|
2023-02-13 21:11:16 +08:00
|
|
|
|
import { ElMessage } from 'element-plus';
|
2022-11-01 22:18:54 +08:00
|
|
|
|
|
2023-02-06 17:14:16 +08:00
|
|
|
|
import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/mysql/mysql.js';
|
2022-11-01 22:18:54 +08:00
|
|
|
|
import * as monaco from 'monaco-editor';
|
2023-02-06 17:14:16 +08:00
|
|
|
|
import { editor, languages, Position } from 'monaco-editor';
|
2021-07-28 18:03:19 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
import { DbInst, TabInfo, TabType } from './db'
|
2023-02-18 23:02:14 +08:00
|
|
|
|
import { TagTreeNode } from '../component/tag';
|
|
|
|
|
|
import TagTree from '../component/TagTree.vue';
|
|
|
|
|
|
import { dbApi } from './api';
|
2022-10-29 20:08:15 +08:00
|
|
|
|
|
2023-03-15 11:41:03 +08:00
|
|
|
|
const Query = defineAsyncComponent(() => import('./component/tab/Query.vue'));
|
|
|
|
|
|
const TableData = defineAsyncComponent(() => import('./component/tab/TableData.vue'));
|
|
|
|
|
|
|
2023-02-18 23:02:14 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 树节点类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
class NodeType {
|
|
|
|
|
|
static DbInst = 1
|
|
|
|
|
|
static Db = 2
|
|
|
|
|
|
static TableMenu = 3;
|
|
|
|
|
|
static SqlMenu = 4;
|
|
|
|
|
|
static Table = 5;
|
|
|
|
|
|
static Sql = 6;
|
|
|
|
|
|
}
|
2023-04-05 22:41:53 +08:00
|
|
|
|
class ContextmenuClickId {
|
|
|
|
|
|
static ReloadTable = 0
|
|
|
|
|
|
}
|
2023-02-18 23:02:14 +08:00
|
|
|
|
|
|
|
|
|
|
const tagTreeRef: any = ref(null)
|
2023-01-31 10:37:40 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const tabs: Map<string, TabInfo> = new Map();
|
2022-10-29 20:08:15 +08:00
|
|
|
|
const state = reactive({
|
2023-02-15 21:28:01 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 当前操作的数据库实例
|
|
|
|
|
|
*/
|
|
|
|
|
|
nowDbInst: {} as DbInst,
|
2023-02-13 21:11:16 +08:00
|
|
|
|
db: '', // 当前操作的数据库
|
2023-02-18 23:02:14 +08:00
|
|
|
|
activeName: '',
|
2023-03-28 15:22:05 +08:00
|
|
|
|
reloadStatus: false,
|
2023-02-13 21:11:16 +08:00
|
|
|
|
tabs,
|
|
|
|
|
|
dataTabsTableHeight: '600',
|
|
|
|
|
|
editorHeight: '600',
|
2023-04-13 20:11:22 +08:00
|
|
|
|
tagTreeHeight: window.innerHeight - 178 + 'px',
|
2022-10-29 20:08:15 +08:00
|
|
|
|
genSqlDialog: {
|
|
|
|
|
|
visible: false,
|
|
|
|
|
|
sql: '',
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2023-02-15 21:28:01 +08:00
|
|
|
|
const {
|
|
|
|
|
|
nowDbInst,
|
|
|
|
|
|
} = toRefs(state);
|
|
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
self.completionItemProvider?.dispose()
|
|
|
|
|
|
setHeight();
|
|
|
|
|
|
// 监听浏览器窗口大小变化,更新对应组件高度
|
|
|
|
|
|
window.onresize = () => setHeight();
|
2022-11-05 22:18:59 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 设置editor高度和数据表高度
|
|
|
|
|
|
*/
|
|
|
|
|
|
const setHeight = () => {
|
|
|
|
|
|
state.editorHeight = window.innerHeight - 518 + 'px';
|
|
|
|
|
|
state.dataTabsTableHeight = window.innerHeight - 219 - 36 + 'px';
|
2023-02-18 23:02:14 +08:00
|
|
|
|
state.tagTreeHeight = window.innerHeight - 165 + 'px';
|
2022-10-28 17:42:23 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2023-02-18 23:02:14 +08:00
|
|
|
|
/**
|
2023-03-15 11:41:03 +08:00
|
|
|
|
* instmap; tagPaht -> info[]
|
2023-02-18 23:02:14 +08:00
|
|
|
|
*/
|
|
|
|
|
|
const instMap: Map<string, any[]> = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
const getInsts = async () => {
|
|
|
|
|
|
const res = await dbApi.dbs.request({ pageNum: 1, pageSize: 1000, })
|
|
|
|
|
|
if (!res.total) return
|
|
|
|
|
|
for (const db of res.list) {
|
|
|
|
|
|
const tagPath = db.tagPath;
|
2023-04-05 22:41:53 +08:00
|
|
|
|
let dbInsts = instMap.get(tagPath) || [];
|
|
|
|
|
|
dbInsts.push(db);
|
|
|
|
|
|
instMap.set(tagPath, dbInsts?.sort());
|
2023-02-18 23:02:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载树节点
|
|
|
|
|
|
* @param {Object} node
|
|
|
|
|
|
* @param {Object} resolve
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadNode = async (node: any) => {
|
|
|
|
|
|
// 一级为tagPath
|
|
|
|
|
|
if (node.level === 0) {
|
|
|
|
|
|
await getInsts();
|
|
|
|
|
|
const tagPaths = instMap.keys();
|
|
|
|
|
|
const tagNodes = [];
|
|
|
|
|
|
for (let tagPath of tagPaths) {
|
|
|
|
|
|
tagNodes.push(new TagTreeNode(tagPath, tagPath));
|
|
|
|
|
|
}
|
|
|
|
|
|
return tagNodes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const data = node.data;
|
|
|
|
|
|
const nodeType = data.type;
|
|
|
|
|
|
const params = data.params;
|
|
|
|
|
|
|
|
|
|
|
|
// 点击tagPath -> 加载数据库实例信息列表
|
|
|
|
|
|
if (nodeType === TagTreeNode.TagPath) {
|
|
|
|
|
|
const dbInfos = instMap.get(data.key)
|
|
|
|
|
|
return dbInfos?.map((x: any) => {
|
|
|
|
|
|
return new TagTreeNode(`${data.key}.${x.id}`, x.name, NodeType.DbInst).withParams(x);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 点击数据库实例 -> 加载库列表
|
|
|
|
|
|
if (nodeType === NodeType.DbInst) {
|
2023-03-15 11:41:03 +08:00
|
|
|
|
const dbs = params.database.split(' ')?.sort();
|
2023-02-18 23:02:14 +08:00
|
|
|
|
return dbs.map((x: any) => {
|
|
|
|
|
|
return new TagTreeNode(`${data.key}.${x}`, x, NodeType.Db).withParams({
|
|
|
|
|
|
tagPath: params.tagPath,
|
|
|
|
|
|
id: params.id,
|
|
|
|
|
|
name: params.name,
|
|
|
|
|
|
type: params.type,
|
|
|
|
|
|
dbs: dbs,
|
|
|
|
|
|
db: x
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 点击数据库 -> 加载 表&Sql 菜单
|
|
|
|
|
|
if (nodeType === NodeType.Db) {
|
|
|
|
|
|
return [new TagTreeNode(`${params.id}.${params.db}.table-menu`, '表', NodeType.TableMenu).withParams(params),
|
|
|
|
|
|
new TagTreeNode(getSqlMenuNodeKey(params.id, params.db), 'SQL', NodeType.SqlMenu).withParams(params)];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 点击表菜单 -> 加载表列表
|
|
|
|
|
|
if (nodeType === NodeType.TableMenu) {
|
|
|
|
|
|
return await getTables(params);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeType === NodeType.SqlMenu) {
|
|
|
|
|
|
return await loadSqls(params.id, params.db, params.dbs);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return [];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const nodeClick = async (data: any) => {
|
|
|
|
|
|
const params = data.params;
|
|
|
|
|
|
const nodeKey = data.key;
|
|
|
|
|
|
const dataType = data.type;
|
|
|
|
|
|
// 点击数据库,修改当前数据库信息
|
|
|
|
|
|
if (dataType === NodeType.Db || dataType === NodeType.SqlMenu || dataType === NodeType.TableMenu) {
|
|
|
|
|
|
changeSchema({ id: params.id, name: params.name, type: params.type, tagPath: params.tagPath }, params.db);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 点击表加载表数据tab
|
|
|
|
|
|
if (dataType === NodeType.Table) {
|
|
|
|
|
|
await loadTableData({ id: params.id, nodeKey: nodeKey }, params.db, params.tableName);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 点击表加载表数据tab
|
|
|
|
|
|
if (dataType === NodeType.Sql) {
|
|
|
|
|
|
await addQueryTab({ id: params.id, nodeKey: nodeKey, dbs: params.dbs }, params.db, params.sqlName);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-05 22:41:53 +08:00
|
|
|
|
const getContextmenuItems = (data: any) => {
|
|
|
|
|
|
const dataType = data.type;
|
|
|
|
|
|
if (dataType === NodeType.TableMenu) {
|
|
|
|
|
|
return [
|
|
|
|
|
|
{ contextMenuClickId: ContextmenuClickId.ReloadTable, txt: '刷新', icon: 'RefreshRight' }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 当前右击菜单点击事件
|
|
|
|
|
|
const onCurrentContextmenuClick = (clickData: any) => {
|
|
|
|
|
|
const clickId = clickData.id;
|
|
|
|
|
|
if (clickId == ContextmenuClickId.ReloadTable) {
|
|
|
|
|
|
reloadTables(clickData.item.key)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-18 23:02:14 +08:00
|
|
|
|
const getTables = async (params: any) => {
|
|
|
|
|
|
const { id, db } = params;
|
2023-03-28 15:22:05 +08:00
|
|
|
|
let tables = await DbInst.getInst(id).loadTables(db, state.reloadStatus);
|
2023-04-05 22:41:53 +08:00
|
|
|
|
state.reloadStatus = false
|
2023-02-18 23:02:14 +08:00
|
|
|
|
return tables.map((x: any) => {
|
|
|
|
|
|
return new TagTreeNode(`${id}.${db}.${x.tableName}`, x.tableName, NodeType.Table).withIsLeaf(true).withParams({
|
|
|
|
|
|
id,
|
|
|
|
|
|
db,
|
|
|
|
|
|
tableName: x.tableName,
|
|
|
|
|
|
tableComment: x.tableComment,
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载用户保存的sql脚本
|
2023-06-13 14:54:52 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @param inst
|
|
|
|
|
|
* @param schema
|
2023-02-18 23:02:14 +08:00
|
|
|
|
*/
|
|
|
|
|
|
const loadSqls = async (id: any, db: string, dbs: any) => {
|
|
|
|
|
|
const sqls = await dbApi.getSqlNames.request({ id: id, db: db, })
|
|
|
|
|
|
return sqls.map((x: any) => {
|
|
|
|
|
|
return new TagTreeNode(`${id}.${db}.${x.name}`, x.name, NodeType.Sql).withIsLeaf(true).withParams({
|
|
|
|
|
|
id,
|
|
|
|
|
|
db,
|
|
|
|
|
|
dbs,
|
|
|
|
|
|
sqlName: x.name,
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
2023-02-06 17:14:16 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
// 选择数据库
|
|
|
|
|
|
const changeSchema = (inst: any, schema: string) => {
|
2023-02-15 21:28:01 +08:00
|
|
|
|
state.nowDbInst = DbInst.getOrNewInst(inst);
|
|
|
|
|
|
state.db = schema;
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
2022-10-28 17:42:23 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
// 加载选中的表数据,即新增表数据操作tab
|
|
|
|
|
|
const loadTableData = async (inst: any, schema: string, tableName: string) => {
|
|
|
|
|
|
changeSchema(inst, schema)
|
|
|
|
|
|
if (tableName == '') {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-11-07 21:57:51 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const label = `${inst.id}:\`${schema}\`.${tableName}`;
|
|
|
|
|
|
let tab = state.tabs.get(label);
|
|
|
|
|
|
state.activeName = label;
|
|
|
|
|
|
// 如果存在该表tab,则直接返回
|
|
|
|
|
|
if (tab) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
tab = new TabInfo();
|
|
|
|
|
|
tab.key = label;
|
2023-02-18 23:02:14 +08:00
|
|
|
|
tab.treeNodeKey = inst.nodeKey;
|
2023-02-13 21:11:16 +08:00
|
|
|
|
tab.dbId = inst.id;
|
|
|
|
|
|
tab.db = schema;
|
|
|
|
|
|
tab.type = TabType.TableData;
|
2023-02-14 11:44:48 +08:00
|
|
|
|
tab.params = {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
table: tableName
|
|
|
|
|
|
}
|
|
|
|
|
|
state.tabs.set(label, tab)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 新建查询panel
|
|
|
|
|
|
const addQueryTab = async (inst: any, db: string, sqlName: string = '') => {
|
2023-02-15 21:28:01 +08:00
|
|
|
|
if (!db || !inst.id) {
|
|
|
|
|
|
ElMessage.warning('请选择数据库实例及对应的schema')
|
2023-02-13 21:11:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
2023-02-18 23:02:14 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const dbId = inst.id;
|
|
|
|
|
|
let label;
|
|
|
|
|
|
// 存在sql模板名,则该模板名只允许一个tab
|
|
|
|
|
|
if (sqlName) {
|
|
|
|
|
|
label = `查询:${dbId}:${db}.${sqlName}`;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
let count = 1;
|
|
|
|
|
|
state.tabs.forEach((v) => {
|
2023-02-14 11:44:48 +08:00
|
|
|
|
if (v.type == TabType.Query && !v.params.sqlName) {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
count++;
|
2022-11-07 21:57:51 +08:00
|
|
|
|
}
|
2023-02-13 21:11:16 +08:00
|
|
|
|
})
|
|
|
|
|
|
label = `新查询${count}:${dbId}:${db}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
state.activeName = label;
|
|
|
|
|
|
let tab = state.tabs.get(label);
|
|
|
|
|
|
if (tab) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
tab = new TabInfo();
|
|
|
|
|
|
tab.key = label;
|
2023-02-18 23:02:14 +08:00
|
|
|
|
tab.treeNodeKey = inst.nodeKey;
|
2023-02-13 21:11:16 +08:00
|
|
|
|
tab.dbId = dbId;
|
|
|
|
|
|
tab.db = db;
|
|
|
|
|
|
tab.type = TabType.Query;
|
2023-02-14 11:44:48 +08:00
|
|
|
|
tab.params = {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
sqlName: sqlName,
|
2023-02-18 23:02:14 +08:00
|
|
|
|
dbs: inst.dbs,
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
state.tabs.set(label, tab)
|
|
|
|
|
|
registerSqlCompletionItemProvider();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-15 21:28:01 +08:00
|
|
|
|
const onRemoveTab = (targetName: string) => {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
let activeName = state.activeName;
|
|
|
|
|
|
const tabNames = [...state.tabs.keys()]
|
|
|
|
|
|
for (let i = 0; i < tabNames.length; i++) {
|
|
|
|
|
|
const tabName = tabNames[i]
|
|
|
|
|
|
if (tabName !== targetName) {
|
|
|
|
|
|
continue;
|
2022-11-07 21:57:51 +08:00
|
|
|
|
}
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const nextTab = tabNames[i + 1] || tabNames[i - 1];
|
|
|
|
|
|
if (nextTab) {
|
|
|
|
|
|
activeName = nextTab;
|
2023-02-15 21:28:01 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
activeName = '';
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
state.tabs.delete(targetName);
|
|
|
|
|
|
state.activeName = activeName;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2023-02-15 21:28:01 +08:00
|
|
|
|
const onTabChange = () => {
|
|
|
|
|
|
if (!state.activeName) {
|
|
|
|
|
|
state.nowDbInst = {} as DbInst;
|
|
|
|
|
|
state.db = '';
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-02-18 23:02:14 +08:00
|
|
|
|
const nowTab = state.tabs.get(state.activeName);
|
|
|
|
|
|
state.nowDbInst = DbInst.getInst(nowTab?.dbId);
|
|
|
|
|
|
state.db = nowTab?.db as string;
|
2023-02-15 21:28:01 +08:00
|
|
|
|
}
|
2022-11-07 21:57:51 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const onGenerateInsertSql = async (sql: string) => {
|
|
|
|
|
|
state.genSqlDialog.sql = sql;
|
|
|
|
|
|
state.genSqlDialog.visible = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const reloadSqls = (dbId: number, db: string) => {
|
2023-02-18 23:02:14 +08:00
|
|
|
|
tagTreeRef.value.reloadNode(getSqlMenuNodeKey(dbId, db));
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const deleteSqlScript = (ti: TabInfo) => {
|
2023-02-18 23:02:14 +08:00
|
|
|
|
reloadSqls(ti.dbId, ti.db);
|
2023-02-15 21:28:01 +08:00
|
|
|
|
onRemoveTab(ti.key);
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-18 23:02:14 +08:00
|
|
|
|
const getSqlMenuNodeKey = (dbId: number, db: string) => {
|
|
|
|
|
|
return `${dbId}.${db}.sql-menu`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-05 22:41:53 +08:00
|
|
|
|
const reloadTables = (nodeKey: string) => {
|
|
|
|
|
|
state.reloadStatus = true
|
|
|
|
|
|
tagTreeRef.value.reloadNode(nodeKey);
|
2023-03-28 15:22:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const registerSqlCompletionItemProvider = () => {
|
2022-10-28 17:42:23 +08:00
|
|
|
|
// 参考 https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
|
2023-01-31 10:37:40 +08:00
|
|
|
|
self.completionItemProvider = self.completionItemProvider || monaco.languages.registerCompletionItemProvider('sql', {
|
2022-11-05 15:13:40 +08:00
|
|
|
|
triggerCharacters: ['.'],
|
2022-11-01 22:18:54 +08:00
|
|
|
|
provideCompletionItems: async (model: editor.ITextModel, position: Position): Promise<languages.CompletionList | null | undefined> => {
|
2022-10-28 17:42:23 +08:00
|
|
|
|
let word = model.getWordUntilPosition(position);
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const nowTab = state.tabs.get(state.activeName);
|
|
|
|
|
|
if (!nowTab) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-02-15 21:28:01 +08:00
|
|
|
|
const { db, dbId } = nowTab;
|
|
|
|
|
|
const dbInst = DbInst.getInst(dbId);
|
2022-11-05 15:13:40 +08:00
|
|
|
|
const { lineNumber, column } = position
|
|
|
|
|
|
const { startColumn, endColumn } = word
|
2022-11-01 22:18:54 +08:00
|
|
|
|
|
|
|
|
|
|
// 当前行文本
|
|
|
|
|
|
let lineContent = model.getLineContent(lineNumber);
|
|
|
|
|
|
// 注释行不需要代码提示
|
2022-11-05 15:13:40 +08:00
|
|
|
|
if (lineContent.startsWith('--')) {
|
|
|
|
|
|
return { suggestions: [] }
|
2022-11-01 22:18:54 +08:00
|
|
|
|
}
|
2022-11-05 15:13:40 +08:00
|
|
|
|
|
2022-10-28 17:42:23 +08:00
|
|
|
|
let range = {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
startLineNumber: lineNumber,
|
|
|
|
|
|
endLineNumber: lineNumber,
|
|
|
|
|
|
startColumn,
|
|
|
|
|
|
endColumn,
|
2022-10-28 17:42:23 +08:00
|
|
|
|
};
|
2022-11-05 15:13:40 +08:00
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 光标前文本
|
|
|
|
|
|
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+/)
|
|
|
|
|
|
const lastToken = tokens[tokens.length - 1].toLowerCase()
|
2023-06-13 14:54:52 +08:00
|
|
|
|
const secondToken = tokens.length >2 && tokens[tokens.length - 2].toLowerCase() || ''
|
2022-11-01 22:18:54 +08:00
|
|
|
|
|
2023-02-14 11:44:48 +08:00
|
|
|
|
const dbs = nowTab.params && nowTab.params.dbs;
|
2022-11-05 15:13:40 +08:00
|
|
|
|
// console.log("光标前文本:=>" + textBeforePointerMulti)
|
|
|
|
|
|
// console.log("最后输入的:=>" + lastToken)
|
2023-06-13 14:54:52 +08:00
|
|
|
|
if (lastToken.indexOf('.') > -1 || secondToken.indexOf('.') > -1) {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 如果是.触发代码提示,则进行【 库.表名联想 】 或 【 表别名.表字段联想 】
|
|
|
|
|
|
let str = lastToken.substring(0, lastToken.lastIndexOf('.'))
|
2023-06-13 14:54:52 +08:00
|
|
|
|
if(lastToken.trim().startsWith('.')){
|
|
|
|
|
|
str = secondToken
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 库.表名联想
|
2023-02-15 21:28:01 +08:00
|
|
|
|
|
2023-02-18 23:02:14 +08:00
|
|
|
|
if (dbs && dbs.filter((a: any) => a === str)?.length > 0) {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
let tables = await dbInst.loadTables(str)
|
2022-11-01 22:18:54 +08:00
|
|
|
|
let suggestions: languages.CompletionItem[] = []
|
2022-11-05 15:13:40 +08:00
|
|
|
|
for (let item of tables) {
|
|
|
|
|
|
const { tableName, tableComment } = item
|
2022-11-01 22:18:54 +08:00
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
2022-11-21 19:49:50 +08:00
|
|
|
|
label: tableName + (tableComment ? ' - ' + tableComment : ''),
|
2022-11-09 15:34:43 +08:00
|
|
|
|
description: 'table'
|
|
|
|
|
|
},
|
2022-11-01 22:18:54 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.File,
|
|
|
|
|
|
insertText: tableName,
|
|
|
|
|
|
range
|
2022-11-05 15:13:40 +08:00
|
|
|
|
});
|
2022-11-01 22:18:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
return { suggestions }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let sql = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1] + textAfterPointerMulti.split(';')[0];
|
|
|
|
|
|
// 表别名.表字段联想
|
2023-01-31 10:37:40 +08:00
|
|
|
|
let tableInfo = getTableByAlias(sql, db, str)
|
2022-11-05 15:13:40 +08:00
|
|
|
|
if (tableInfo.tableName) {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
let table = tableInfo.tableName
|
2023-02-13 21:11:16 +08:00
|
|
|
|
let db = tableInfo.dbName;
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 取出表名并提示
|
2023-02-13 21:11:16 +08:00
|
|
|
|
let dbHits = await dbInst.loadDbHints(db)
|
|
|
|
|
|
let columns = dbHits[table]
|
2022-11-01 22:18:54 +08:00
|
|
|
|
let suggestions: languages.CompletionItem[] = []
|
2023-02-14 12:23:38 +08:00
|
|
|
|
columns?.forEach((a: string, index: any) => {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 字段数据格式 字段名 字段注释, 如: create_time [datetime][创建时间]
|
2022-11-05 15:13:40 +08:00
|
|
|
|
const nameAndComment = a.split(" ")
|
|
|
|
|
|
const fieldName = nameAndComment[0]
|
2022-11-01 22:18:54 +08:00
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
|
|
|
|
|
label: a,
|
|
|
|
|
|
description: 'column'
|
|
|
|
|
|
},
|
2022-11-01 22:18:54 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.Property,
|
2022-11-05 15:13:40 +08:00
|
|
|
|
detail: '', // 不显示detail, 否则选中时备注等会被遮挡
|
2022-11-19 15:05:44 +08:00
|
|
|
|
insertText: fieldName + ' ', // create_time
|
2022-11-05 15:13:40 +08:00
|
|
|
|
range,
|
2022-11-05 21:08:01 +08:00
|
|
|
|
sortText: 100 + index + '' // 使用表字段声明顺序排序,排序需为字符串类型
|
2022-11-01 22:18:54 +08:00
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
return { suggestions }
|
|
|
|
|
|
}
|
2022-11-05 15:13:40 +08:00
|
|
|
|
return { suggestions: [] }
|
|
|
|
|
|
}
|
2022-10-28 17:42:23 +08:00
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 库名联想
|
|
|
|
|
|
|
|
|
|
|
|
let suggestions: languages.CompletionItem[] = []
|
|
|
|
|
|
// mysql关键字
|
2022-10-28 17:42:23 +08:00
|
|
|
|
sqlLanguage.keywords.forEach((item: any) => {
|
|
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
2022-11-21 19:49:50 +08:00
|
|
|
|
label: item,
|
2022-11-09 15:34:43 +08:00
|
|
|
|
description: 'keyword'
|
|
|
|
|
|
},
|
2022-10-28 17:42:23 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.Keyword,
|
|
|
|
|
|
insertText: item,
|
|
|
|
|
|
range
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
2022-11-19 15:05:44 +08:00
|
|
|
|
// 操作符
|
2022-10-28 17:42:23 +08:00
|
|
|
|
sqlLanguage.operators.forEach((item: any) => {
|
|
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
2022-11-21 19:49:50 +08:00
|
|
|
|
label: item,
|
2022-11-09 15:34:43 +08:00
|
|
|
|
description: 'opt'
|
|
|
|
|
|
},
|
2022-10-28 17:42:23 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.Operator,
|
|
|
|
|
|
insertText: item,
|
|
|
|
|
|
range
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 内置函数
|
2022-10-28 17:42:23 +08:00
|
|
|
|
sqlLanguage.builtinFunctions.forEach((item: any) => {
|
|
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
2022-11-21 19:49:50 +08:00
|
|
|
|
label: item,
|
2022-11-09 15:34:43 +08:00
|
|
|
|
description: 'func'
|
|
|
|
|
|
},
|
2022-10-28 17:42:23 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.Function,
|
|
|
|
|
|
insertText: item,
|
|
|
|
|
|
range
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 内置变量
|
|
|
|
|
|
sqlLanguage.builtinVariables.forEach((item: string) => {
|
2022-10-28 17:42:23 +08:00
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
2022-11-21 19:49:50 +08:00
|
|
|
|
label: item,
|
2022-11-09 15:34:43 +08:00
|
|
|
|
description: 'var'
|
|
|
|
|
|
},
|
2022-10-28 17:42:23 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.Variable,
|
|
|
|
|
|
insertText: item,
|
|
|
|
|
|
range
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
2022-11-01 22:18:54 +08:00
|
|
|
|
|
|
|
|
|
|
// 库名提示
|
2023-02-18 23:02:14 +08:00
|
|
|
|
if (dbs) {
|
|
|
|
|
|
dbs.forEach((a: any) => {
|
|
|
|
|
|
suggestions.push({
|
|
|
|
|
|
label: {
|
|
|
|
|
|
label: a,
|
|
|
|
|
|
description: 'schema'
|
|
|
|
|
|
},
|
|
|
|
|
|
kind: monaco.languages.CompletionItemKind.Folder,
|
|
|
|
|
|
insertText: a,
|
|
|
|
|
|
range
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2022-11-01 22:18:54 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
const tables = await dbInst.loadTables(db);
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 表名联想
|
2023-02-13 21:11:16 +08:00
|
|
|
|
tables.forEach((tableMeta: any) => {
|
2022-11-05 15:13:40 +08:00
|
|
|
|
const { tableName, tableComment } = tableMeta
|
2022-11-01 22:18:54 +08:00
|
|
|
|
suggestions.push({
|
2022-11-09 15:34:43 +08:00
|
|
|
|
label: {
|
2022-11-21 19:49:50 +08:00
|
|
|
|
label: tableName + ' - ' + tableComment,
|
2022-11-09 15:34:43 +08:00
|
|
|
|
description: 'table'
|
|
|
|
|
|
},
|
2022-11-01 22:18:54 +08:00
|
|
|
|
kind: monaco.languages.CompletionItemKind.File,
|
|
|
|
|
|
detail: tableComment,
|
2022-11-05 15:13:40 +08:00
|
|
|
|
insertText: tableName + ' ',
|
2022-11-01 22:18:54 +08:00
|
|
|
|
range
|
2022-11-05 15:13:40 +08:00
|
|
|
|
});
|
2022-11-01 22:18:54 +08:00
|
|
|
|
})
|
2022-10-29 20:08:15 +08:00
|
|
|
|
|
2022-10-28 17:42:23 +08:00
|
|
|
|
// 默认提示
|
|
|
|
|
|
return {
|
|
|
|
|
|
suggestions: suggestions
|
2022-11-05 15:13:40 +08:00
|
|
|
|
};
|
2022-10-28 17:42:23 +08:00
|
|
|
|
},
|
2022-10-29 20:08:15 +08:00
|
|
|
|
});
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
2022-10-29 20:08:15 +08:00
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据别名获取sql里的表名
|
|
|
|
|
|
* @param sql sql
|
|
|
|
|
|
* @param db 默认数据库
|
|
|
|
|
|
* @param alias 别名
|
|
|
|
|
|
*/
|
2022-11-05 15:13:40 +08:00
|
|
|
|
const getTableByAlias = (sql: string, db: string, alias: string): { dbName: string, tableName: string } => {
|
|
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 表别名:表名
|
|
|
|
|
|
let result = {};
|
|
|
|
|
|
let defName = '';
|
|
|
|
|
|
let defResult = {};
|
|
|
|
|
|
// 正则匹配取出表名和表别名
|
|
|
|
|
|
// 测试sql
|
|
|
|
|
|
/*
|
2022-11-19 15:05:44 +08:00
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
`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)
|
|
|
|
|
|
*/
|
2022-11-09 15:34:43 +08:00
|
|
|
|
let match = sql.match(/(join|from)\n*\s+\n*(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)\n*/gi)
|
2022-11-05 15:13:40 +08:00
|
|
|
|
if (match && match.length > 0) {
|
|
|
|
|
|
match.forEach(a => {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 去掉前缀,取出
|
|
|
|
|
|
let t = a.substring(5, a.length)
|
2022-11-09 15:34:43 +08:00
|
|
|
|
.replaceAll(/\s+/g, ' ')
|
|
|
|
|
|
.replaceAll(/\s+as\s+/gi, ' ')
|
|
|
|
|
|
.replaceAll(/\r\n/g, ' ').trim()
|
2022-11-01 22:18:54 +08:00
|
|
|
|
.split(/\s+/);
|
|
|
|
|
|
let withDb = t[0].split('.');
|
|
|
|
|
|
// 表名是 db名.表名
|
|
|
|
|
|
let tName = withDb.length > 1 ? withDb[1] : withDb[0]
|
2022-11-05 15:13:40 +08:00
|
|
|
|
let dbName = withDb.length > 1 ? withDb[0] : (db || '')
|
|
|
|
|
|
if (t.length == 2) {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 表别名:表名
|
2022-11-05 15:13:40 +08:00
|
|
|
|
result[t[1]] = { tableName: tName, dbName }
|
|
|
|
|
|
} else {
|
2022-11-01 22:18:54 +08:00
|
|
|
|
// 只有表名无别名 取第一个无别名的表为默认表
|
|
|
|
|
|
!defName && (defResult = { tableName: tName, dbName: db })
|
2022-10-28 17:42:23 +08:00
|
|
|
|
}
|
2022-11-01 22:18:54 +08:00
|
|
|
|
})
|
2022-10-28 17:42:23 +08:00
|
|
|
|
}
|
2022-11-01 22:18:54 +08:00
|
|
|
|
return result[alias] || defResult
|
2022-10-28 17:42:23 +08:00
|
|
|
|
}
|
2021-06-07 17:22:07 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
2022-03-15 22:27:39 +08:00
|
|
|
|
<style lang="scss">
|
2022-11-22 00:34:42 +08:00
|
|
|
|
.sql-file-exec {
|
2022-11-22 17:15:08 +08:00
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
text-decoration: none;
|
2022-11-22 00:34:42 +08:00
|
|
|
|
}
|
2022-11-22 17:15:08 +08:00
|
|
|
|
|
2022-04-10 10:41:14 +08:00
|
|
|
|
.sqlEditor {
|
|
|
|
|
|
font-size: 8pt;
|
2022-01-12 16:00:31 +08:00
|
|
|
|
font-weight: 600;
|
2022-04-10 10:41:14 +08:00
|
|
|
|
border: 1px solid #ccc;
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
2022-10-29 20:08:15 +08:00
|
|
|
|
|
2022-11-01 22:18:54 +08:00
|
|
|
|
.editor-move-resize {
|
|
|
|
|
|
cursor: n-resize;
|
|
|
|
|
|
height: 3px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-01-16 19:40:20 +08:00
|
|
|
|
.el-tabs__header {
|
2022-01-19 15:10:17 +08:00
|
|
|
|
padding: 0 10px;
|
2022-01-16 19:40:20 +08:00
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
}
|
2022-02-07 17:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
#data-exec {
|
|
|
|
|
|
min-height: calc(100vh - 155px);
|
2023-02-06 17:14:16 +08:00
|
|
|
|
|
|
|
|
|
|
.el-tabs__header {
|
|
|
|
|
|
margin: 0 0 5px;
|
|
|
|
|
|
|
|
|
|
|
|
.el-tabs__item {
|
|
|
|
|
|
padding: 0 5px;
|
|
|
|
|
|
}
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
2022-02-07 17:49:48 +08:00
|
|
|
|
}
|
2022-11-22 17:15:08 +08:00
|
|
|
|
|
|
|
|
|
|
.update_field_active {
|
|
|
|
|
|
background-color: var(--el-color-success)
|
2022-11-22 00:34:42 +08:00
|
|
|
|
}
|
2023-02-18 23:02:14 +08:00
|
|
|
|
|
|
|
|
|
|
.instances-pop-form {
|
|
|
|
|
|
.el-form-item {
|
|
|
|
|
|
margin-bottom: unset;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-06-07 17:22:07 +08:00
|
|
|
|
</style>
|