增加数据库函数和存储过程的增删改查支持,优化数据源管理

This commit is contained in:
暮光:城中城
2021-04-25 21:56:27 +08:00
parent f270a9bb12
commit 744e877309
22 changed files with 1007 additions and 98 deletions

View File

@@ -2,18 +2,18 @@
<div class="table-database-vue">
<el-card style="margin: 10px;" shadow="never">
<div slot="header" class="clearfix">库信息</div>
<el-form label-width="100px">
<el-form-item label="数据源:">{{vueQueryParam.host}}</el-form-item>
<el-form-item label="数据库:">{{vueQueryParam.dbName}}</el-form-item>
</el-form>
<el-form :inline="true" label-width="100px">
<el-form-item label="关键字:">
<el-input v-model="keyword" placeholder="输入字段名或注释搜索相关的表或字段信息" style="width: 500px;"></el-input>
</el-form-item>
<el-form-item>
<el-button class="search-submit" type="primary" icon="el-icon-search" @click="searchSubmit">模糊搜索</el-button>
</el-form-item>
</el-form>
<el-row style="margin-bottom: 20px;">
<el-col :span="12"><span class="label">数据源</span>{{vueQueryParam.host}}</el-col>
<el-col :span="12"><span class="label">数据库</span>{{vueQueryParam.dbName}}</el-col>
</el-row>
<el-row>
<el-col :span="24">
<span class="label">关键字</span>
<el-input v-model="keyword" placeholder="输入字段名或注释搜索库中相关的表或字段信息" style="width: 350px;margin-right: 10px;"></el-input>
<el-button class="search-submit" type="primary" icon="el-icon-search" @click="searchSubmit">模糊搜索</el-button>
<el-button icon="el-icon-coin" @click="funcManage">函数管理</el-button>
</el-col>
</el-row>
</el-card>
<div style="padding: 10px;" v-loading="columnListLoading">
<el-table :data="columnList" stripe border style="width: 100%; margin-bottom: 5px;">
@@ -65,10 +65,14 @@
this.columnListLoading = false;
});
},
funcManage() {
this.$router.push({path: '/procedure/list', query: this.vueQueryParam});
},
}
}
</script>
<style>
.table-database-vue .el-table td, .table-database-vue .el-table th{padding: 5px 0;}
.table-database-vue .label{width: 140px; text-align: right;}
</style>

View File

@@ -0,0 +1,180 @@
<template>
<div class="table-procedure-vue">
<el-card style="margin: 10px;" shadow="never">
<div slot="header" class="clearfix">库信息</div>
<el-row>
<el-col :span="12"><span class="label">数据源</span>{{vueQueryParam.host}}</el-col>
<el-col :span="12"><span class="label">数据库</span>{{vueQueryParam.dbName}}</el-col>
</el-row>
</el-card>
<el-card style="margin: 10px;" shadow="never" header="函数管理">
<el-form :inline="true">
<el-form-item label="名称">
<el-input v-model="searchParam.name" placeholder="名字"></el-input>
</el-form-item>
<el-form-item label="类型">
<el-select v-model="searchParam.type" placeholder="类型">
<el-option value="">全部</el-option>
<el-option value="PROCEDURE" label="存储过程"></el-option>
<el-option value="FUNCTION" label="函数"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="procedureListLoading" @click="searchProcedureList" icon="el-icon-search">查询</el-button>
<el-button @click="createProc" icon="el-icon-circle-plus-outline">新建函数</el-button>
</el-form-item>
</el-form>
<el-table :data="procedureList" stripe border style="width: 100%;">
<el-table-column prop="name" label="名称" width="200"></el-table-column>
<el-table-column prop="type" label="类型" width="200">
<!--<template slot-scope="scope">{{scope.row.type=='PROCEDURE' ? '过程' : '函数'}}</template>-->
</el-table-column>
<el-table-column prop="definer" label="定义者"></el-table-column>
<el-table-column prop="created" label="创建时间"></el-table-column>
<el-table-column prop="action" label="操作">
<template slot-scope="scope">
<el-button type="primary" @click="doEditProc(scope.row)">编辑</el-button>
<el-button type="danger" @click="doDeleteProc(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 10px;"
@size-change="handlePageSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 30, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="tableTotalCount">
</el-pagination>
</el-card>
<!--新建函数弹窗-->
<el-dialog :inline="true" title="新建函数" :visible.sync="newProcedureDialogVisible" width="760px">
<el-form label-width="120px">
<el-form-item label="类型:">
<el-select v-model="newProcedureInfo.type" placeholder="请选择类型" style="width: 100%">
<el-option value="PROCEDURE" label="存储过程"></el-option>
<el-option value="FUNCTION" label="函数"></el-option>
</el-select>
</el-form-item>
<el-form-item label="函数名:">
<el-input v-model="newProcedureInfo.name" placeholder="请输入函数名"></el-input>
</el-form-item>
</el-form>
<div slot="footer" style="text-align: center;">
<el-button @click="newProcedureOk" type="primary">下一步</el-button>
<el-button @click="newProcedureDialogVisible=false" plain>取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import datasourceApi from '../../common/api/datasource'
export default {
data() {
return {
procedureListLoading: false,
vueQueryParam: {},
procedureList: [],
newProcedureDialogVisible: false,
newProcedureInfo: {
type: '',
name: '',
},
searchParam: {
name: '',
type: ''
},
pageSize: 30,
currentPage: 1,
tableTotalCount: 0,
};
},
mounted: function () {
// 延迟设置展开的目录edit比app先初始化
setTimeout(() => {
this.$emit('initLoadDataList', {
sourceId: this.vueQueryParam.sourceId,
host: this.vueQueryParam.host,
dbName: this.vueQueryParam.dbName
});
}, 500);
this.initQueryParam(this.$route);
this.searchProcedureList();
},
methods: {
initQueryParam(to) {
this.vueQueryParam = to.query;
let newName = {key: this.$route.fullPath, val: '函数管理-' + this.vueQueryParam.dbName};
this.$store.commit('global/addTableName', newName);
},
handleCurrentChange(to) {
this.currentPage = to;
this.searchProcedureList();
},
handlePageSizeChange(to) {
this.pageSize = to;
this.searchProcedureList();
},
searchProcedureList() {
this.procedureListLoading = true;
let param = {...this.vueQueryParam, ...this.searchParam, pageNum: this.currentPage, pageSize: this.pageSize};
datasourceApi.procedureList(param).then(json => {
if (this.currentPage == 1) {
this.tableTotalCount = json.total || 0;
}
this.procedureList = json.data || [];
this.procedureListLoading = false;
});
},
doEditProc(item) {
let param = {...this.vueQueryParam, typeName: item.type, procName: item.name};
this.$router.push({path: '/procedure/edit', query: param});
},
createProc() {
this.newProcedureDialogVisible = true;
},
newProcedureOk() {
if (!this.newProcedureInfo.type) {
this.$message.error("请先选择类型");return;
}
if (!this.newProcedureInfo.name) {
this.$message.error("请先输入函数名");return;
}
let param = {
...this.vueQueryParam,
typeName: this.newProcedureInfo.type,
procName: this.newProcedureInfo.name
};
this.newProcedureDialogVisible = false;
this.newProcedureInfo = {type: '', name: ''};
this.$router.push({path: '/procedure/edit', query: param});
},
doDeleteProc(item) {
let param = {
sourceId: this.vueQueryParam.sourceId,
dbName: this.vueQueryParam.dbName,
typeName: item.type,
procName: item.name
};
this.$confirm('确定要删除此存储过程吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
datasourceApi.deleteProcedure(param).then(json => {
this.$message.success("删除成功!");
this.searchProcedureList();
});
}).catch(() => {});
},
}
}
</script>
<style>
.table-procedure-vue .el-table td, .table-database-vue .el-table th{padding: 5px 0;}
</style>

View File

@@ -0,0 +1,135 @@
<template>
<div class="table-procedure-edit-vue">
<el-card style="margin: 10px;" shadow="never">
<div slot="header" class="clearfix">函数信息</div>
<el-row>
<el-col :span="6"><span class="label">数据源</span>{{vueQueryParam.host}}</el-col>
<el-col :span="6"><span class="label">数据库</span>{{vueQueryParam.dbName}}</el-col>
<el-col :span="6"><span class="label">类型</span>{{vueQueryParam.typeName}}</el-col>
<el-col :span="6"><span class="label">名称</span>{{vueQueryParam.procName}}</el-col>
</el-row>
</el-card>
<el-card style="margin: 10px;" shadow="never" v-loading="procedureInfoLoading">
<div slot="header" class="clearfix">
<span style="margin-right: 20px;">编辑函数</span>
<el-button type="" @click="saveProcedure" icon="el-icon-document-checked" size="mini">保存</el-button>
<!-- <el-button type="" @click="" icon="el-icon-video-play" size="mini">运行</el-button>-->
<!-- <el-button type="" @click="" icon="el-icon-video-pause" size="mini">停止</el-button>-->
</div>
<pre id="sqlExecutorEditor" style="width: 100%;height: 500px;margin-top: 0;"></pre>
</el-card>
<!--错误信息弹窗-->
<el-dialog title="保存函数失败" :visible.sync="saveProcedureErrVisible" :footer="null">
<div style="width: 700px;max-height: 500px;overflow: auto;">
<pre>{{saveProcedureErrInfo}}</pre>
</div>
</el-dialog>
</div>
</template>
<script>
import '../../common/lib/ace/ace'
import '../../common/lib/ace/theme-monokai'
import '../../common/lib/ace/mode-sql'
import '../../common/lib/ace/ext-language_tools'
import '../../common/lib/ace/snippets/sql'
import datasourceApi from '../../common/api/datasource'
export default {
data() {
return {
procedureInfoLoading: false,
vueQueryParam: {},
procedureInfo: {},
sqlExecutorEditor: {},
saveProcedureErrInfo: '',
saveProcedureErrVisible: false,
};
},
mounted: function () {
// 延迟设置展开的目录edit比app先初始化
setTimeout(() => {
this.$emit('initLoadDataList', {
sourceId: this.vueQueryParam.sourceId,
host: this.vueQueryParam.host,
dbName: this.vueQueryParam.dbName
});
}, 500);
let that = this;
this.sqlExecutorEditor = this.initAceEditor("sqlExecutorEditor", 20);
this.sqlExecutorEditor.setFontSize(16);
this.sqlExecutorEditor.commands.addCommand({
name: "execute-sql",
bindKey: {win: "Ctrl-S", mac: "Command-S"},
exec: function (editor) {
that.saveProcedure();
}
});
this.initQueryParam(this.$route);
this.searchProcedureDetail();
},
methods: {
initQueryParam(to) {
this.vueQueryParam = to.query;
let newName = {key: this.$route.fullPath, val: '编辑函数-' + this.vueQueryParam.procName};
this.$store.commit('global/addTableName', newName);
},
searchProcedureDetail() {
this.procedureInfoLoading = true;
datasourceApi.procedureDetail(this.vueQueryParam).then(json => {
this.procedureInfo = json.data || {};
this.procedureInfoLoading = false;
this.sqlExecutorEditor.setValue(this.procedureInfo.body, 1);
});
},
saveProcedure() {
this.procedureInfoLoading = true;
let param = {...this.vueQueryParam, procSql: this.sqlExecutorEditor.getValue()};
datasourceApi.saveProcedure(param).then(json => {
this.procedureInfoLoading = false;
let executeInfo = json.data || {};
if (!!executeInfo.errMsg) {
this.saveProcedureErrInfo = executeInfo.errMsg;
this.saveProcedureErrVisible = true;
} else {
this.$message.success("保存成功!");
}
});
},
doDeleteProc(item) {
let param = {
sourceId: this.vueQueryParam.sourceId,
dbName: this.vueQueryParam.dbName,
typeName: item.type,
procName: item.name
};
this.$confirm('确定要删除此存储过程吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
datasourceApi.deleteProcedure(param).then(json => {
this.$message.success("删除成功!");
});
}).catch(() => {});
},
initAceEditor(editor, minLines) {
return ace.edit(editor, {
theme: "ace/theme/monokai",
mode: "ace/mode/sql",
wrap: true,
autoScrollEditorIntoView: true,
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
minLines: minLines,
maxLines: 40,
});
},
}
}
</script>
<style>
.table-procedure-edit-vue .el-table td, .table-database-vue .el-table th{padding: 5px 0;}
</style>