前端在线SQL执行

This commit is contained in:
inrgihc
2024-05-23 21:43:38 +08:00
parent 944c7df17d
commit 52c899e770
58 changed files with 718 additions and 338 deletions

View File

@@ -11,6 +11,7 @@
"echarts": "^4.9.0",
"element-ui": "^2.15.6",
"qs": "^6.11.2",
"sql-formatter": "^15.3.1",
"urlencode": "^1.1.0",
"vue": "^2.5.2",
"vue-count-to": "^1.0.13",
@@ -3892,6 +3893,11 @@
"node": ">=4"
}
},
"node_modules/discontinuous-range": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="
},
"node_modules/dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -7140,6 +7146,11 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/moo": {
"version": "0.5.2",
"resolved": "https://registry.npmmirror.com/moo/-/moo-0.5.2.tgz",
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
},
"node_modules/move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -7225,6 +7236,28 @@
"dev": true,
"optional": true
},
"node_modules/nearley": {
"version": "2.20.1",
"resolved": "https://registry.npmmirror.com/nearley/-/nearley-2.20.1.tgz",
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
"dependencies": {
"commander": "^2.19.0",
"moo": "^0.5.0",
"railroad-diagrams": "^1.0.0",
"randexp": "0.4.6"
},
"bin": {
"nearley-railroad": "bin/nearley-railroad.js",
"nearley-test": "bin/nearley-test.js",
"nearley-unparse": "bin/nearley-unparse.js",
"nearleyc": "bin/nearleyc.js"
}
},
"node_modules/nearley/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
@@ -10867,6 +10900,23 @@
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"dev": true
},
"node_modules/railroad-diagrams": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="
},
"node_modules/randexp": {
"version": "0.4.6",
"resolved": "https://registry.npmmirror.com/randexp/-/randexp-0.4.6.tgz",
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
"dependencies": {
"discontinuous-range": "1.0.0",
"ret": "~0.1.10"
},
"engines": {
"node": ">=0.12"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
@@ -11322,7 +11372,6 @@
"version": "0.1.15",
"resolved": "https://registry.npmmirror.com/ret/-/ret-0.1.15.tgz",
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
"dev": true,
"engines": {
"node": ">=0.12"
}
@@ -12136,6 +12185,32 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"node_modules/sql-formatter": {
"version": "15.3.1",
"resolved": "https://registry.npmmirror.com/sql-formatter/-/sql-formatter-15.3.1.tgz",
"integrity": "sha512-L/dqan+Hrt0PpPdCbHcI9bdfOvqaQZR7v5c5SWMJ3bUGQSezK09Mm9q2I3B4iObjaq7FyoldIM+fDSmfzGRXCA==",
"dependencies": {
"argparse": "^2.0.1",
"get-stdin": "=8.0.0",
"nearley": "^2.20.1"
},
"bin": {
"sql-formatter": "bin/sql-formatter-cli.cjs"
}
},
"node_modules/sql-formatter/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/sql-formatter/node_modules/get-stdin": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-8.0.0.tgz",
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
"engines": {
"node": ">=10"
}
},
"node_modules/ssri": {
"version": "5.3.0",
"resolved": "https://registry.npmmirror.com/ssri/-/ssri-5.3.0.tgz",
@@ -13301,6 +13376,18 @@
"vue": "^2.5.9"
}
},
"node_modules/vue-drag-resize": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/vue-drag-resize/-/vue-drag-resize-1.5.4.tgz",
"integrity": "sha512-SR3U7n6TAZEBgP7zw7bR9mjtAlYBjqIoaWTDPz5HXN/nYhOxKSA31aD7p71fmq1jtyt9reAnCx62valNL9ZAcg==",
"dependencies": {
"vue-drag-resize": "^1.5.0-rc3"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/vue-hot-reload-api": {
"version": "2.3.4",
"resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
@@ -17978,6 +18065,11 @@
"path-type": "^3.0.0"
}
},
"discontinuous-range": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="
},
"dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -20643,6 +20735,11 @@
"minimist": "^1.2.6"
}
},
"moo": {
"version": "0.5.2",
"resolved": "https://registry.npmmirror.com/moo/-/moo-0.5.2.tgz",
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -20716,6 +20813,24 @@
"dev": true,
"optional": true
},
"nearley": {
"version": "2.20.1",
"resolved": "https://registry.npmmirror.com/nearley/-/nearley-2.20.1.tgz",
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
"requires": {
"commander": "^2.19.0",
"moo": "^0.5.0",
"railroad-diagrams": "^1.0.0",
"randexp": "0.4.6"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}
}
},
"negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
@@ -23738,6 +23853,20 @@
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"dev": true
},
"railroad-diagrams": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="
},
"randexp": {
"version": "0.4.6",
"resolved": "https://registry.npmmirror.com/randexp/-/randexp-0.4.6.tgz",
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
"requires": {
"discontinuous-range": "1.0.0",
"ret": "~0.1.10"
}
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
@@ -24123,8 +24252,7 @@
"ret": {
"version": "0.1.15",
"resolved": "https://registry.npmmirror.com/ret/-/ret-0.1.15.tgz",
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
"dev": true
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
},
"rgb-regex": {
"version": "1.0.1",
@@ -24818,6 +24946,28 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"sql-formatter": {
"version": "15.3.1",
"resolved": "https://registry.npmmirror.com/sql-formatter/-/sql-formatter-15.3.1.tgz",
"integrity": "sha512-L/dqan+Hrt0PpPdCbHcI9bdfOvqaQZR7v5c5SWMJ3bUGQSezK09Mm9q2I3B4iObjaq7FyoldIM+fDSmfzGRXCA==",
"requires": {
"argparse": "^2.0.1",
"get-stdin": "=8.0.0",
"nearley": "^2.20.1"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"get-stdin": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-8.0.0.tgz",
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg=="
}
}
},
"ssri": {
"version": "5.3.0",
"resolved": "https://registry.npmmirror.com/ssri/-/ssri-5.3.0.tgz",
@@ -25787,6 +25937,14 @@
"vue": "^2.5.9"
}
},
"vue-drag-resize": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/vue-drag-resize/-/vue-drag-resize-1.5.4.tgz",
"integrity": "sha512-SR3U7n6TAZEBgP7zw7bR9mjtAlYBjqIoaWTDPz5HXN/nYhOxKSA31aD7p71fmq1jtyt9reAnCx62valNL9ZAcg==",
"requires": {
"vue-drag-resize": "^1.5.0-rc3"
}
},
"vue-hot-reload-api": {
"version": "2.3.4",
"resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",

View File

@@ -14,6 +14,7 @@
"echarts": "^4.9.0",
"element-ui": "^2.15.6",
"qs": "^6.11.2",
"sql-formatter": "^15.3.1",
"urlencode": "^1.1.0",
"vue": "^2.5.2",
"vue-count-to": "^1.0.13",

View File

@@ -121,14 +121,14 @@ const constantRouter = new Router({
},
{
path: '/connection/list/addDataSource1',
name: '接入数据源',
name: '数据源创建步骤1',
icon: "el-icon-menu",
hidden: true,
component: () => import('@/views/connection/addDataSource1.vue')
},
{
path: '/connection/list/addDataSource2',
name: '接入数据源',
name: '数据源创建步骤2',
icon: "el-icon-menu",
hidden: true,
component: () => import('@/views/connection/addDataSource2.vue')

View File

@@ -144,7 +144,7 @@
<el-row style="text-align: center">
<el-button type="success"
class="startTest"
@click="startTest">开始检测</el-button>
@click="startTest">测</el-button>
<el-button type="primary"
class="createDataSource"
@click="createDataSource">创建</el-button>

View File

@@ -53,7 +53,7 @@
</div>
</div>
</el-card>
<el-dialog title="添加数据库驱动JAR说明"
<el-dialog title="添加说明"
:visible.sync="dialogVisible"
width="40%"
:before-close="handleClose">

View File

@@ -41,7 +41,7 @@
</el-form-item>
<el-form-item :required=true
label="数据库类型">
<label>{{ this.selectedDataSource.name }}</label>
<label>{{ this.updateform.type }}</label>
</el-form-item>
<el-form-item prop="version"
label="驱动版本">
@@ -144,7 +144,7 @@
<el-row style="text-align: center">
<el-button type="success"
class="startTest"
@click="startTest">开始检测</el-button>
@click="startTest">测</el-button>
<el-button type="primary"
class="createDataSource"
@click="updateDataSource">修改</el-button>

View File

@@ -1,38 +1,46 @@
<template>
<div>
<el-card>
<div class="flex-between">
<div class="tree-container">
<el-select placeholder="请选择数据"
v-model="dataSourceId"
@change="loadTreeData">
<el-option v-for="(item,index) in connectionList"
:key="index"
:label="`[${item.id}]${item.name}`"
:value="item.id"></el-option>
</el-select>
<el-scrollbar style="height: 800px;">
<el-tree ref="metadataTree"
empty-text="请选择数据源后查看"
:indent=6
:data="treeData"
:props="props"
:load="loadTreeNode"
:expand-on-click-node="true"
:highlight-current="true"
:render-content="renderContent"
@node-click="handleNodeClick"
lazy>
</el-tree>
</el-scrollbar>
</div>
<div class="table-container">
<el-tabs v-model="tabActiveTabName"
type="border-card">
<el-tab-pane label="元数据"
name="metadata">
<el-tabs v-model="tabActiveTabName"
type="border-card">
<el-tab-pane label="数据"
name="metadata">
<div class="flex-between">
<el-aside>
<div class="select-datasource-container">
<el-select placeholder="请选择数据源"
v-model="dataSourceId"
@change="loadTreeData">
<el-option v-for="(item,index) in connectionList"
:key="index"
:label="`[${item.id}]${item.name}`"
:value="item.id"></el-option>
</el-select>
<el-button type="primary"
size="mini"
:disabled="metadataLoading"
icon="el-icon-refresh"
@click="loadTreeData">刷新</el-button>
</div>
<el-scrollbar style="height: 800px;">
<el-tree ref="metadataTree"
empty-text="请选择数据源后查看"
:indent=6
:data="treeData"
:props="props"
:load="loadTreeNode"
:expand-on-click-node="true"
:highlight-current="true"
:render-content="renderContent"
@node-click="handleNodeClick"
lazy>
</el-tree>
</el-scrollbar>
</el-aside>
<el-main class="metadata-container">
当前表<el-tag size="medium">{{currentNode.schemaName}} / {{currentNode.tableName}}</el-tag>
<el-tabs v-model="metadataActiveTabName">
<el-tabs v-model="metadataActiveTabName"
type="border-card">
<el-tab-pane label="基本信息"
name="first">
<el-descriptions size="small"
@@ -64,7 +72,7 @@
border
style="width: 100%">
<template slot="empty">
<span>单击左侧展开"数据源导航树"来查看表的元数据记录</span>
<span>单击点击左侧节点查看对应表的字段信息</span>
</template>
<el-table-column prop="fieldName"
min-width="20%"
@@ -73,11 +81,11 @@
</el-table-column>
<el-table-column prop="typeName"
min-width="20%"
label="类型">
label="数据类型">
</el-table-column>
<el-table-column prop="fieldType"
min-width="7%"
label="枚举">
label="类型枚举">
</el-table-column>
<el-table-column prop="displaySize"
min-width="7%"
@@ -118,7 +126,7 @@
border
style="width: 100%">
<template slot="empty">
<span>单击左侧展开"数据源导航树"来查看表的元数据记录</span>
<span>单击点击左侧节点查看对应表的索引信息</span>
</template>
<el-table-column prop="indexType"
min-width="20%"
@@ -143,7 +151,7 @@
:data="sampleData.rows"
border>
<template slot="empty">
<span>单击左侧展开"数据源导航树"来查看表的数据记录</span>
<span>单击点击左侧节点查看对应表的取样数据</span>
</template>
<el-table-column v-for="(item,index) in sampleData.columns"
:prop="item"
@@ -154,14 +162,111 @@
</el-table>
</el-tab-pane>
</el-tabs>
</el-tab-pane>
<!-- <el-tab-pane label="SQL在线"
name="sqlQuery">
<multi-sql-editor ref="sqlEditors"></multi-sql-editor>
</el-tab-pane> -->
</el-tabs>
</div>
</div>
</el-main>
</div>
</el-tab-pane>
<el-tab-pane label="SQL在线"
name="sqlQuery">
<el-row :gutter=12
class="padding-row-stype">
<el-col :span="6">
<div class="sqlonline-select-suffix">
<span class="text-label">数据源</span>
<el-select size="small"
placeholder="请选择数据源"
v-model="sqlDataSourceId">
<el-option v-for="(item,index) in connectionList"
:key="index"
:label="`[${item.id}]${item.name}`"
:value="item.id"></el-option>
</el-select>
</div>
</el-col>
<el-col :span="6">
<div class="sqlonline-select-suffix">
<span class="text-label">最大记录数</span>
<el-select size="small"
placeholder="选择结果集MaxRow"
v-model="rsMaxRowCount">
<el-option v-for="(item,index) in maxRowCountList"
:key="index"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</div>
</el-col>
<el-col :span="6">
<div class="sqlonline-select-suffix">
<span class="text-label">编辑器高度</span>
<el-input-number v-model="editorHeightNum"
size="small"
:step="10"
step-strictly></el-input-number>
</div>
</el-col>
<el-col :span="6">
<div class="tool">
<div class="item-button"
@click="runAll"><i class="el-icon-video-play"></i><span>执行</span></div>
<div class="item-button"
@click="runSelected"><i class="el-icon-caret-right"></i><span>选中执行</span></div>
<div class="item-button"
@click="formatSql"><i class="el-icon-postcard"></i><span>格式化</span></div>
</div>
</el-col>
</el-row>
<el-row class="padding-row-stype">
</el-row>
<el-row class="padding-row-stype">
<div v-loading="sqlResultLoading"
:style="'height: ' + editorHeightNum + 'px'">
<ace ref="sqlEditor"
@init="initEditor"
lang="sql"
width="100%"
height="100%"
theme="monokai"
:options="sqlEditorOption">
</ace>
</div>
</el-row>
<el-row class="padding-row-stype">
<el-tabs v-model="activeResultTab"
tab-position="top"
type="border-card">
<el-tab-pane label="信息"
name="0">
<div v-for="(one,idx) in sqlExecuteResult.summaries"
:key="idx">
[SQL]: {{one.sql}}<br />{{one.summary}}<br /><br />
</div>
</el-tab-pane>
<el-tab-pane v-for="(one,idx) in sqlExecuteResult.results"
:key="(idx+1)"
:label="'结果'+(idx+1)"
:name="''+(idx+1)">
<el-table :header-cell-style="{background:'#eef1f6',color:'#606266','font-size': '12px'}"
style="width: 100%; max-height: 400px; overflow: auto;"
height="400px"
:data="one.rows"
border>
<template slot="empty">
<span>SQL结果为空</span>
</template>
<el-table-column v-for="(item,index) in one.columns"
:prop="item.columnName"
:key="index"
show-overflow-tooltip>
<template slot="header">
{{item.columnName}}<br />({{item.columnType}})
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</el-row>
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</template>
@@ -169,14 +274,15 @@
<script>
import urlencode from "urlencode";
import ace from 'vue2-ace-editor'
const sqlformatter = require("sql-formatter");
// 参考文章https://blog.csdn.net/m0_50255772/article/details/109484828
export default {
components: {
ace
},
data () {
return {
metadataLoading: false,
props: {
label: 'label',
children: 'children',
@@ -210,7 +316,34 @@ export default {
columns: []
},
count: 1,
sampleData: []
sampleData: [],
sqlDataSourceId: null,
sqlEditorOption: {
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
showPrintMargin: false,
showLineNumbers: true,
tabSize: 6,
fontSize: 18,
},
rsMaxRowCount: 200,
maxRowCountList: [
{ id: 100, name: '100条' },
{ id: 200, name: '200条' },
{ id: 500, name: '500条' },
{ id: 1000, name: '1000条' },
{ id: 2000, name: '2000条' },
{ id: 5000, name: '5000条' },
{ id: 10000, name: '10000条' },
],
editorHeightNum: 200,
sqlResultLoading: false,
sqlExecuteResult: {
summaries: [],
results: [],
},
activeResultTab: "0",
};
},
methods: {
@@ -248,12 +381,14 @@ export default {
loadTreeData: function () {
if (this.dataSourceId && this.dataSourceId > 0) {
this.treeData = []
this.metadataLoading = true;
setTimeout(() => {
this.$http({
method: "GET",
url: "/dbswitch/admin/api/v1/connection/schemas/get/" + this.dataSourceId
}).then(
res => {
this.metadataLoading = false;
if (0 === res.data.code) {
for (let element of res.data.data) {
let obj = new Object();
@@ -304,11 +439,13 @@ export default {
},
loadTablesList: function (resolve, dataSourceId, schema, type) {
var tableType = 'VIEW' === type ? 'views' : 'tables'
this.metadataLoading = true;
this.$http({
method: "GET",
url: "/dbswitch/admin/api/v1/connection/" + tableType + "/get/" + dataSourceId + "?schema=" + urlencode(schema)
}).then(
res => {
this.metadataLoading = false;
if (0 === res.data.code) {
let tableList = []
for (let element of res.data.data) {
@@ -400,6 +537,7 @@ export default {
if (!data.hasChild && datasourceId && schema && table) {
this.tabActiveTabName = 'metadata';
this.metadataActiveTabName = 'first';
this.clearDataSet();
this.getTableMeta(datasourceId, schema, table);
this.getTableData(datasourceId, schema, table);
}
@@ -415,8 +553,8 @@ export default {
createSql: "",
primaryKeys: [],
columns: []
},
this.sampleData = []
};
this.sampleData = []
},
getTableMeta (id, schema, table) {
this.$http({
@@ -431,7 +569,6 @@ export default {
this.currentNode.schemaName = schema;
} else {
this.$alert("加载失败,原因:" + res.data.message, '数据加载失败');
this.clearDataSet();
}
}
);
@@ -447,7 +584,6 @@ export default {
//console.log(this.sampleData)
} else {
this.$alert("加载失败,原因:" + res.data.message, '数据加载失败');
this.clearDataSet();
}
}
);
@@ -477,6 +613,78 @@ export default {
}
);
},
formatSql: function () {
if (this.sqlResultLoading === true) {
return
}
let editor = this.$refs.sqlEditor.editor;
let sqlcontent = editor.getSelectedText();
if (sqlcontent && sqlcontent.length > 0) {
let formatSql = sqlformatter.format(sqlcontent)
editor.session.replace(editor.getSelectionRange(), formatSql);
} else {
sqlcontent = editor.getValue();
if (!sqlcontent || sqlcontent.length === 0) {
alert("SQL文本内容为空");
return
}
editor.setValue(sqlformatter.format(editor.getValue()));
}
},
runAll: function () {
let editor = this.$refs.sqlEditor.editor;
let sqlcontent = editor.getValue();
if (!sqlcontent || 0 === sqlcontent.length) {
alert("SQL文本内容为空");
return
}
this.executeSqlScript(sqlcontent)
},
runSelected: function () {
let editor = this.$refs.sqlEditor.editor;
let sqlcontent = editor.getSelectedText();
if (!sqlcontent || 0 === sqlcontent.length) {
alert("请首先选择SQL文本内容");
return
}
this.executeSqlScript(sqlcontent)
},
executeSqlScript: function (sqlScript) {
if (this.sqlResultLoading === true) {
alert("已有一个查询正在进行中");
return
}
if (!this.sqlDataSourceId || this.dataSourceId < 0) {
alert("请首先选择一个数据源来");
return
}
this.sqlResultLoading = true;
this.sqlExecuteResult = {
summaries: [],
results: [],
};
this.$http({
method: "POST",
headers: {
'Content-Type': 'application/json'
},
url: "/dbswitch/admin/api/v1/metadata/data/sql/" + this.sqlDataSourceId,
data: JSON.stringify({
script: sqlScript,
page: 1,
size: this.rsMaxRowCount
})
}).then(res => {
this.sqlResultLoading = false;
if (0 === res.data.code) {
this.sqlExecuteResult = res.data.data;
this.activeResultTab = "0";
} else {
alert("SQL执行报错:" + res.data.message);
}
}
);
},
},
created () {
this.loadConnections();
@@ -521,8 +729,12 @@ export default {
.tree-container .tree {
overflow: auto;
}
.metadata-container {
padding: 4px;
}
.table-container {
width: 100%;
border: darkblue;
}
.table-container-data-table {
height: 90%;
@@ -551,4 +763,35 @@ el-tabs--border-card > .el-tabs__header .el-tabs__item {
background-color: #0065d5;
color: #ffffff;
}
.sqlonline-select-suffix {
display: flex;
justify-content: flex-start;
align-items: center; /* 垂直居中 */
}
.text-label {
font-size: 11px;
font-weight: 700;
}
.select-datasource-container {
display: flex;
}
.tool {
display: flex;
justify-content: flex-end;
}
.tool .item-button {
display: inline-block;
font-size: 20px;
color: #009966;
margin: 0 20px 0 0;
line-height: 26px;
cursor: pointer;
}
.tool .item-button span {
color: #000;
font-size: 16px;
}
.padding-row-stype {
padding: 5px;
}
</style>

View File

@@ -1,121 +0,0 @@
<template>
<div>
<div class="tool">
<div class="item-button"><i class="iconfont icon-play"></i><span>执行</span></div>
<div class="item-button"><i class="iconfont icon-play"></i><span>执行选中</span></div>
<div class="item-button"><i class="iconfont icon-play"></i><span>格式化</span></div>
</div>
<ace ref="editor"
:value="content"
@init="initEditor"
:lang="lang"
:height="height === 0 ? '100%' : height"
:theme="theme"
:options="options"
width="100%"
v-bind="config">
</ace>
</div>
</template>
<script>
import ace from 'vue2-ace-editor'
export default {
name: "multiSqlEditer",
components: {
ace
},
data () {
return {
}
},
props: {
content: {
type: String,
default: ''
},
height: {
type: Number,
default: 300
},
readOnly: {
type: Boolean,
default: false
},
theme: {
type: String,
default: 'monokai'
},
lang: {
type: String,
default: 'sql'
},
config: {
type: Object,
default: () => {
return {
font_size: 16,
sql_atom: true
}
}
}
},
computed: {
options () {
if (this.readOnly) {
return {
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: this.config.sql_atom,
showPrintMargin: false,
fontSize: this.config.font_size,
readOnly: true
}
}
return {
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: this.config.sql_atom,
showPrintMargin: false,
fontSize: this.config.font_size
}
}
},
methods: {
initEditor (editor) {
require('brace/ext/language_tools')
// 设置语言
require('brace/mode/sql')
require('brace/snippets/sql')
// 设置主题 按需加载
require('brace/theme/monokai')
require('brace/theme/chrome')
require('brace/theme/crimson_editor')
// 监听值的变化
editor.getSession().on('change', val => {
this.$emit('change', editor.getValue())
})
},
},
mounted () {
},
created () {
},
}
</script>
<style scoped>
.tool .item-button {
display: inline-block;
font-size: 20px;
color: #009966;
margin: 0 20px 0 0;
line-height: 26px;
cursor: pointer;
}
.tool .item-button span {
color: #000;
font-size: 16px;
}
</style>