初始化
This commit is contained in:
7
frontend/packages/DataSourceManagement/index.js
Normal file
7
frontend/packages/DataSourceManagement/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import DataSource from './src/index.vue'
|
||||
|
||||
DataSource.install = function (Vue) {
|
||||
Vue.component(DataSource.name, DataSource)
|
||||
}
|
||||
|
||||
export default DataSource
|
||||
194
frontend/packages/DataSourceManagement/index.vue
Normal file
194
frontend/packages/DataSourceManagement/index.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="application-setting-wrap">
|
||||
<div class="left-tab-box">
|
||||
<ul>
|
||||
<li
|
||||
v-for="tab in tabList"
|
||||
:key="tab.path"
|
||||
:class="{'tab-active': tab.active,'tab-style':true}"
|
||||
@click="openTab(tab)"
|
||||
>
|
||||
<icon-svg
|
||||
:name="tab.img"
|
||||
class="tabIconStyle"
|
||||
/>
|
||||
<span>{{ tab.name }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<el-scrollbar class="scroll-box">
|
||||
<div class="inner-router-view-wrap">
|
||||
<router-view v-if="isRresh" />
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from 'data-room-ui/assets/images/dataSourceIcon/export'
|
||||
import IconSvg from 'data-room-ui/SvgIcon'
|
||||
export default {
|
||||
name: 'DataSourceManagement',
|
||||
components: {
|
||||
IconSvg
|
||||
},
|
||||
provide () {
|
||||
return {
|
||||
refresh: this.refresh
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// appIcon: Icon.getNameList(),
|
||||
isRresh: true,
|
||||
activeTabName: '',
|
||||
currentPermission: 1,
|
||||
tabList: [
|
||||
{
|
||||
active: false,
|
||||
name: '数据源管理',
|
||||
path: window?.routers?.dataSourceUrl,
|
||||
// permissionRequire: 0
|
||||
img: Icon.getNameList()[0]
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
name: '数据集管理',
|
||||
path: window?.routers?.dataSetUrl,
|
||||
// permissionRequire: 9
|
||||
img: Icon.getNameList()[1]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
created () {
|
||||
this.tabList[0].path = window?.BS_CONFIG?.routers?.dataSourceUrl || '/data-sources/data-source-sets'
|
||||
this.tabList[1].path = window?.BS_CONFIG?.routers?.dataSetUrl || '/data-sources/data-set-configuration'
|
||||
},
|
||||
mounted () {
|
||||
this.openTab(this.tabList[0])
|
||||
},
|
||||
methods: {
|
||||
refresh () {
|
||||
this.isRresh = false
|
||||
this.$nextTick(() => {
|
||||
this.isRresh = true
|
||||
})
|
||||
},
|
||||
openTab (tab) {
|
||||
this.$router.push({
|
||||
path: tab.path
|
||||
})
|
||||
this.tabList.forEach((item) => {
|
||||
if (item.path !== tab.path) {
|
||||
item.active = false
|
||||
} else {
|
||||
item.active = true
|
||||
}
|
||||
})
|
||||
},
|
||||
setActiveTab (route) {
|
||||
this.$router.push({
|
||||
path: route.path
|
||||
})
|
||||
this.tabList.forEach((tab) => {
|
||||
if (tab.path === route.path) {
|
||||
tab.active = true
|
||||
} else {
|
||||
tab.active = false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.application-setting-wrap {
|
||||
display: flex;
|
||||
height: calc(100vh - 40px);
|
||||
overflow-y: hidden;
|
||||
background: #f5f7fa;
|
||||
|
||||
.left-tab-box {
|
||||
background: #fff;
|
||||
width: 290px;
|
||||
|
||||
ul {
|
||||
padding-left: 0;
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
padding-left: 20px;
|
||||
margin: 5px 0;
|
||||
img {
|
||||
width: 20px;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #007aff10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-active {
|
||||
background-color: #007aff10;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
border-left: 4px solid #007aff;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-tabs__item {
|
||||
text-align: left;
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
::v-deep .el-tabs__nav-wrap::after {
|
||||
background-color: #fff !important;
|
||||
}
|
||||
}
|
||||
.scroll-box {
|
||||
width: calc(100% - 300px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
margin: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.inner-router-view-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
::v-deep .el-scrollbar__view{
|
||||
height: 100%;
|
||||
.inner-router-view-wrap{
|
||||
height: 100%;
|
||||
.bs-table-box{
|
||||
height: calc(100vh - 205px);
|
||||
.el-table{
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tabIconStyle{
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
width="700px"
|
||||
title="提示"
|
||||
:visible.sync="checkDatasourceVisible"
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="handleClose"
|
||||
class="bs-dialog-wrap bs-el-dialog"
|
||||
>
|
||||
<div class="text-style">
|
||||
<div
|
||||
v-for="(item,index) in reasonList"
|
||||
:key="index"
|
||||
class="item"
|
||||
>
|
||||
<span v-if="reasonList.length>1"> {{ index+1 }}、</span>{{ item }}
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
slot="footer"
|
||||
class="dialog-footer"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleClose"
|
||||
>
|
||||
确定
|
||||
</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
reasonList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
checkDatasourceVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose () {
|
||||
this.checkDatasourceVisible = false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../assets/style/bsTheme.scss';
|
||||
::v-deep .el-dialog__body{
|
||||
min-height: 0 !important;
|
||||
}
|
||||
.item{
|
||||
padding: 8px 0;
|
||||
}
|
||||
.text-style{
|
||||
padding-right: 80px;
|
||||
color: var(--bs-el-text);
|
||||
}
|
||||
</style>
|
||||
337
frontend/packages/DataSourceManagement/src/index.vue
Normal file
337
frontend/packages/DataSourceManagement/src/index.vue
Normal file
@@ -0,0 +1,337 @@
|
||||
<template>
|
||||
<div class="bs-container">
|
||||
<!--数据源查看-->
|
||||
<div class="inner-container">
|
||||
<el-form
|
||||
:inline="true"
|
||||
class="filter-container"
|
||||
>
|
||||
<el-form-item class="filter-input filter-item">
|
||||
<el-input
|
||||
v-model="searchForm.sourceName"
|
||||
class="bs-el-input"
|
||||
placeholder="请输入数据源名称"
|
||||
clearable
|
||||
maxlength="200"
|
||||
@clear="searchData"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="filter-item">
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="searchLoading"
|
||||
icon="el-icon-search"
|
||||
@click="searchData"
|
||||
>
|
||||
查询
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item class="filter-item">
|
||||
<el-button
|
||||
class="bs-el-button-default"
|
||||
@click="addSource"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="bs-table-box">
|
||||
<el-table
|
||||
v-table
|
||||
v-loading="searchLoading"
|
||||
height="0"
|
||||
class="bs-el-table bs-scrollbar"
|
||||
:element-loading-text="loadingText"
|
||||
:data="dataSourceList"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-empty slot="empty" />
|
||||
<el-table-column
|
||||
prop="sourceName"
|
||||
label="数据源名称"
|
||||
align="left"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-radio
|
||||
v-if="isDialog"
|
||||
v-model="curRow"
|
||||
:label="scope.row"
|
||||
>
|
||||
{{ scope.row.sourceName }}
|
||||
</el-radio>
|
||||
<span v-else>{{ scope.row.sourceName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="sourceType"
|
||||
label="类型"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="remark"
|
||||
label="备注"
|
||||
align="left"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="200"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
class="bs-el-button-default"
|
||||
:loading="testBtnLoading.includes(scope.row.id)"
|
||||
@click="sourceLinkTest(scope.row)"
|
||||
>
|
||||
测试
|
||||
</el-button>
|
||||
<el-button
|
||||
class="bs-el-button-default"
|
||||
:disabled="scope.row.editable == 1 && !appCode"
|
||||
@click="viewSource(scope.row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
class="bs-el-button-default"
|
||||
:loading="scope.row.loading"
|
||||
:disabled="scope.row.editable == 1 && !appCode"
|
||||
@click="handleDelete(scope.row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="bs-pagination">
|
||||
<el-pagination
|
||||
class="bs-el-pagination"
|
||||
popper-class="bs-el-pagination"
|
||||
:current-page="current"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="size"
|
||||
:total="totalCount"
|
||||
background
|
||||
prev-text="上一页"
|
||||
next-text="下一页"
|
||||
layout="total, prev, pager, next,sizes"
|
||||
@size-change="sizeChangeHandle"
|
||||
@current-change="currentChangeHandle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 数据源新增/编辑 -->
|
||||
<set-datasource
|
||||
ref="setDatasource"
|
||||
:app-code="appCode"
|
||||
@refreshTable="init"
|
||||
/>
|
||||
<checkDatasource
|
||||
ref="checkDatasource"
|
||||
:reason-list="reasonList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import table from 'data-room-ui/js/utils/table.js'
|
||||
import '../style/index.scss'
|
||||
import { sourceLinkTest, datasourcePage, sourceRemove, dataSourceCheck } from 'data-room-ui/js/utils/dataSourceService'
|
||||
import setDatasource from './setDatasource.vue'
|
||||
import checkDatasource from './checkDatasource.vue'
|
||||
// import _ from 'lodash'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { pageMixins } from 'data-room-ui/js/mixins/page'
|
||||
export default {
|
||||
name: 'DataSource',
|
||||
directives: {
|
||||
table // 注册自定义指令
|
||||
},
|
||||
components: {
|
||||
setDatasource,
|
||||
checkDatasource
|
||||
},
|
||||
// 路由守卫-离开页面
|
||||
beforeRouteLeave (to, from, next) {
|
||||
const layoutEl = document.querySelector('.big-screen-router-view-wrap')
|
||||
if (layoutEl) {
|
||||
layoutEl.style.paddingLeft = '0'
|
||||
}
|
||||
next()
|
||||
},
|
||||
// 路由进入页面
|
||||
beforeRouteEnter (to, from, next) {
|
||||
const layoutEl = document.querySelector('.big-screen-router-view-wrap')
|
||||
if (layoutEl) {
|
||||
layoutEl.style.paddingLeft = '16px'
|
||||
}
|
||||
next()
|
||||
},
|
||||
mixins: [pageMixins],
|
||||
props: {
|
||||
isDialog: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
sourceId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
appCode: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
reasonList: [],
|
||||
testBtnLoading: [],
|
||||
loadingText: '',
|
||||
deling: false,
|
||||
searchLoading: false,
|
||||
dataSourceList: [],
|
||||
searchForm: {
|
||||
sourceName: '',
|
||||
sourceType: ''
|
||||
},
|
||||
size: 10,
|
||||
current: 1,
|
||||
curRow: null
|
||||
}
|
||||
},
|
||||
created () { },
|
||||
mounted () {
|
||||
this.init()
|
||||
const layoutEl = document.querySelector('.big-screen-router-view-wrap')
|
||||
if (layoutEl) {
|
||||
layoutEl.style.paddingLeft = '16px'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 获取当前选择数据集id
|
||||
getSourceId () {
|
||||
if (!this.isDialog) return
|
||||
if (this.curRow) {
|
||||
return this.curRow.id
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
// 单选数据集
|
||||
handleCurrentChange (currentRow) {
|
||||
this.curRow = currentRow
|
||||
},
|
||||
// 分页操作
|
||||
sizeChangeHandle (news) {
|
||||
this.size = news
|
||||
this.getDataList()
|
||||
},
|
||||
currentChangeHandle (newss) {
|
||||
this.current = newss
|
||||
this.getDataList()
|
||||
},
|
||||
// 查询数据
|
||||
searchData () {
|
||||
this.searchLoading = true
|
||||
this.loadingText = '正在查询数据...'
|
||||
// 重置current
|
||||
this.current = 1
|
||||
this.getDataList()
|
||||
},
|
||||
init () {
|
||||
this.current = 1
|
||||
this.getDataList()
|
||||
},
|
||||
getDataList () {
|
||||
const params = {
|
||||
current: this.current,
|
||||
size: this.size,
|
||||
sourceName: this.searchForm.sourceName,
|
||||
// sourceType: this.searchForm.sourceType,
|
||||
moduleCode: this.appCode
|
||||
}
|
||||
datasourcePage(params).then((data) => {
|
||||
this.totalCount = data.totalCount
|
||||
this.dataSourceList = data.list
|
||||
this.dataSourceList.forEach(r => {
|
||||
r.status = 0
|
||||
this.$set(r, 'loading', false)
|
||||
if (r.id === this.sourceId) {
|
||||
this.curRow = r
|
||||
}
|
||||
})
|
||||
this.searchLoading = false
|
||||
}).catch(() => {
|
||||
this.searchLoading = false
|
||||
})
|
||||
},
|
||||
addSource () {
|
||||
this.$refs.setDatasource.setDatasourceVisible = true
|
||||
this.$refs.setDatasource.title = '新增数据源'
|
||||
this.$refs.setDatasource.init()
|
||||
},
|
||||
viewSource (row) {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (row.editable == 1 && !this.appCode) return
|
||||
this.$refs.setDatasource.setDatasourceVisible = true
|
||||
this.$refs.setDatasource.title = '编辑数据源'
|
||||
this.$refs.setDatasource.init(cloneDeep(row))
|
||||
},
|
||||
handleDelete (row) {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (row.editable == 1 && !this.appCode) return
|
||||
row.loading = true
|
||||
dataSourceCheck(row.id).then((res) => {
|
||||
row.loading = false
|
||||
if (res.canDelete) {
|
||||
this.$confirm('确定删除当前数据源吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
customClass: 'bs-el-message-box'
|
||||
}).then(() => {
|
||||
sourceRemove(row.id).then((r) => {
|
||||
this.$message.success('删除成功')
|
||||
this.init()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.reasonList = res.reasons
|
||||
this.$refs.checkDatasource.checkDatasourceVisible = true
|
||||
}
|
||||
})
|
||||
},
|
||||
sourceLinkTest (row) {
|
||||
this.testBtnLoading.push(row.id)
|
||||
this.linkLoading = true
|
||||
sourceLinkTest(row).then((r) => {
|
||||
this.$message.success(r)
|
||||
this.linkLoading = false
|
||||
this.testBtnLoading.splice(this.testBtnLoading.indexOf(row.id), 1)
|
||||
}).catch(() => {
|
||||
this.linkLoading = false
|
||||
this.testBtnLoading.splice(this.testBtnLoading.indexOf(row.id), 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../assets/style/bsTheme.scss';
|
||||
|
||||
.bs-pagination {
|
||||
margin-top: 4px;
|
||||
padding-right: 16px;
|
||||
::v-deep .el-input__inner {
|
||||
|
||||
width: 110px !important;
|
||||
border: none;
|
||||
background: var(--bs-el-background-1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
438
frontend/packages/DataSourceManagement/src/setDatasource.vue
Normal file
438
frontend/packages/DataSourceManagement/src/setDatasource.vue
Normal file
@@ -0,0 +1,438 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
width="700px"
|
||||
:title="title"
|
||||
:visible.sync="setDatasourceVisible"
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="handleClose"
|
||||
class="bs-dialog-wrap bs-el-dialog"
|
||||
>
|
||||
<div
|
||||
v-loading="linkLoading"
|
||||
element-loading-text="正在测试连接..."
|
||||
style="padding-right: 80px;"
|
||||
>
|
||||
<el-form
|
||||
ref="dataForm"
|
||||
class="bs-el-form"
|
||||
:model="dataForm"
|
||||
:rules="dataForm.id ? updateRules : rules"
|
||||
size="small"
|
||||
label-position="right"
|
||||
:label-width="dataForm.advanceSettingFlag ? '200px' : '150px'"
|
||||
>
|
||||
<el-form-item
|
||||
label="类型"
|
||||
prop="sourceType"
|
||||
>
|
||||
<el-select
|
||||
v-model="dataForm.sourceType"
|
||||
placeholder="请选择类型"
|
||||
class="bs-el-select"
|
||||
popper-class="bs-el-select"
|
||||
clearable
|
||||
filterable
|
||||
@change="sourceTypeChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="sourceType in sourceTypeList"
|
||||
:key="sourceType.code"
|
||||
:label="sourceType.label"
|
||||
:value="sourceType.code"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="数据源名称"
|
||||
prop="sourceName"
|
||||
>
|
||||
<el-input
|
||||
v-model="dataForm.sourceName"
|
||||
placeholder="请输入数据源名称"
|
||||
class="bs-el-input"
|
||||
maxlength="200"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="JDBC URL"
|
||||
prop="url"
|
||||
>
|
||||
<el-input
|
||||
v-model="dataForm.url"
|
||||
placeholder="请输入JDBC URL"
|
||||
class="bs-el-input"
|
||||
type="textarea"
|
||||
rows="4"
|
||||
@keydown.enter.native="textareaKeydown"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="用户名"
|
||||
prop="username"
|
||||
>
|
||||
<el-input
|
||||
v-model="dataForm.username"
|
||||
placeholder="请输入用户名"
|
||||
class="bs-el-input"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="密码"
|
||||
prop="password"
|
||||
>
|
||||
<el-input
|
||||
v-model="dataForm.password"
|
||||
:placeholder="dataForm.id ? '请输入密码,不输入代表不更新' : '请输入密码'"
|
||||
class="bs-el-input"
|
||||
type="password"
|
||||
show-password
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="备注"
|
||||
prop="remark"
|
||||
>
|
||||
<el-input
|
||||
v-model="dataForm.remark"
|
||||
placeholder="请输入备注"
|
||||
class="bs-el-input"
|
||||
type="textarea"
|
||||
rows="4"
|
||||
maxlength="200"
|
||||
@keydown.enter.native="textareaKeydown"
|
||||
/>
|
||||
</el-form-item>
|
||||
<template v-if="dataForm.advanceSettingFlag">
|
||||
<el-form-item label="初始化连接数">
|
||||
<el-input v-model="dataForm.initConnNum" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最大活动连接数">
|
||||
<el-input v-model="dataForm.maxActiveConnNum" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最大空闲连接数">
|
||||
<el-input v-model="dataForm.maxIdleConnNum" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最小空闲连接数">
|
||||
<el-input v-model="dataForm.minIdleConnNum" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最大等待时间 (ms)">
|
||||
<el-input v-model="dataForm.maxWaitConnNum" />
|
||||
</el-form-item>
|
||||
<el-form-item label="SQL验证查询">
|
||||
<el-input
|
||||
v-model="dataForm.sqlCheck"
|
||||
type="text"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="获取连接前校验">
|
||||
<el-select
|
||||
v-model="dataForm.getconnCheckFlag"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
label="是"
|
||||
:value="1"
|
||||
/>
|
||||
<el-option
|
||||
label="否"
|
||||
:value="0"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="归还连接前校验">
|
||||
<el-select
|
||||
v-model="dataForm.returnCheckFlag"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
label="是"
|
||||
:value="1"
|
||||
/>
|
||||
<el-option
|
||||
label="否"
|
||||
:value="0"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启空闲回收器校验">
|
||||
<el-select
|
||||
v-model="dataForm.startIdleCheckFlag"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
label="是"
|
||||
:value="1"
|
||||
/>
|
||||
<el-option
|
||||
label="否"
|
||||
:value="0"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="空闲连接回收器休眠时间 (ms)">
|
||||
<el-input v-model="dataForm.idleConnDormantTime" />
|
||||
</el-form-item>
|
||||
<el-form-item label="空闲连接回收检查数">
|
||||
<el-input v-model="dataForm.idleConnCheckNum" />
|
||||
</el-form-item>
|
||||
<el-form-item label="保持空闲最小时间值 (s)">
|
||||
<el-input v-model="dataForm.keepIdleMinTime" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<span
|
||||
slot="footer"
|
||||
class="dialog-footer"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="sourceLinkCheck"
|
||||
>
|
||||
测试
|
||||
</el-button>
|
||||
<el-button
|
||||
class="bs-el-button-default"
|
||||
@click="handleClose"
|
||||
>
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submitForm"
|
||||
>
|
||||
确定
|
||||
</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { checkRepeat, sourceLinkTest, add, update } from 'data-room-ui/js/utils/dataSourceService'
|
||||
export default {
|
||||
props: {
|
||||
appCode: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
setDatasourceVisible: false,
|
||||
title: '',
|
||||
linkLoading: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
sourceName: '',
|
||||
sourceType: 'mysql',
|
||||
driverClassName: 'com.mysql.jdbc.Driver',
|
||||
username: '',
|
||||
password: '',
|
||||
url: 'jdbc:mysql://localhost:3306/db_name?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false&useOldAliasMetadataBehavior=true',
|
||||
remark: ''
|
||||
},
|
||||
rules: {
|
||||
sourceType: [
|
||||
{ required: true, message: '请选择数据源类型', trigger: 'blur' }
|
||||
],
|
||||
sourceName: [
|
||||
{ required: true, message: '请输入数据源名称', trigger: 'blur' },
|
||||
{ validator: this.validateSourceName, trigger: 'blur' }
|
||||
],
|
||||
driverClassName: [
|
||||
{ required: true, message: '请选择连接驱动', trigger: 'blur' }
|
||||
],
|
||||
database: [
|
||||
{ required: true, message: '请输入数据库名称', trigger: 'blur' },
|
||||
{ pattern: /^[^\u4e00-\u9fa5]+$/, message: '数据库名称不能包含汉字' }
|
||||
],
|
||||
host: [
|
||||
{ required: true, message: '请输入主机号', trigger: 'blur' },
|
||||
{
|
||||
pattern: /((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))/,
|
||||
message: '主机号格式有误'
|
||||
}
|
||||
],
|
||||
port: [
|
||||
{ required: true, message: '请输入端口', trigger: 'blur' },
|
||||
{ pattern: /^[0-9]*$/, message: '端口号只能为数字' }
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ pattern: /^[^\u4e00-\u9fa5]+$/, message: '用户名不能包含汉字' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' }
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: '请输入连接url', trigger: 'blur' }
|
||||
],
|
||||
coding: [
|
||||
{ required: true, message: '请选择编码', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
updateRules: {
|
||||
sourceType: [
|
||||
{ required: true, message: '请选择数据源类型', trigger: 'blur' }
|
||||
],
|
||||
sourceName: [
|
||||
{ required: true, message: '请输入数据源名称', trigger: 'blur' },
|
||||
{ validator: this.validateSourceName, trigger: 'blur' }
|
||||
],
|
||||
driverClassName: [
|
||||
{ required: true, message: '请选择连接驱动', trigger: 'blur' }
|
||||
],
|
||||
database: [
|
||||
{ required: true, message: '请输入数据库名称', trigger: 'blur' },
|
||||
{ pattern: /^[^\u4e00-\u9fa5]+$/, message: '数据库名称不能包含汉字' }
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: '请输入连接url', trigger: 'blur' }
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ pattern: /^[^\u4e00-\u9fa5]+$/, message: '用户名不能包含汉字' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sourceTypeList () {
|
||||
return window.BS_CONFIG?.sourceTypeList || [
|
||||
{ label: 'Mysql', code: 'mysql', name: 'com.mysql.jdbc.Driver', url: 'jdbc:mysql://localhost:3306/db_name?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false&useOldAliasMetadataBehavior=true' },
|
||||
{ label: 'ClickHouse', code: 'clickhouse', name: 'ru.yandex.clickhouse.ClickHouseDriver', url: 'jdbc:clickhouse://localhost:8123/db_name' },
|
||||
{ label: 'PostgreSQL', code: 'postgresql', name: 'org.postgresql.Driver', url: 'jdbc:postgresql://localhost:13308/db_name' },
|
||||
{ label: 'Oracle', code: 'oracle', name: 'oracle.jdbc.driver.OracleDriver', url: 'jdbc:oracle:thin:@localhost:1521:orcl' },
|
||||
{ label: 'Sqlserver', code: 'sqlserver', name: 'com.microsoft.sqlserver.jdbc.SQLServerDriver', url: 'jdbc:sqlserver://localhost:1433;databaseName=db_name' }
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 初始化
|
||||
init (row) {
|
||||
// 清除表单验证
|
||||
if (this.$refs.dataForm) {
|
||||
this.$refs.dataForm.clearValidate()
|
||||
}
|
||||
if (row && row.id) {
|
||||
this.dataForm = row
|
||||
}
|
||||
},
|
||||
// 名称校验
|
||||
validateSourceName (rule, value, callback) {
|
||||
checkRepeat({
|
||||
id: this.dataForm.id,
|
||||
sourceName: this.dataForm.sourceName,
|
||||
moduleCode: this.appCode
|
||||
}).then(r => {
|
||||
if (r) {
|
||||
callback(new Error('数据源名称已存在'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 数据源类型选择
|
||||
sourceTypeChange (code) {
|
||||
if (!this.dataForm.id && code) {
|
||||
this.dataForm.driverClassName = this.sourceTypeList.find(item => item.code === code)?.name
|
||||
this.$set(this.dataForm, 'url', this.sourceTypeList.find(item => item.code === code)?.url)
|
||||
}
|
||||
},
|
||||
// 阻止文本域回车换行
|
||||
textareaKeydown () {
|
||||
const e = window.event || arguments[0]
|
||||
if (e.key === 'Enter' || e.code === 'Enter' || e.keyCode === 13) {
|
||||
e.returnValue = false
|
||||
return false
|
||||
}
|
||||
},
|
||||
// 连接测试
|
||||
sourceLinkCheck () {
|
||||
let flag = 0
|
||||
this.$refs.dataForm.validate((valid) => {
|
||||
if (!valid) {
|
||||
flag = 1
|
||||
return false
|
||||
} else {
|
||||
if (flag === 0) {
|
||||
this.sourceLinkTest(this.dataForm)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
sourceLinkTest (row) {
|
||||
this.linkLoading = true
|
||||
sourceLinkTest(row).then((r) => {
|
||||
this.$message.success(r)
|
||||
this.linkLoading = false
|
||||
}).catch(() => {
|
||||
this.linkLoading = false
|
||||
})
|
||||
},
|
||||
// 取消重制
|
||||
handleClose () {
|
||||
this.$refs.dataForm.resetFields()
|
||||
this.dataForm = {
|
||||
id: '',
|
||||
sourceName: '',
|
||||
sourceType: 'mysql',
|
||||
driverClassName: 'com.mysql.jdbc.Driver',
|
||||
username: '',
|
||||
password: '',
|
||||
url: 'jdbc:mysql://localhost:3306/db_name?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false&useOldAliasMetadataBehavior=true',
|
||||
remark: ''
|
||||
}
|
||||
this.setDatasourceVisible = false
|
||||
},
|
||||
// 保存
|
||||
submitForm () {
|
||||
// mysql 需要包含useOldAliasMetadataBehavior
|
||||
// if (this.dataForm.sourceType == 'Mysql') {
|
||||
// if (this.dataForm.url.indexOf('useOldAliasMetadataBehavior') == -1) {
|
||||
// if (this.dataForm.url.indexOf('?') == -1) {
|
||||
// this.dataForm.url = this.dataForm.url + '?useOldAliasMetadataBehavior=true'
|
||||
// } else {
|
||||
// this.dataForm.url = this.dataForm.url + '&useOldAliasMetadataBehavior=true'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
this.$refs.dataForm.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.dataForm.id) {
|
||||
update({
|
||||
...this.dataForm,
|
||||
moduleCode: this.appCode,
|
||||
editable: this.appCode ? 1 : 0
|
||||
}).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
// 刷新表格
|
||||
this.$emit('refreshTable')
|
||||
this.handleClose()
|
||||
})
|
||||
} else {
|
||||
add({
|
||||
...this.dataForm,
|
||||
moduleCode: this.appCode,
|
||||
editable: this.appCode ? 1 : 0
|
||||
}).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
// 刷新表格
|
||||
this.$emit('refreshTable')
|
||||
this.handleClose()
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../assets//style/bsTheme.scss';
|
||||
</style>
|
||||
159
frontend/packages/DataSourceManagement/style/index.scss
Normal file
159
frontend/packages/DataSourceManagement/style/index.scss
Normal file
@@ -0,0 +1,159 @@
|
||||
.data-source-wrap {
|
||||
.el-input__inner {
|
||||
width: 100%;
|
||||
}
|
||||
.filter-input .el-input__inner {
|
||||
width: 200px;
|
||||
}
|
||||
.dsItem {
|
||||
height: 116px;
|
||||
}
|
||||
.card-list {
|
||||
margin: 0 10px 10px;
|
||||
.card-title {
|
||||
margin-top: 8px;
|
||||
padding: 0 16px;
|
||||
height: 40px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 16px;
|
||||
color: #4e5054;
|
||||
}
|
||||
.card-type {
|
||||
margin: 12px 0;
|
||||
padding: 0 16px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
color: #7c8496;
|
||||
}
|
||||
.card-button {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
background-color: #f6f8fb;
|
||||
height: 35px;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
.btn-col {
|
||||
width: 100%;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 14px;
|
||||
color: #7c8496;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
&:hover {
|
||||
color: #1183FF;
|
||||
}
|
||||
}
|
||||
.btn-disabled {
|
||||
&:hover {
|
||||
color: #7c8496;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
.btn-col::after {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
content: '';
|
||||
width: 1px;
|
||||
height: 16px;
|
||||
background: #e1e2e3;
|
||||
}
|
||||
.btn-col:last-of-type::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.add-card {
|
||||
margin: 0 10px 10px;
|
||||
height: 117px;
|
||||
line-height: 117px;
|
||||
text-align: center;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
.modal {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 117px;
|
||||
position: absolute;
|
||||
background: rgba(8, 8, 8, 0.15);
|
||||
color: #1183FF;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
&:hover {
|
||||
span {
|
||||
display: none;
|
||||
}
|
||||
.modal {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.searchInput{
|
||||
width: 100%;
|
||||
}
|
||||
.dsFontImage {
|
||||
width: 150px;
|
||||
height: 70px;
|
||||
line-height: 70px;
|
||||
text-align: center;
|
||||
background: rgba(33, 139, 255, 0.7);
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
}
|
||||
.FontIcon {
|
||||
height: 36px;
|
||||
width: 100%;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
// border-radius: 7px;
|
||||
background: rgba(33, 139, 255, 0.7);
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
::v-deep .el-button.item {
|
||||
border-width: 0;
|
||||
&:hover, &:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.dsType {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.dsName {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.el-dialog {
|
||||
.bs-container {
|
||||
// max-height: calc(90vh - 236px);
|
||||
.el-table {
|
||||
max-height: calc(90vh - 340px);
|
||||
}
|
||||
::v-deep .ztree {
|
||||
max-height: calc(90vh - 325px) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user