mirror of
https://gitee.com/dromara/dbswitch.git
synced 2025-10-15 06:10:23 +00:00
前端在线SQL执行
This commit is contained in:
164
dbswitch-admin-ui/package-lock.json
generated
164
dbswitch-admin-ui/package-lock.json
generated
@@ -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",
|
||||
|
@@ -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",
|
||||
|
@@ -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')
|
||||
|
@@ -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>
|
||||
|
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-dialog title="添加数据库驱动JAR说明"
|
||||
<el-dialog title="添加说明"
|
||||
:visible.sync="dialogVisible"
|
||||
width="40%"
|
||||
:before-close="handleClose">
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
Reference in New Issue
Block a user