dataease/frontend/src/views/system/datasource/DsTree.vue

532 lines
14 KiB
Vue
Raw Normal View History

<template xmlns:el-col="http://www.w3.org/1999/html">
<el-col class="tree-style">
<el-col>
2022-05-20 00:31:17 +08:00
<el-row >
<el-tabs v-model="showView" @tab-click="changeTab" type="card">
<el-tab-pane v-for="(item, index) in editableTabs" :key="item.name" :label="item.title" :name="item.name">
</el-tab-pane>
</el-tabs>
</el-row>
<el-row>
<el-button icon="el-icon-plus" type="text" size="mini" style="float: left;" @click="addFolder"/>
</el-row>
<el-row>
<el-form>
<el-form-item class="form-item">
<el-input
v-model="key"
size="mini"
:placeholder="$t('chart.search')"
prefix-icon="el-icon-search"
clearable
2021-10-08 17:22:21 +08:00
class="main-area-input"
/>
</el-form-item>
</el-form>
</el-row>
<el-col class="custom-tree-container">
<div class="block">
<el-tree
2021-06-18 10:59:51 +08:00
ref="myDsTree"
:default-expanded-keys="expandedArray"
:data="tData"
node-key="id"
:expand-on-click-node="true"
2021-06-18 10:59:51 +08:00
:filter-node-method="filterNode"
@node-click="nodeClick"
>
<span slot-scope="{ node, data }" class="custom-tree-node-list father">
<span style="display: flex;flex: 1;width: 0;">
2022-02-18 17:59:19 +08:00
<span v-if="data.type !== 'folder' && data.status !== 'Error' && data.status !== 'Warning'">
2021-11-24 18:49:41 +08:00
<svg-icon icon-class="datasource" class="ds-icon-scene"/>
</span>
<span v-if="data.status === 'Error'">
2021-11-24 18:49:41 +08:00
<svg-icon icon-class="exclamationmark" class="ds-icon-scene"/>
2021-08-27 17:56:10 +08:00
</span>
2022-02-18 17:59:19 +08:00
<span v-if="data.status === 'Warning'">
<svg-icon icon-class="exclamationmark2" class="ds-icon-scene"/>
</span>
<span v-if="data.type === 'folder'">
2021-11-24 18:49:41 +08:00
<i class="el-icon-folder"/>
</span>
2022-02-18 17:59:19 +08:00
<span v-if=" data.status === 'Error'"
style="margin-left: 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<el-tooltip effect="dark" :content="$t('datasource.in_valid')" placement="right">
<span>
{{ data.name }}
</span>
</el-tooltip>
</span>
2022-02-18 17:59:19 +08:00
<span v-if=" data.status === 'Warning'"
style="margin-left: 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<el-tooltip effect="dark" :content="$t('datasource.warning')" placement="right">
<span>
{{ data.name }}
</span>
</el-tooltip>
</span>
<span v-if="data.status !== 'Error' && data.status !== 'Warning'"
2021-11-24 18:49:41 +08:00
style="margin-left: 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
{{ data.name }}
</span>
</span>
<span class="child">
<span v-if="data.type ==='folder'" @click.stop>
2021-06-24 11:09:07 +08:00
<span class="el-dropdown-link">
<el-button
icon="el-icon-plus"
type="text"
size="small"
@click="addFolderWithType(data)"
/>
2021-06-24 11:09:07 +08:00
</span>
</span>
<span v-if="data.type !=='folder'" style="margin-left: 12px;" @click.stop>
<span v-if="hasDataPermission('manage',data.privileges)" class="el-dropdown-link">
<el-button
icon="el-icon-delete"
type="text"
size="small"
@click="_handleDelete(data)"
/>
</span>
</span>
</span>
</span>
</el-tree>
</div>
</el-col>
2022-05-20 00:31:17 +08:00
<el-dialog v-dialogDrag :title="dialogTitle" :visible="editDriver" :show-close="false" width="50%" append-to-body>
<el-form ref="driverForm" :model="driverForm" label-position="right" label-width="100px" :rules="rule">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="driverForm.name" />
</el-form-item>
<el-form-item :label="$t('commons.description')" prop="desc">
<el-input v-model="driverForm.desc" />
</el-form-item>
<el-form-item :label="$t('datasource.type')" prop="type">
<el-select
v-model="driverForm.type"
:placeholder="$t('datasource.please_choose_type')"
class="select-width"
:disabled="disabledModifyType"
filterable
>
<el-option
v-for="item in dsTypes"
:key="item.type"
:label="item.name"
:value="item.type"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="close()">{{ $t('commons.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveDriver(driverForm)">{{ $t('commons.save') }}
</el-button>
</div>
</el-dialog>
</el-col>
</el-col>
</template>
<script>
2022-05-20 00:31:17 +08:00
import {
listDatasource,
listDatasourceByType,
listDriverByType,
delDs,
listDatasourceType,
listDrivers,
addDriver, delDriver
} from '@/api/system/datasource'
import { mapGetters } from 'vuex'
import i18n from "@/lang";
export default {
name: 'DsTree',
props: {
datasource: {
type: Object,
default: null
}
},
data() {
return {
expandedArray: [],
2021-06-18 10:59:51 +08:00
tData: [],
2022-04-15 16:08:33 +08:00
dsTypes: [],
2021-06-18 10:59:51 +08:00
showSearchInput: false,
2022-05-20 00:31:17 +08:00
key: '',
showView: 'Datasource',
dialogTitle: '',
editDriver: false,
driverForm: {
name: '',
desc: '',
type: ''
},
disabledModifyType: false,
rule: {
name: [{required: true, message: i18n.t('datasource.input_name'), trigger: 'blur'},
{min: 2, max: 50, message: i18n.t('datasource.input_limit_2_25', [2, 25]), trigger: 'blur'}],
desc: [{required: true, message: i18n.t('datasource.input_name'), trigger: 'blur'},
{min: 2, max: 200, message: i18n.t('datasource.input_limit_2_25', [2, 25]), trigger: 'blur'}],
type: [{required: true, message: i18n.t('datasource.please_choose_type'), trigger: 'blur'}]
},
editableTabs: [{
title: i18n.t('commons.datasource'),
name: 'Datasource'
}]
2021-06-18 10:59:51 +08:00
}
},
watch: {
key(val) {
this.$refs.myDsTree.filter(val)
}
},
2022-05-20 00:31:17 +08:00
computed: {
...mapGetters([
'user'
])
},
2022-04-18 11:59:17 +08:00
created() {
this.queryTreeDatas()
2022-04-15 16:08:33 +08:00
this.datasourceTypes()
2022-05-20 00:31:17 +08:00
if(this.user.isAdmin){
this.editableTabs.push({
title: i18n.t('driver.mgm'),
name: 'Driver'
})
}
},
methods: {
2021-06-18 10:59:51 +08:00
filterNode(value, data) {
if (!value) return true
return data.name.indexOf(value) !== -1
},
showSearchWidget() {
this.showSearchInput = true
},
closeSearchWidget() {
this.key = ''
this.showSearchInput = false
},
queryTreeDatas() {
2022-05-20 00:31:17 +08:00
if(this.showView === 'Datasource'){
listDatasource().then(res => {
this.tData = this.buildTree(res.data)
})
}
if(this.showView === 'Driver'){
listDrivers().then(res => {
this.tData = this.buildTree(res.data)
})
}
},
2022-04-15 16:08:33 +08:00
datasourceTypes() {
listDatasourceType().then(res => {
this.dsTypes = res.data
})
},
refreshType(datasource) {
2022-05-20 00:31:17 +08:00
const method = this.showView === 'Datasource' ? listDatasourceByType : listDriverByType
let typeData = []
2022-05-20 00:31:17 +08:00
method(datasource.type).then(res => {
typeData = this.buildTree(res.data)
2022-02-18 17:59:19 +08:00
if (typeData.length === 0) {
let index = this.tData.findIndex(item => {
2022-02-18 17:59:19 +08:00
if (item.id === datasource.type) {
return true;
}
})
2022-02-18 17:59:19 +08:00
this.tData.splice(index, 1)
} else {
let find = false;
for (let index = 0; index < this.tData.length; index++) {
if (typeData[0].id === this.tData[index].id) {
this.tData[index].children = typeData[0].children
find = true
}
}
2022-02-18 17:59:19 +08:00
if (!find) {
this.tData.push(typeData[0])
}
}
})
},
buildTree(array) {
const types = {}
const newArr = []
for (let index = 0; index < array.length; index++) {
const element = array[index]
2021-08-27 17:56:10 +08:00
if (this.msgNodeId) {
if (element.id === this.msgNodeId) {
element.msgNode = true
}
}
if (!(element.type in types)) {
types[element.type] = []
// newArr.push(...element, ...{ children: types[element.type] })
2021-11-24 18:49:41 +08:00
newArr.push({
id: element.type,
2022-04-15 16:08:33 +08:00
name: element.typeDesc,
2021-11-24 18:49:41 +08:00
type: 'folder',
children: types[element.type]
})
}
types[element.type].push(element)
// newArr.children.push({ id: element.id, label: element.name })
}
return newArr
},
addFolder() {
2022-05-20 00:31:17 +08:00
if(this.showView === 'Driver'){
this.dialogTitle = this.$t('driver.driver')
this.editDriver = true
// this.switchMain('DriverForm', {}, this.tData, this.dsTypes)
}else {
this.switchMain('DsForm', {}, this.tData, this.dsTypes)
}
},
2022-05-20 00:31:17 +08:00
changeTab() {
this.expandedArray = []
this.tData = []
this.queryTreeDatas()
},
addFolderWithType(data) {
2022-05-20 00:31:17 +08:00
if(this.showView === 'Driver'){
this.driverForm.type = data.id
this.dialogTitle = this.$t('driver.driver')
this.editDriver = false
this.switchMain('DriverForm', {}, this.tData, this.dsTypes)
}else {
this.switchMain('DsForm', {type: data.id}, this.tData, this.dsTypes)
}
},
nodeClick(node, data) {
if (node.type === 'folder') return
this.showInfo(data)
},
clickFileMore(param) {
2021-11-24 18:49:41 +08:00
const {optType, data} = param
switch (optType) {
case 'edit':
this.edit(data)
break
case 'delete':
this._handleDelete(data)
break
default:
break
}
},
beforeClickFile(optType, data, node) {
2021-11-24 18:49:41 +08:00
return {optType, data, node}
},
edit(row) {
2022-04-15 16:08:33 +08:00
this.switchMain('DsForm', row, this.tData, this.dsTypes)
},
showInfo(row) {
2021-11-24 18:49:41 +08:00
const param = {...row.data, ...{showModel: 'show'}}
2022-05-20 00:31:17 +08:00
if(this.showView === 'Datasource'){
this.switchMain('DsForm', param, this.tData, this.dsTypes)
}else {
this.switchMain('DriverForm', param, this.tData, this.dsTypes)
}
},
_handleDelete(datasource) {
this.$confirm(this.$t('datasource.delete_warning'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
2022-05-20 00:31:17 +08:00
const method = this.showView === 'Datasource' ? delDs : delDriver
method(datasource.id).then(res => {
if(res.success){
this.$success(this.$t('commons.delete_success'))
2022-04-15 16:08:33 +08:00
this.switchMain('DataHome', {}, this.tData, this.dsTypes)
this.refreshType(datasource)
}else {
this.$message({
type: 'error',
message: res.message
})
}
})
}).catch(() => {
this.$message({
type: 'info',
message: this.$t('commons.delete_cancelled')
})
})
},
2022-04-15 16:08:33 +08:00
switchMain(component, componentParam, tData, dsTypes) {
this.$emit('switch-main', {
component,
componentParam,
2022-04-15 16:08:33 +08:00
tData,
dsTypes
})
2021-08-27 17:56:10 +08:00
},
markInvalid(msgParam) {
const param = JSON.parse(msgParam)
const msgNodeId = param.id
this.msgNodeId = msgNodeId
this.$nextTick(() => {
this.tData.forEach(folder => {
const nodes = folder.children
nodes.forEach(node => {
if (node.id === msgNodeId) {
node.msgNode = true
}
})
})
})
2022-05-20 00:31:17 +08:00
},
close() {
this.$refs['driverForm'].resetFields()
this.editDriver = false
this.driverForm = {
name: '',
desc: '',
type: ''
}
},
saveDriver(driverForm) {
this.$refs['driverForm'].validate((valid) => {
if (valid) {
addDriver(driverForm).then(res => {
this.$message({
message: this.$t('dataset.save_success'),
type: 'success',
showClose: true
})
this.refreshType(driverForm)
this.close()
})
} else {
return false
}
})
},
}
}
</script>
<style lang="scss" scoped>
2021-11-24 18:49:41 +08:00
.el-divider--horizontal {
margin: 12px 0
}
2021-11-24 18:49:41 +08:00
.search-input {
padding: 12px 0;
}
2021-11-24 18:49:41 +08:00
.custom-tree-container {
margin-top: 10px;
}
2021-11-24 18:49:41 +08:00
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
2021-11-24 18:49:41 +08:00
.custom-tree-node-list {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding: 0 8px;
}
2021-11-24 18:49:41 +08:00
.tree-list > > > .el-tree-node__expand-icon.is-leaf {
display: none;
}
2021-11-24 18:49:41 +08:00
.custom-position {
flex: 1;
display: flex;
align-items: center;
font-size: 14px;
flex-flow: row nowrap;
}
2021-11-24 18:49:41 +08:00
.form-item {
margin-bottom: 0;
}
2021-11-24 18:49:41 +08:00
.title-css {
height: 26px;
}
2021-11-24 18:49:41 +08:00
.title-text {
line-height: 26px;
}
2021-11-24 18:49:41 +08:00
.dialog-css > > > .el-dialog__header {
padding: 20px 20px 0;
}
2021-11-24 18:49:41 +08:00
.dialog-css > > > .el-dialog__body {
padding: 10px 20px 20px;
}
2021-11-24 18:49:41 +08:00
.form-item > > > .el-form-item__label {
font-size: 12px;
}
2021-11-24 18:49:41 +08:00
.scene-title {
width: 100%;
display: flex;
}
.scene-title-name {
width: 100%;
overflow: hidden;
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
}
.father .child {
/*display: none;*/
visibility: hidden;
}
.father:hover .child {
/*display: inline;*/
visibility: visible;
}
.tree-style {
padding: 10px 15px;
height: 100%;
overflow-y: auto;
}
.msg-node-class {
color: red;
> > > i {
2021-08-27 17:56:10 +08:00
color: red;
}
2021-11-24 18:49:41 +08:00
}
</style>