db模块tab页面增加右键菜单

This commit is contained in:
diant
2023-05-24 16:44:29 +08:00
parent 960eccd165
commit e456d4e95e
10 changed files with 671 additions and 462 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon-db.png"><title>数据库文档管理</title><link href="css/chunk-vendors.2fa4c9b3.css" rel="preload" as="style"><link href="css/index.108f40b4.css" rel="preload" as="style"><link href="js/chunk-vendors.6270548d.js" rel="preload" as="script"><link href="js/index.ddad9e6e.js" rel="preload" as="script"><link href="css/chunk-vendors.2fa4c9b3.css" rel="stylesheet"><link href="css/index.108f40b4.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.6270548d.js"></script><script src="js/index.ddad9e6e.js"></script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon-db.png"><title>数据库文档管理</title><link href="css/chunk-vendors.2fa4c9b3.css" rel="preload" as="style"><link href="css/index.acbccf83.css" rel="preload" as="style"><link href="js/chunk-vendors.6270548d.js" rel="preload" as="script"><link href="js/index.790e04cd.js" rel="preload" as="script"><link href="css/chunk-vendors.2fa4c9b3.css" rel="stylesheet"><link href="css/index.acbccf83.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.6270548d.js"></script><script src="js/index.790e04cd.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,200 +1,350 @@
<template>
<div>
<el-tabs v-model="activePage" type="card" closable @tab-click="changePage" @tab-remove="removePageTab" style="padding: 5px 10px 0;">
<el-tab-pane :label="pageTabNameMap[item.fullPath]||item.name" :name="getRouteRealPath(item)" :fullPath="item.fullPath" :key="item.fullPath" v-for="item in pageList"/>
</el-tabs>
<keep-alive>
<router-view v-on:listenToChildEvent = "getDatafromChild" :key="$route.fullPath" @initLoadDataList="initLoadDataList" @loadDatasourceList="loadDatasourceList"/>
</keep-alive>
</div>
<div>
<el-tabs v-model="activePage" type="card" closable @tab-click="changePage" @tab-remove="removePageTab"
@contextmenu.prevent.native="openContextMenu($event)" style="padding: 5px 10px 0;">
<el-tab-pane :label="pageTabNameMap[item.fullPath]||item.name" :name="getRouteRealPath(item)"
:fullPath="item.fullPath" :key="item.fullPath" v-for="item in pageList"/>
</el-tabs>
<keep-alive>
<router-view v-on:listenToChildEvent="getDatafromChild" :key="$route.fullPath"
@initLoadDataList="initLoadDataList" @loadDatasourceList="loadDatasourceList"/>
</keep-alive>
<ul v-show="contextMenuVisible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
<!--<li @click="curTabReload()"><el-button type="text" size="mini">重新加载</el-button></li>-->
<li @click="closeAllTabs()">
<el-button type="text" size="mini">关闭所有</el-button>
</li>
<li @click="closeOtherTabs('left')">
<el-button type="text" size="mini">关闭左边</el-button>
</li>
<li @click="closeOtherTabs('right')">
<el-button type="text" size="mini">关闭右边</el-button>
</li>
<li @click="closeOtherTabs('other')">
<el-button type="text" size="mini">关闭其他</el-button>
</li>
</ul>
</div>
</template>
<script>
import datasourceApi from "@/common/api/datasource";
import datasourceApi from "@/common/api/datasource";
export default {
name: 'PageTableView',
components: {},
data() {
return {
pageList: [],
linkList: [],
activePage: '',
datasourceList: [],
multiPage: true,
ignoreParamPath: [
"/data/export",
],
}
},
computed: {
pageTabNameMap () {
return this.$store.state.global.pageTabNameMap;
}
},
created() {
let {name, path, fullPath} = this.$route;
//sql执行器tab页名称动态变化
if(path === '/data/executor'){
let database = this.$route.query.database;
let datasourceId = this.$route.query.datasourceId;
if(datasourceId){
datasourceApi.datasource({sourceId: datasourceId}).then(json => {
let dataname = json.data.name;
let groupName = json.data.name;
if(dataname){
name = name+"( "+dataname+"["+database+"] )"
}
this.pageList.push({name, path, fullPath});
let activePage = this.getRouteRealPath(this.$route);
this.linkList.push(activePage);
this.activePage = activePage;
this.$router.push(this.$route.fullPath);
})
return false;
}else{
datasourceApi.datasourceList({}).then(json => {
this.datasourceList = json.data || [];
if (this.datasourceList.length > 0) {
let dataname = this.datasourceList[0].name;
if(this.datasourceList[0].id){
datasourceApi.databaseList({sourceId: this.datasourceList[0].id}).then(json => {
if (json.data.length > 0) {
// 排除系统库
let sysDbName = ["information_schema", "master", "model", "msdb", "tempdb"];
let notSysDbItem = json.data.find(item => sysDbName.indexOf(item.dbName) < 0);
let choiceDatabase = (!!notSysDbItem) ? notSysDbItem.dbName : json.data[0].dbName;
if(dataname&&choiceDatabase){
name = name+"( "+dataname+"["+choiceDatabase+"] )"
}
this.$router.replace({ query: { datasourceId: this.datasourceList[0].id,database:choiceDatabase } })
}
})
}
}
})
return false;
}
}
this.pageList.push({name, path, fullPath});
let activePage = this.getRouteRealPath(this.$route);
this.linkList.push(activePage);
this.activePage = activePage;
this.$router.push(this.$route.fullPath);
},
watch: {
'$route': function (newRoute, oldRoute) {
let activePage = this.getRouteRealPath(newRoute);
this.activePage = activePage;
if (this.linkList.indexOf(activePage) < 0) {
export default {
name: 'PageTableView',
components: {},
data() {
return {
pageList: [],
linkList: [],
activePage: '',
datasourceList: [],
multiPage: true,
ignoreParamPath: [
"/data/export",
],
contextMenuVisible: false,
left: 0,
top: 0,
}
},
computed: {
pageTabNameMap() {
return this.$store.state.global.pageTabNameMap;
}
},
created() {
let {name, path, fullPath} = this.$route;
//sql执行器tab页名称动态变化
if (path === '/data/executor') {
let database = this.$route.query.database;
let datasourceId = this.$route.query.datasourceId;
if (datasourceId) {
datasourceApi.datasource({sourceId: datasourceId}).then(json => {
let dataname = json.data.name;
let groupName = json.data.name;
if (dataname) {
name = name + "( " + dataname + "[" + database + "] )"
}
this.pageList.push({name, path, fullPath});
let activePage = this.getRouteRealPath(this.$route);
this.linkList.push(activePage);
let {name, path, fullPath} = newRoute;
this.pageList.push({name, path, fullPath});
//sql执行器tab页名称动态变化
if(path === '/data/executor'){
let database = newRoute.query.database;
let datasourceId = newRoute.query.datasourceId;
if(datasourceId) {
datasourceApi.datasource({sourceId: datasourceId}).then(json => {
this.activePage = activePage;
this.$router.push(this.$route.fullPath);
})
return false;
} else {
datasourceApi.datasourceList({}).then(json => {
this.datasourceList = json.data || [];
if (this.datasourceList.length > 0) {
let dataname = this.datasourceList[0].name;
if (this.datasourceList[0].id) {
datasourceApi.databaseList({sourceId: this.datasourceList[0].id}).then(json => {
if (json.data.length > 0) {
// 排除系统库
let sysDbName = ["information_schema", "master", "model", "msdb", "tempdb"];
let notSysDbItem = json.data.find(item => sysDbName.indexOf(item.dbName) < 0);
let choiceDatabase = (!!notSysDbItem) ? notSysDbItem.dbName : json.data[0].dbName;
if (dataname && choiceDatabase) {
name = name + "( " + dataname + "[" + choiceDatabase + "] )"
}
this.$router.replace({
query: {
datasourceId: this.datasourceList[0].id,
database: choiceDatabase
}
})
}
})
}
}
})
return false;
}
}
this.pageList.push({name, path, fullPath});
let activePage = this.getRouteRealPath(this.$route);
this.linkList.push(activePage);
this.activePage = activePage;
this.$router.push(this.$route.fullPath);
},
watch: {
'$route': function (newRoute, oldRoute) {
let activePage = this.getRouteRealPath(newRoute);
this.activePage = activePage;
if (this.linkList.indexOf(activePage) < 0) {
this.linkList.push(activePage);
let {name, path, fullPath} = newRoute;
this.pageList.push({name, path, fullPath});
//sql执行器tab页名称动态变化
if (path === '/data/executor') {
let database = newRoute.query.database;
let datasourceId = newRoute.query.datasourceId;
if (datasourceId) {
datasourceApi.datasource({sourceId: datasourceId}).then(json => {
let dataname = json.data.name;
let groupName = json.data.groupName;
if (dataname) {
name = name+"( "+dataname+"["+database+"] )"
name = name + "( " + dataname + "[" + database + "] )"
}
//this.pageList.push({name, path, fullPath});
let pageRoute = this.pageList.find(item => this.getRouteRealPath(item) === activePage);
pageRoute.name = name;
//this.pageList.push({name, path, fullPath});
let pageRoute = this.pageList.find(item => this.getRouteRealPath(item) === activePage);
pageRoute.name = name;
})
}else{
datasourceApi.datasourceList({}).then(json => {
this.datasourceList = json.data || [];
if (this.datasourceList.length > 0) {
let dataname = this.datasourceList[0].name;
if(this.datasourceList[0].id){
})
} else {
datasourceApi.datasourceList({}).then(json => {
this.datasourceList = json.data || [];
if (this.datasourceList.length > 0) {
let dataname = this.datasourceList[0].name;
if (this.datasourceList[0].id) {
datasourceApi.databaseList({sourceId: this.datasourceList[0].id}).then(json => {
if (json.data.length > 0) {
// 排除系统库
let sysDbName = ["information_schema", "master", "model", "msdb", "tempdb"];
let notSysDbItem = json.data.find(item => sysDbName.indexOf(item.dbName) < 0);
let choiceDatabase = (!!notSysDbItem) ? notSysDbItem.dbName : json.data[0].dbName;
if(dataname&&choiceDatabase){
name = name+"( "+dataname+"["+choiceDatabase+"] )"
if (dataname && choiceDatabase) {
name = name + "( " + dataname + "[" + choiceDatabase + "] )"
}
console.log("this.pageList+++++++++"+JSON.stringify(this.pageList))
this.pageList.splice(this.pageList.findIndex(item => item.fullPath === path),1);
this.linkList.splice(this.linkList.findIndex(item => item === path),1);
console.log("this.pageList+++++++++"+JSON.stringify(this.pageList))
this.$router.replace({ query: { datasourceId: this.datasourceList[0].id,database:choiceDatabase } })
this.pageList.splice(this.pageList.findIndex(item => item.fullPath === path), 1);
this.linkList.splice(this.linkList.findIndex(item => item === path), 1);
this.$router.replace({
query: {
datasourceId: this.datasourceList[0].id,
database: choiceDatabase
}
})
}
})
}
}
})
}
}
})
}
}
//let pageRoute = this.pageList.find(item => this.getRouteRealPath(item) === activePage);
//pageRoute.fullPath = newRoute.fullPath;
},
},
methods: {
getDatafromChild(data){
this.datasourceList = data;
},
initLoadDataList(param) {
this.$emit('initLoadDataList', param);
},
loadDatasourceList() {
this.$emit('loadDatasourceList');
},
isIgnoreParamPath(path) {
return this.ignoreParamPath.indexOf(path) >= 0;
},
getRouteRealPath(route) {
return this.isIgnoreParamPath(route.path) ? route.path : route.fullPath;
},
changePage(tab) {
this.activePage = tab.name;
this.$router.push(tab.$attrs.fullPath);
},
editPage(key, action) {
this[action](key);
},
removePageTab(key) {
if (this.pageList.length === 1) {
this.$message.warning('这是最后一页,不能再关闭了啦');
return;
}
this.pageList = this.pageList.filter(item => this.getRouteRealPath(item) !== key);
this.linkList = this.linkList.filter(item => item !== key);
let index = this.linkList.indexOf(this.activePage);
if (index < 0) {
index = this.linkList.length - 1;
this.activePage = this.linkList[index];
}
//let pageRoute = this.pageList.find(item => this.getRouteRealPath(item) === activePage);
//pageRoute.fullPath = newRoute.fullPath;
},
contextMenuVisible(value) {
if (value) {
document.body.addEventListener('click', this.closeContextMenu)
} else {
document.body.removeEventListener('click', this.closeContextMenu)
}
}
},
methods: {
getDatafromChild(data) {
this.datasourceList = data;
},
initLoadDataList(param) {
this.$emit('initLoadDataList', param);
},
loadDatasourceList() {
this.$emit('loadDatasourceList');
},
isIgnoreParamPath(path) {
return this.ignoreParamPath.indexOf(path) >= 0;
},
getRouteRealPath(route) {
return this.isIgnoreParamPath(route.path) ? route.path : route.fullPath;
},
changePage(tab) {
this.activePage = tab.name;
this.$router.push(tab.$attrs.fullPath);
},
editPage(key, action) {
this[action](key);
},
removePageTab(key) {
if (this.pageList.length === 1) {
this.$message.warning('这是最后一页,不能再关闭了啦');
return;
}
this.pageList = this.pageList.filter(item => this.getRouteRealPath(item) !== key);
this.linkList = this.linkList.filter(item => item !== key);
let index = this.linkList.indexOf(this.activePage);
if (index < 0) {
index = this.linkList.length - 1;
this.activePage = this.linkList[index];
this.$router.push(this.activePage);
}
},
//tab栏右键菜单
openContextMenu(e) {
let obj = e.srcElement ? e.srcElement : e.target;
if (obj.id) {
let currentContextTabId = obj.id.split("-")[1];
this.contextMenuVisible = true;
this.$store.commit("saveCurContextTabId", currentContextTabId);
this.left = e.clientX;
this.top = e.clientY + 10;
}
},
//刷新当前页
curTabReload() {
let currTabIndex = 0;
let curContextTabId = this.$store.state.tagsView.curContextTabId;
for (let i = 0; i < this.pageList.length; i++) {
if (curContextTabId === this.pageList[i].fullPath) {
currTabIndex = i;
break;
}
}
this.activePage = this.linkList[currTabIndex];
this.$router.push(this.activePage);
this.closeContextMenu()
},
// 关闭所有标签页
closeAllTabs() {
//删除所有tab标签
this.linkList.splice(0, this.linkList.length)
this.pageList.splice(0, this.pageList.length)
this.$router.replace({query: {}})
this.closeContextMenu()
},
// 关闭其它标签页
closeOtherTabs(par) {
let currTabIndex = 0;
let curContextTabId = this.$store.state.tagsView.curContextTabId;
for (let i = 0; i < this.pageList.length; i++) {
if (curContextTabId === this.pageList[i].fullPath) {
currTabIndex = i;
break;
}
}
switch (par) {
case "left": {
//删除左侧tab标签
this.pageList.splice(0, currTabIndex);
this.linkList.splice(0, currTabIndex);
this.activePage = this.linkList[0];
this.$router.push(this.activePage);
break;
}
},
}
}
case "right": {
//删除右侧tab标签
this.pageList.splice(currTabIndex + 1, this.pageList.length);
this.linkList.splice(currTabIndex + 1, this.linkList.length);
this.activePage = this.linkList[currTabIndex];
this.$router.push(this.activePage);
break;
}
case "other": {
//删除其他所有tab标签
this.pageList.splice(0, currTabIndex);
this.linkList.splice(0, currTabIndex);
this.pageList.splice(currTabIndex + 1, this.pageList.length);
this.linkList.splice(currTabIndex + 1, this.linkList.length);
this.activePage = this.linkList[0];
this.$router.push(this.activePage);
break;
}
}
this.closeContextMenu()
},
// 关闭contextMenu
closeContextMenu() {
this.contextMenuVisible = false;
},
}
}
</script>
<style scoped>
/deep/ .el-tabs--card>.el-tabs__header{
margin: 0 0 5px;
/deep/ .el-tabs--card > .el-tabs__header {
margin: 0 0 5px;
}
/deep/ .el-tabs--card>.el-tabs__header .el-tabs__item{
height: 30px;
line-height: 30px;
/deep/ .el-tabs--card > .el-tabs__header .el-tabs__item {
height: 30px;
line-height: 30px;
}
/deep/ .el-tabs__nav-next{
line-height: 33px;
font-size: 20px;
/deep/ .el-tabs__nav-next {
line-height: 33px;
font-size: 20px;
}
/deep/ .el-tabs__nav-prev{
line-height: 33px;
font-size: 20px;
/deep/ .el-tabs__nav-prev {
line-height: 33px;
font-size: 20px;
}
.contextmenu {
width: 100px;
margin: 0;
border: 1px solid #ccc;
background: #fff;
z-index: 3000;
position: absolute;
list-style-type: none;
padding: 5px 0;
border-radius: 4px;
font-size: 14px;
color: #333;
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.2);
}
.contextmenu li {
margin: 0;
padding: 0px 22px;
}
.contextmenu li:hover {
background: #f2f2f2;
cursor: pointer;
}
.contextmenu li button {
color: #2c3e50;
}
</style>

View File

@@ -1,11 +1,13 @@
import Vue from 'vue'
import Vuex from 'vuex'
import global from './modules/global'
import tagsView from './modules/tagsView'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
global,
tagsView
}
});

View File

@@ -0,0 +1,15 @@
const state = {
}
const mutations = {
// <20><><EFBFBD><EFBFBD><EFBFBD>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD>tab<61><62>id
saveCurContextTabId(state, curContextTabId) {
state.curContextTabId = curContextTabId
},
}
export default {
state,
mutations
}

View File

@@ -4,43 +4,47 @@
<el-card style="margin-bottom: 10px;">
<div v-show="aceEditorShow">
<el-alert
title="筛选示例 (支持 and , or 等连接符)"
type="info"
:description="executorDesc"
show-icon>
title="筛选示例 (支持 and , or 等连接符)"
type="info"
:description="executorDesc"
show-icon>
</el-alert>
<ace-editor v-model="sqlExecutorContent" @init="sqlExecutorInit" lang="sql" theme="monokai" width="100%"
height="60" :options="sqlEditorConfig" :source="executorSource"
style="margin-bottom: 10px;">
<ace-editor v-model="sqlExecutorContent" @init="sqlExecutorInit" lang="sql" theme="monokai"
width="100%"
height="60" :options="sqlEditorConfig" :source="executorSource"
style="margin-bottom: 10px;">
</ace-editor>
</div>
<div>
<el-button v-on:click="doAceEditorShow" type="primary" plain size="small" icon="el-icon-search">筛选
</el-button>
<el-button v-if="sqlExecuting" v-on:click="cancelExecutorSql" type="primary" plain size="small"
icon="el-icon-video-pause">取消执行
icon="el-icon-video-pause">取消执行
</el-button>
<el-tooltip v-show="aceEditorShow" v-else effect="dark" content="Ctrl+R、Ctrl+Enter" placement="top">
<el-button v-on:click="doExecutorClick" type="primary" plain size="small"
icon="el-icon-video-play">执行
icon="el-icon-video-play">执行
</el-button>
</el-tooltip>
<el-button icon="el-icon-refresh-left" size="small" @click="refreshData">重置</el-button>
<el-button @click="downloadTableData" type="success" size="small" icon="el-icon-download" plain
style="margin-left: 30px;">导出
style="margin-left: 30px;">导出
</el-button>
</div>
</el-card>
<el-card>
<div v-if="!!executeError" style="color: #f00;">{{ executeError }}</div>
<div v-else-if="sqlExecuting" v-loading="sqlExecuting" style="padding: 20px 0;">数据加载中...</div>
<div v-else-if="executeResultList.length <= 0" v-loading="sqlExecuting" style="padding: 20px 0;">暂无数据</div>
<div v-else-if="executeResultList.length <= 0" v-loading="sqlExecuting" style="padding: 20px 0;">
暂无数据
</div>
<div v-else style="position: relative;">
<div style="position: absolute;right: 0;z-index: 1;" v-show="executeShowTable !== 'table0'">
<span v-show="choiceResultObj[executeShowTable] && choiceResultObj[executeShowTable].length > 0">
<span
v-show="choiceResultObj[executeShowTable] && choiceResultObj[executeShowTable].length > 0">
<el-button icon="el-icon-delete" size="small" @click="deleteCheckLine" type="danger" plain
style="margin-right: 10px;">删除</el-button>
style="margin-right: 10px;">删除</el-button>
<!-- 复制选中行 -->
<el-dropdown @command="handleCopyCheckLineCommand">
<el-button type="primary" size="small" icon="el-icon-document-copy">
@@ -55,7 +59,7 @@
</span>
<el-tooltip effect="dark" content="选择展示列" placement="top">
<el-button icon="el-icon-setting" size="small" style="margin-left: 10px;"
@click="choiceShowColumnDrawerShow"></el-button>
@click="choiceShowColumnDrawerShow"></el-button>
</el-tooltip>
</div>
<el-tabs v-model="executeShowTable">
@@ -63,47 +67,51 @@
<pre class="xxpre">{{ executeResultInfo }}</pre>
</el-tab-pane>
<el-tab-pane :label="'结果'+resultItem.index" :name="resultItem.name"
v-for="(resultItem,index) in executeResultList" :key="index" v-if="!!resultItem.index">
v-for="(resultItem,index) in executeResultList" :key="index"
v-if="!!resultItem.index">
<div v-if="!!resultItem.errMsg" style="color: #f00;">{{ resultItem.errMsg }}</div>
<div v-else-if="resultItem.dataList.length <= 0"
style="text-align: center; color: #aaa; padding: 20px 0;">暂无数据
style="text-align: center; color: #aaa; padding: 20px 0;">暂无数据
</div>
<template v-else>
<ux-grid
v-clickoutside="handleClickOutside"
:data="resultItem.dataList"
stripe
border
:height="height"
style="width: 100%; margin-bottom: 5px;" class="execute-result-table" :max-height="tableMaxHeight"
@selection-change="handleSelectionChange"
@cell-click="mouseOnFocus"
@cell-mouse-leave="mouseLeave"
@sort-change="tableSortChange"
:default-sort="tableSort">
v-clickoutside="handleClickOutside"
:data="resultItem.dataList"
stripe
border
:height="height"
style="width: 100%; margin-bottom: 5px;" class="execute-result-table"
:max-height="tableMaxHeight"
@selection-change="handleSelectionChange"
@cell-click="mouseOnFocus"
@cell-mouse-leave="mouseLeave"
@sort-change="tableSortChange"
:default-sort="tableSort">
<ux-table-column type="checkbox" width="55"></ux-table-column>
<ux-table-column type="index" width="50" title=" "></ux-table-column>
<ux-table-column v-for="(item,index) in resultItem.dataCols" :key="index" :prop="item.prop" :title="item.prop"
:width="item.width" sortable>
<ux-table-column v-for="(item,index) in resultItem.dataCols" :key="index"
:prop="item.prop" :title="item.prop"
:width="item.width" sortable>
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="item.desc" placement="top">
<span>{{ item.prop }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<textarea readonly :value="scope.row[item.prop]" class="el-textarea__inner" rows="1"></textarea>
<textarea readonly :value="scope.row[item.prop]" class="el-textarea__inner"
rows="1"></textarea>
</template>
</ux-table-column>
</ux-grid>
<el-pagination
style="margin-top: 10px;"
@size-change="handlePageSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[50, 100, 300, 500]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="tableTotalCount">
style="margin-top: 10px;"
@size-change="handlePageSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[50, 100, 300, 500]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="tableTotalCount">
</el-pagination>
</template>
</el-tab-pane>
@@ -117,7 +125,7 @@
更新条件列
<el-select v-model="conditionDataColsChoice" multiple placeholder="请选择" style="width: 370px;">
<el-option v-for="item in conditionDataCols" :key="item.prop" :label="item.prop"
:value="item.prop"></el-option>
:value="item.prop"></el-option>
</el-select>
</div>
<span slot="footer" class="dialog-footer">
@@ -130,7 +138,7 @@
<el-form label-width="120px">
<el-form-item label="导出类型:">
<el-select v-model="downloadDataParam.downloadType" filterable placeholder="请选择导出类型"
style="width: 370px;">
style="width: 370px;">
<el-option label="SQL Inserts" value="insert"></el-option>
<el-option label="SQL Updates" value="update"></el-option>
<el-option label="JSON" value="json"></el-option>
@@ -139,17 +147,20 @@
</el-form-item>
<el-form-item label="数据表:" v-if="downloadDataParam.downloadType === 'insert'">
<el-checkbox :true-label="1" :false-label="0" v-model="downloadDataParam.dropTableFlag"
@change="dropTableFlagChange">删除表{{ downloadDataParam.dropTableFlag == 1 ? '!!' : '' }}
@change="dropTableFlagChange">删除表{{
downloadDataParam.dropTableFlag == 1 ? '!!' : ''
}}
</el-checkbox>
<el-checkbox :true-label="1" :false-label="0" v-model="downloadDataParam.createTableFlag"
@change="createTableFlagChange">创建表
@change="createTableFlagChange">创建表
</el-checkbox>
</el-form-item>
<el-form-item label="更新条件列:" v-if="downloadDataParam.downloadType === 'update'">
<el-select v-model="downloadDataParam.conditionColumnArr" multiple placeholder="不选则是没有条件的更新"
style="width: 370px;">
<el-select v-model="downloadDataParam.conditionColumnArr" multiple
placeholder="不选则是没有条件的更新"
style="width: 370px;">
<el-option v-for="item in conditionDataCols" :key="item.prop" :label="item.prop"
:value="item.prop"></el-option>
:value="item.prop"></el-option>
</el-select>
</el-form-item>
</el-form>
@@ -159,16 +170,17 @@
</span>
</el-dialog>
<el-drawer
size="350px"
:with-header="false"
:visible.sync="choiceShowColumnDrawer"
:before-close="choiceShowColumnDrawerClose"
direction="rtl">
size="350px"
:with-header="false"
:visible.sync="choiceShowColumnDrawer"
:before-close="choiceShowColumnDrawerClose"
direction="rtl">
<div style="padding: 10px;">
<el-row>
<el-col :span="12">选择展示列</el-col>
<el-col :span="12" style="text-align: right;">
<el-checkbox v-model="choiceShowColumnAll" @change="choiceShowColumnAllChange">全选</el-checkbox>
<el-checkbox v-model="choiceShowColumnAll" @change="choiceShowColumnAllChange">全选
</el-checkbox>
<el-button type="primary" size="mini" @click="choiceShowColumnOk" style="margin-left: 10px;">确定
</el-button>
</el-col>
@@ -176,8 +188,8 @@
</div>
<div style="overflow: auto; height: calc(100vh - 50px);">
<el-tree ref="showColumnTree" node-key="name" :props="showColumnProps" :data="tableDataColumns"
check-on-click-node show-checkbox
@check-change="tableDataColumnsCheckChange">
check-on-click-node show-checkbox
@check-change="tableDataColumnsCheckChange">
</el-tree>
</div>
</el-drawer>
@@ -198,7 +210,7 @@ import Clickoutside from 'element-ui/src/utils/clickoutside'
export default {
name: 'dataPreview',
directives: { Clickoutside },
directives: {Clickoutside},
data() {
return {
executorDesc: "",
@@ -463,24 +475,24 @@ export default {
this.$set(this.choiceResultObj, this.executeShowTable, val);
},
//表格单元格鼠标焦点事件
mouseOnFocus(row, column, cell, event){
if(this.uxGridCell){
this.uxGridCell.style.border = 'none'
}
cell.style.border = '2px solid #0078d7'
this.uxGridCell = cell;
mouseOnFocus(row, column, cell, event) {
if (this.uxGridCell) {
this.uxGridCell.style.border = 'none'
}
cell.style.border = '2px solid #0078d7'
this.uxGridCell = cell;
},
//表格单元格 hover 退出
mouseLeave(row, column, cell, event){
// if(this.uxGridCell){
// this.uxGridCell.style.border = 'none'
// }
mouseLeave(row, column, cell, event) {
// if(this.uxGridCell){
// this.uxGridCell.style.border = 'none'
// }
},
// 点击区域外
handleClickOutside() {
if(this.uxGridCell){
this.uxGridCell.style.border = 'none'
}
if (this.uxGridCell) {
this.uxGridCell.style.border = 'none'
}
},
doCopyCheckLineUpdate() {
let choiceData = this.choiceResultObj[this.executeShowTable] || [];
@@ -490,8 +502,8 @@ export default {
this.conditionDataColsChoice = [];
this.exportConditionVisible = false;
this.$copyText(copyData).then(
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
);
}
},
@@ -546,8 +558,8 @@ export default {
}
let copyData = copyFormatter.format(type, this.pageParam.dbType, dataCols, choiceData, this.conditionDataColsChoice, this.pageParam.dbName, this.pageParam.tableName);
this.$copyText(copyData).then(
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
);
}
},
@@ -686,17 +698,19 @@ export default {
/deep/ .elx-table .elx-header--column.col--ellipsis {
height: 30px;
//padding-left: 5px;
//padding-left: 5px;
}
.xxpre{
overflow: auto;
.xxpre {
overflow: auto;
}
.el-textarea__inner{
border: none;
background-color: #f0f8ff00;
.el-textarea__inner {
border: none;
background-color: #f0f8ff00;
}
.el-textarea__inner::-webkit-scrollbar {
display: none;
display: none;
}
</style>

View File

@@ -2,34 +2,37 @@
<div class="data-executor-vue">
<div style="padding: 0 10px 10px;height: 100%;box-sizing: border-box;">
<el-card style="margin-bottom: 5px;">
<ace-editor v-model="sqlExecutorContent" ref="sqlEditor" @init="sqlExecutorInit" lang="sql" theme="monokai"
width="100%" height="20" :options="sqlEditorConfig" :source="executorSource"
@cursorSelection="cursorSelection" style="margin-bottom: 5px;"></ace-editor>
<ace-editor v-model="sqlExecutorContent" ref="sqlEditor" @init="sqlExecutorInit" lang="sql"
theme="monokai"
width="100%" height="20" :options="sqlEditorConfig" :source="executorSource"
@cursorSelection="cursorSelection" style="margin-bottom: 5px;"></ace-editor>
<div>
<el-button v-if="sqlExecuting" v-on:click="cancelExecutorSql" type="primary" plain size="mini"
icon="el-icon-video-pause">取消执行
icon="el-icon-video-pause">取消执行
</el-button>
<el-tooltip v-else effect="dark" content="Ctrl+R、Ctrl+Enter" placement="top">
<el-button v-on:click="doExecutorSql" type="primary" plain size="mini" icon="el-icon-video-play">{{executeButtonText}}
<el-button v-on:click="doExecutorSql" type="primary" plain size="mini"
icon="el-icon-video-play">{{ executeButtonText }}
</el-button>
</el-tooltip>
<el-button icon="el-icon-brush" size="mini" @click="formatterSql">SQL美化</el-button>
<el-button v-on:click="addFavorite('')" plain size="mini" icon="el-icon-star-off">收藏</el-button>
<div style="float: right;">
<el-select v-model="choiceDatasourceId" @change="datasourceChangeEvents" size="mini" filterable
placeholder="请选择数据源" style="width: 300px;margin-left: 10px;">
placeholder="请选择数据源" style="width: 300px;margin-left: 10px;">
<el-option v-for="item in datasourceOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
:value="item.id"></el-option>
</el-select>
<el-select v-model="choiceDatabase" @change="databaseChangeEvents" size="mini" filterable
placeholder="请选择数据库" style="width: 200px;margin-left: 10px;">
placeholder="请选择数据库" style="width: 200px;margin-left: 10px;">
<el-option v-for="item in databaseList" :key="item.dbName" :label="item.dbName"
:value="item.dbName"></el-option>
:value="item.dbName"></el-option>
</el-select>
</div>
</div>
<div v-if="sqlParams.length > 0" class="sql-params">
<el-input :placeholder="'请输入'+param.key+'的值'" v-model="param.value" v-for="(param,index) in sqlParams" :key="index">
<el-input :placeholder="'请输入'+param.key+'的值'" v-model="param.value"
v-for="(param,index) in sqlParams" :key="index">
<template slot="prepend">{{ param.key }}</template>
</el-input>
</div>
@@ -39,7 +42,7 @@
<div style="position: absolute;right: 0;z-index: 1;">
<!-- 复制选中行 -->
<el-dropdown @command="handleCopyCheckLineCommand"
v-show="this.choiceResultObj[this.executeShowTable] && this.choiceResultObj[this.executeShowTable].length > 0">
v-show="this.choiceResultObj[this.executeShowTable] && this.choiceResultObj[this.executeShowTable].length > 0">
<el-button type="primary" size="small" icon="el-icon-document-copy">
复制选中行<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
@@ -57,32 +60,38 @@
<el-table-column prop="content" label="SQL">
<template slot-scope="scope">
<pre class="sql-content-line" @dblclick="inputFavoriteSql(scope.row)"
:title="scope.row.content">{{ scope.row.content }}</pre>
:title="scope.row.content">{{ scope.row.content }}</pre>
</template>
</el-table-column>
<el-table-column label="操作" width="160px">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="inputFavoriteSql(scope.row)">输入</el-button>
<el-button size="mini" type="primary" @click="inputFavoriteSql(scope.row)">
输入
</el-button>
<el-button size="mini" type="success" @click="addFavorite(scope.row.content)"
style="margin-left: 10px;">收藏
style="margin-left: 10px;">收藏
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="我的收藏" name="tabFavorite">
<el-table :data="myFavoriteList" stripe border style="width: 100%; margin-bottom: 5px;" v-infinite-scroll>
<el-table :data="myFavoriteList" stripe border style="width: 100%; margin-bottom: 5px;"
v-infinite-scroll>
<el-table-column prop="createTime" label="执行时间" width="160px"></el-table-column>
<el-table-column prop="content" label="SQL">
<template slot-scope="scope">
<pre class="sql-content-line" @dblclick="inputFavoriteSql(scope.row)"
:title="scope.row.content">{{ scope.row.content }}</pre>
:title="scope.row.content">{{ scope.row.content }}</pre>
</template>
</el-table-column>
<el-table-column label="操作" width="160px">
<template slot-scope="scope">
<el-button size="mini" type="primary" v-on:click="inputFavoriteSql(scope.row)">输入</el-button>
<el-button size="mini" type="danger" v-on:click="delFavorite(scope.row)" style="margin-left: 10px;">
<el-button size="mini" type="primary" v-on:click="inputFavoriteSql(scope.row)">
输入
</el-button>
<el-button size="mini" type="danger" v-on:click="delFavorite(scope.row)"
style="margin-left: 10px;">
删除
</el-button>
</template>
@@ -96,50 +105,59 @@
<div style="color: #f00;">{{ executeError }}</div>
</el-tab-pane>
<template v-else>
<el-tab-pane :label="resultItem.label" :name="resultItem.name" v-for="(resultItem,index) in executeResultList" :key="index"
lazy>
<el-tab-pane :label="resultItem.label" :name="resultItem.name"
v-for="(resultItem,index) in executeResultList" :key="index"
lazy>
<div v-if="!!resultItem.errMsg" style="color: #f00;">{{ resultItem.errMsg }}</div>
<ux-grid v-else
v-clickoutside="handleClickOutside"
:data="resultItem.dataList"
@table-body-scroll="scroll"
@selection-change="handleSelectionChange"
@cell-click="mouseOnFocus"
@cell-mouse-leave="mouseLeave"
:checkboxConfig="{checkMethod: selectable, highlight: true}"
stripe border :height="height" max-height="600"
style="width: 100%; margin-bottom: 5px;" class="execute-result-table">
v-clickoutside="handleClickOutside"
:data="resultItem.dataList"
@table-body-scroll="scroll"
@selection-change="handleSelectionChange"
@cell-click="mouseOnFocus"
@cell-mouse-leave="mouseLeave"
:checkboxConfig="{checkMethod: selectable, highlight: true}"
stripe border :height="height" max-height="600"
style="width: 100%; margin-bottom: 5px;" class="execute-result-table">
<ux-table-column type="checkbox" width="55"></ux-table-column>
<ux-table-column type="index" width="55" title=" "></ux-table-column>
<ux-table-column v-for="(item,index) in resultItem.dataCols" :key="index" :prop="item.prop" :title="item.label"
:width="item.width">
<ux-table-column v-for="(item,index) in resultItem.dataCols" :key="index"
:prop="item.prop" :title="item.label"
:width="item.width">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="item.desc" placement="top">
<span>{{ item.label }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<textarea readonly :value="scope.row[item.prop]" class="el-textarea__inner" rows="1"></textarea>
<textarea readonly :value="scope.row[item.prop]" class="el-textarea__inner"
rows="1"></textarea>
</template>
</ux-table-column>
</ux-grid>
<el-pagination
v-if="resultItem.selectCount"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-size="pageSize"
:page-sizes="[1000]"
layout="total, sizes, prev, pager, next, jumper"
:total="resultItem.selectCount">
v-if="resultItem.selectCount"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-size="pageSize"
:page-sizes="[1000]"
layout="total, sizes, prev, pager, next, jumper"
:total="resultItem.selectCount">
</el-pagination>
<div v-if="resultItem.selectCount" style="position: absolute;right: 5px;bottom: 5px;">
<el-button type="primary" plain v-on:click="viewAllData()">查看所有</el-button>
</div>
<div v-if="!resultItem.selectCount" style="height: 20px;font-size: 13px;font-weight: 400;color: #606266;padding-left: 5px;">
{{resultItem.totalCount}}
<div v-if="!resultItem.selectCount"
style="height: 20px;font-size: 13px;font-weight: 400;color: #606266;padding-left: 5px;">
{{ resultItem.totalCount }}
</div>
</el-tab-pane>
</template>
<el-main v-loading="loadingAll"
v-show="loadingAll"
element-loading-text="正在加载中"
element-loading-spinner="el-icon-loading"
style="height: 175px;">
v-show="loadingAll"
element-loading-text="正在加载中"
element-loading-spinner="el-icon-loading"
style="height: 175px;">
</el-main>
</el-tabs>
</div>
@@ -151,7 +169,7 @@
更新条件列
<el-select v-model="conditionDataColsChoice" multiple placeholder="请选择" style="width: 370px;">
<el-option v-for="item in conditionDataCols" :key="item.prop" :label="item.label"
:value="item.prop"></el-option>
:value="item.prop"></el-option>
</el-select>
</div>
<span slot="footer" class="dialog-footer">
@@ -173,11 +191,11 @@ import Clickoutside from 'element-ui/src/utils/clickoutside';
import merge from 'webpack-merge';
export default {
directives: { Clickoutside },
directives: {Clickoutside},
data() {
return {
//遮罩层
loadingAll: false,
//遮罩层
loadingAll: false,
height: 0,
scrollTop: 0,
@@ -195,10 +213,10 @@ export default {
editorColumnInfo: {},
//选中的单元格
uxGridCell: "",
uxGridCell: "",
pageSize: 1000,
currentPage: 1,
currentPage: 1,
sqlExecuting: false,
executeResultList: [],
@@ -217,7 +235,7 @@ export default {
conditionDataCols: [],
conditionDataColsChoice: [],
//执行按钮文本
executeButtonText: '执行',
executeButtonText: '执行',
// 编辑器
sqlExecutorContent: '',
sqlEditorConfig: {
@@ -243,9 +261,9 @@ export default {
this.height = 190;
this.loadDatasourceList();
},
activated(){
activated() {
this.loadDatasourceList();
},
},
methods: {
sqlExecutorInit(editor) {
this.sqlExecutorEditor = editor;
@@ -275,12 +293,12 @@ export default {
}
});
},
cursorSelection(sqlValue){
if(sqlValue){
cursorSelection(sqlValue) {
if (sqlValue) {
this.executeButtonText = '执行已选择的'
}else{
} else {
this.executeButtonText = '执行'
}
}
},
scroll({scrollTop, scrollLeft}) {
this.scrollTop = scrollTop
@@ -365,7 +383,7 @@ export default {
this.$message.error("请先选择数据源");
return;
}
if(!this.choiceDatabase){
if (!this.choiceDatabase) {
this.$message.error("请先选择数据库");
return;
}
@@ -389,17 +407,124 @@ export default {
sourceId: this.choiceDatasourceId,
dbName: this.choiceDatabase,
executeId: this.nowExecutorId,
pageNum: this.currentPage,
pageSize: this.pageSize,
pageNum: this.currentPage,
pageSize: this.pageSize,
sql: sqlValue,
params: JSON.stringify(sqlParamObj),
}).then(response => {
this.sqlExecuting = false;
if (response.errCode != 200) {
this.executeShowTable = 'tabError';
this.executeError = response.errMsg;
return;
}
if (response.errCode != 200) {
this.executeShowTable = 'tabError';
this.executeError = response.errMsg;
return;
}
let resIndex = 1;
let executeResultList = [];
let resData = response.data || [];
let executeResultInfo = "";
resData.forEach(result => {
let dataListRes = [];
let previewColumns = [];
executeResultInfo += this.getExecuteInfoStr(result);
if (result.errCode === 0) {
let dataListTemp = result.data || [];
let headerList = result.header || [];
// 组装表头
let columnSet = {};
if (headerList.length > 0) {
let headerIndex = 0;
headerList.forEach(item => {
let key = 'value_' + (headerIndex++);
columnSet[key] = item;
previewColumns.push({prop: key, label: item, desc: item});
});
dataListTemp.forEach(item => {
let dataItem = {}, dataIndex = 0;
previewColumns.forEach(column => {
let key = column.prop;
dataItem[key] = item[dataIndex++];
if ((dataItem[key] + '').length > columnSet[key].length) {
columnSet[key] = dataItem[key] + '';
}
});
dataListRes.push(dataItem);
});
previewColumns.forEach(item => {
// 动态计算宽度~自己想的一个方法666
document.getElementById("widthCalculate").innerText = columnSet[item.prop];
let width = document.getElementById("widthCalculate").offsetWidth;
width = width + (columnSet[item.prop] === item.label ? 35 : 55);
width = (width < 50) ? 50 : width;
item.width = (width > 200) ? 200 : width;
});
}
}
executeResultList.push({
label: '结果' + resIndex,
name: 'result_' + resIndex,
errMsg: result.errMsg,
errCode: result.errCode,
queryTime: result.queryTime,
selectCount: result.selectCount,
totalCount: dataListRes.length,
dataCols: previewColumns,
dataList: dataListRes
});
resIndex++;
//动态设置表格高度,尽量避免出现滚动条
if (result.selectCount) {
this.height = 170;
}
});
//多个结果情况下,且点击分页
if (init != 1) {
this.executeShowTable = (resIndex === 1) ? "tabInfo" : "result_1";
}
this.executeResultInfo = executeResultInfo;
this.executeResultList = executeResultList;
this.loadHistoryList();
});
},
//查看所有数据
viewAllData(init) {
this.loadingAll = true;
if (!this.choiceDatasourceId) {
this.$message.error("请先选择数据源");
return;
}
this.executeError = "";
this.executeUseTime = "";
this.executeResultList = [];
let sqlParamObj = {};
this.sqlParams.forEach(item => {
if (!!item.value) {
sqlParamObj[item.key] = item.value;
this.sqlParamHistory[item.key] = item.value;
}
});
this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000);
let sqlValue = this.sqlExecutorEditor.getSelectedText();
if (!sqlValue) {
sqlValue = this.sqlExecutorEditor.getValue();
}
this.sqlExecuting = true;
datasourceApi.queryExecuteSql({
sourceId: this.choiceDatasourceId,
dbName: this.choiceDatabase,
executeId: this.nowExecutorId,
pageNum: this.currentPage,
pageSize: this.pageSize,
sql: sqlValue,
type: 'noPage',
params: JSON.stringify(sqlParamObj),
}).then(response => {
this.sqlExecuting = false;
this.loadingAll = false;
if (response.errCode != 200) {
this.executeShowTable = 'tabError';
this.executeError = response.errMsg;
return;
}
let resIndex = 1;
let executeResultList = [];
let resData = response.data || [];
@@ -454,12 +579,12 @@ export default {
});
resIndex++;
//动态设置表格高度,尽量避免出现滚动条
if(result.selectCount){
if (result.selectCount) {
this.height = 170;
}
});
//多个结果情况下,且点击分页
if(init!=1){
if (init != 1) {
this.executeShowTable = (resIndex === 1) ? "tabInfo" : "result_1";
}
this.executeResultInfo = executeResultInfo;
@@ -467,118 +592,11 @@ export default {
this.loadHistoryList();
});
},
//查看所有数据
viewAllData(init){
this.loadingAll = true;
if (!this.choiceDatasourceId) {
this.$message.error("请先选择数据源");
return;
}
this.executeError = "";
this.executeUseTime = "";
this.executeResultList = [];
let sqlParamObj = {};
this.sqlParams.forEach(item => {
if (!!item.value) {
sqlParamObj[item.key] = item.value;
this.sqlParamHistory[item.key] = item.value;
}
});
this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000);
let sqlValue = this.sqlExecutorEditor.getSelectedText();
if (!sqlValue) {
sqlValue = this.sqlExecutorEditor.getValue();
}
this.sqlExecuting = true;
datasourceApi.queryExecuteSql({
sourceId: this.choiceDatasourceId,
dbName: this.choiceDatabase,
executeId: this.nowExecutorId,
pageNum: this.currentPage,
pageSize: this.pageSize,
sql: sqlValue,
type: 'noPage',
params: JSON.stringify(sqlParamObj),
}).then(response => {
this.sqlExecuting = false;
this.loadingAll = false;
if (response.errCode != 200) {
this.executeShowTable = 'tabError';
this.executeError = response.errMsg;
return;
}
let resIndex = 1;
let executeResultList = [];
let resData = response.data || [];
let executeResultInfo = "";
resData.forEach(result => {
let dataListRes = [];
let previewColumns = [];
executeResultInfo += this.getExecuteInfoStr(result);
if (result.errCode === 0) {
let dataListTemp = result.data || [];
let headerList = result.header || [];
// 组装表头
let columnSet = {};
if (headerList.length > 0) {
let headerIndex = 0;
headerList.forEach(item => {
let key = 'value_' + (headerIndex++);
columnSet[key] = item;
previewColumns.push({prop: key, label: item});
});
dataListTemp.forEach(item => {
let dataItem = {}, dataIndex = 0;
previewColumns.forEach(column => {
let key = column.prop;
dataItem[key] = item[dataIndex++];
if ((dataItem[key] + '').length > columnSet[key].length) {
columnSet[key] = dataItem[key] + '';
}
});
dataListRes.push(dataItem);
});
previewColumns.forEach(item => {
// 动态计算宽度~自己想的一个方法666
document.getElementById("widthCalculate").innerText = columnSet[item.prop];
let width = document.getElementById("widthCalculate").offsetWidth;
width = width + (columnSet[item.prop] === item.label ? 35 : 55);
width = (width < 50) ? 50 : width;
item.width = (width > 200) ? 200 : width;
});
}
}
executeResultList.push({
label: '结果' + resIndex,
name: 'result_' + resIndex,
errMsg: result.errMsg,
errCode: result.errCode,
queryTime: result.queryTime,
selectCount: result.selectCount,
totalCount: dataListRes.length,
dataCols: previewColumns,
dataList: dataListRes
});
resIndex++;
//动态设置表格高度,尽量避免出现滚动条
if(result.selectCount){
this.height = 170;
}
});
//多个结果情况下,且点击分页
if(init!=1){
this.executeShowTable = (resIndex === 1) ? "tabInfo" : "result_1";
}
this.executeResultInfo = executeResultInfo;
this.executeResultList = executeResultList;
this.loadHistoryList();
});
handleCurrentChange(to) {
this.currentPage = to;
let init = 1;
this.doExecutorSql(init);
},
handleCurrentChange(to) {
this.currentPage = to;
let init = 1;
this.doExecutorSql(init);
},
loadDatasourceList() {
datasourceApi.datasourceList({}).then(json => {
this.datasourceList = json.data || [];
@@ -594,11 +612,11 @@ export default {
if (this.datasourceList.length > 0) {
this.choiceDatasourceId = this.datasourceList[0].id;
//初次加载根据query值设置对应数据源
if(this.$route.query.datasourceId){
if (this.$route.query.datasourceId) {
this.choiceDatasourceId = parseInt(this.$route.query.datasourceId);
}
//初次加载根据query值设置对应数据库
if(this.$route.query.database){
if (this.$route.query.database) {
this.choiceDatabase = this.$route.query.database;
}
this.executorSource = {sourceId: this.choiceDatasourceId};
@@ -617,9 +635,14 @@ export default {
let sysDbName = ["information_schema", "master", "model", "msdb", "tempdb"];
let notSysDbItem = this.databaseList.find(item => sysDbName.indexOf(item.dbName) < 0);
// 非初次加载动态改变url参数
if(!initFlag){
if (!initFlag) {
this.choiceDatabase = (!!notSysDbItem) ? notSysDbItem.dbName : this.databaseList[0].dbName;
this.$router.replace({ query: { datasourceId: this.choiceDatasourceId,database:this.choiceDatabase } })
this.$router.replace({
query: {
datasourceId: this.choiceDatasourceId,
database: this.choiceDatabase
}
})
}
this.executorSource = {sourceId: this.choiceDatasourceId, dbName: this.choiceDatabase};
}
@@ -650,15 +673,15 @@ export default {
},
datasourceChangeEvents() {
this.executorSource = {sourceId: this.choiceDatasourceId};
this.currentPage = 1;
this.currentPage = 1;
this.loadDatabaseList();
this.loadSourceBaseInfo();
this.loadHistoryAndFavoriteList();
},
databaseChangeEvents() {
this.$router.replace({ query: { datasourceId: this.choiceDatasourceId,database:this.choiceDatabase } })
this.$router.replace({query: {datasourceId: this.choiceDatasourceId, database: this.choiceDatabase}})
this.executorSource = {sourceId: this.choiceDatasourceId, dbName: this.choiceDatabase};
this.currentPage = 1;
this.currentPage = 1;
},
getExecuteInfoStr(resultData) {
var resultStr = resultData.executeSql;
@@ -698,7 +721,7 @@ export default {
handleSelectionChange(val) {
this.$set(this.choiceResultObj, this.executeShowTable, val);
},
tabHandleClick(t){
tabHandleClick(t) {
},
doCopyCheckLineUpdate() {
@@ -709,8 +732,8 @@ export default {
this.conditionDataColsChoice = [];
this.exportConditionVisible = false;
this.$copyText(copyData).then(
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
);
}
},
@@ -726,30 +749,30 @@ export default {
}
let copyData = copyFormatter.format(type, this.editorDbProduct, dataCols, choiceData, '');
this.$copyText(copyData).then(
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
res => this.$message.success("内容已复制到剪切板!"),
err => this.$message.error("抱歉,复制失败!")
);
}
},
//表格单元格鼠标焦点事件
mouseOnFocus(row, column, cell, event){
if(this.uxGridCell){
mouseOnFocus(row, column, cell, event) {
if (this.uxGridCell) {
this.uxGridCell.style.border = 'none'
}
cell.style.border = '2px solid #0078d7'
cell.style.border = '2px solid #0078d7'
this.uxGridCell = cell;
},
//表格单元格 hover 退出
mouseLeave(row, column, cell, event){
// if(this.uxGridCell){
mouseLeave(row, column, cell, event) {
// if(this.uxGridCell){
// this.uxGridCell.style.border = 'none'
// }
// }
},
// 点击区域外
handleClickOutside() {
if(this.uxGridCell){
this.uxGridCell.style.border = 'none'
}
if (this.uxGridCell) {
this.uxGridCell.style.border = 'none'
}
},
}
}
@@ -837,25 +860,30 @@ export default {
/deep/ .elx-table .elx-header--column.col--ellipsis {
height: 30px;
//padding-left: 5px;
//padding-left: 5px;
}
.el-textarea__inner{
border: none;
background-color: #f0f8ff00;
.el-textarea__inner {
border: none;
background-color: #f0f8ff00;
}
.el-textarea__inner::-webkit-scrollbar {
display: none;
display: none;
}
/deep/ .el-tabs--border-card>.el-tabs__content {
padding: 5px;
/deep/ .el-tabs--border-card > .el-tabs__content {
padding: 5px;
}
/deep/ .elx-table .elx-body--column.col--ellipsis>.elx-cell,
.elx-table .elx-footer--column.col--ellipsis>.elx-cell,
.elx-table .elx-header--column.col--ellipsis>.elx-cell{
overflow: auto;
text-overflow: unset;
/deep/ .elx-table .elx-body--column.col--ellipsis > .elx-cell,
.elx-table .elx-footer--column.col--ellipsis > .elx-cell,
.elx-table .elx-header--column.col--ellipsis > .elx-cell {
overflow: auto;
text-overflow: unset;
}
/deep/ .elx-table .elx-body--column.col--ellipsis>.elx-cell::-webkit-scrollbar {
display: none;
/deep/ .elx-table .elx-body--column.col--ellipsis > .elx-cell::-webkit-scrollbar {
display: none;
}
</style>