You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

896 lines
26 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div
id="box"
class="bs-container"
@mousemove="mousemoveOnBox"
@mouseup="mouseupOnBox"
>
<el-row
v-show="datasetType === null"
type="flex"
class="layout"
>
<div
id="left-box"
class="left-box"
:style="{ 'transition': transition + 's' }"
>
<div class="inner-container">
<TypeTree
ref="datasetsTypeTree"
:dataset-type-list="datasetTypeList"
:app-code="appCode"
@nodeClick="nodeClick"
@refreshData="refreshData"
@expandedNodes="expandedNodes"
@reCategory="getTreeList"
/>
</div>
</div>
<div
class="right-box inner-container"
:style="{ 'transition': transition + 's' }"
>
<div
id="resize"
class="resize pack-up-box"
@mousedown="mousedown"
@mouseup="mouseup"
@mousemove="mousemove"
>
<a
v-if="isPackUpTree"
@click="packUpTree"
@mousedown="resize = null"
@mouseup="resize = null"
@mousemove="resize = null"
>
<i :class="isPackUpTree === false ? 'el-icon-caret-left' : 'el-icon-caret-right'" />
</a>
<a
v-else
class="visible-pack-up"
>
<span>||</span>
</a>
</div>
<el-form
ref="queryForm"
:model="queryForm"
class="filter-container bs-el-form"
@submit.native.prevent
>
<el-form-item
class="filter-item"
prop="name"
>
<el-input
v-model="queryForm.name"
class="bs-el-input"
placeholder="请输入数据集名称"
clearable
@keyup.enter.native="handleSearch()"
@clear="handleSearch()"
/>
</el-form-item>
<el-form-item
class="filter-item"
prop="labelIds"
>
<el-select
v-model="queryForm.labelIds"
class="bs-el-select"
popper-class="bs-el-select"
clearable
filterable
multiple
collapse-tags
placeholder="请选择数据集关联标签"
@clear="handleSearch()"
>
<el-option
v-for="labelItem in labelList"
:key="labelItem.id"
:label="labelItem.labelName"
:value="labelItem.id"
/>
</el-select>
</el-form-item>
<el-form-item class="filter-item">
<el-button
:loading="dataListLoading"
type="primary"
icon="el-icon-search"
@click="handleSearch()"
>
查询
</el-button>
</el-form-item>
<el-form-item class="filter-item">
<el-button
v-if="toAdd"
class="bs-el-button-default"
@click="addDataset"
>
新增
</el-button>
</el-form-item>
</el-form>
<div class="bs-table-box">
<el-table
v-if="isDialog"
ref="userTable"
v-loading="dataListLoading"
class="bs-el-table bs-scrollbar"
:element-loading-text="loadingText"
:data="tableData"
:header-cell-style="sortStyle"
@sort-change="reSort"
@current-change="handleCurrentChange"
@select="selectDs"
@select-all="selectAll"
>
<el-empty slot="empty" />
<el-table-column
v-if="isDialog && multiple"
type="selection"
width="55"
/>
<el-table-column
prop="name"
label="数据集名称"
align="left"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-radio
v-if="isDialog && !multiple"
v-model="curRow"
:label="scope.row"
>
{{ scope.row.name }}
</el-radio>
<span v-else>{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column
prop="datasetType"
label="数据集类型"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<span>{{ datasetTypeList.find(type=>type.datasetType===scope.row.datasetType) ? datasetTypeList.find(type=>type.datasetType===scope.row.datasetType).name : '其他' }}</span>
</template>
</el-table-column>
<el-table-column
prop="labelIds"
label="标签"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<span>{{ getLabels(scope.row.labelIds).join(',') }}</span>
</template>
</el-table-column>
<el-table-column
prop="remark"
label="备注"
align="left"
show-overflow-tooltip
/>
<!--操作栏-->
<el-table-column
v-if="doEdit||isDelete"
label="操作"
width="200"
align="center"
>
<template
v-if="showOperate(scope.row.datasetType)"
slot-scope="scope"
>
<el-button
v-if="doEdit"
class="bs-el-button-default"
:disabled="scope.row.editable === 1 && !appCode"
@click="toEdit(scope.row.id, scope.row.datasetType, scope.row.name, scope.row.typeId)"
>
编辑
</el-button>
<el-button
v-if="isDelete"
class="bs-el-button-default"
:loading="scope.row.loading"
:disabled="scope.row.editable === 1 && !appCode"
@click="delDataset(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-table
v-else
ref="userTable"
v-table
v-loading="dataListLoading"
height="0"
class="bs-el-table bs-scrollbar"
:element-loading-text="loadingText"
:data="tableData"
:header-cell-style="sortStyle"
@sort-change="reSort"
@current-change="handleCurrentChange"
@select="selectDs"
@select-all="selectAll"
>
<el-empty slot="empty" />
<el-table-column
v-if="isDialog && multiple"
type="selection"
width="55"
/>
<el-table-column
prop="name"
label="数据集名称"
align="left"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-radio
v-if="isDialog && !multiple"
v-model="curRow"
:label="scope.row"
>
{{ scope.row.name }}
</el-radio>
<span v-else>{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column
prop="datasetType"
label="数据集类型"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<span>{{ datasetTypeList.find(type=>type.datasetType===scope.row.datasetType) ? datasetTypeList.find(type=>type.datasetType===scope.row.datasetType).name : '其他' }}</span>
</template>
</el-table-column>
<el-table-column
prop="labelIds"
label="标签"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<span>{{ getLabels(scope.row.labelIds).join(',') }}</span>
</template>
</el-table-column>
<el-table-column
prop="remark"
label="备注"
align="left"
show-overflow-tooltip
/>
<!--操作栏-->
<el-table-column
v-if="doEdit||isDelete"
label="操作"
width="200"
align="center"
>
<template
v-if="showOperate(scope.row.datasetType)"
slot-scope="scope"
>
<el-button
v-if="doEdit"
class="bs-el-button-default"
:disabled="scope.row.editable === 1 && !appCode"
@click="toEdit(scope.row.id, scope.row.datasetType, scope.row.name, scope.row.typeId)"
>
编辑
</el-button>
<el-button
v-if="isDelete"
class="bs-el-button-default"
:loading="scope.row.loading"
:disabled="scope.row.editable === 1 && !appCode"
@click="delDataset(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>
</el-row>
<!-- 新增-类型窗口 -->
<DatasetTypeDialog
ref="DatasetTypeDialog"
:dataset-type-list="datasetTypeList"
@openAddForm="openAddForm"
/>
<checkDatasource
ref="checkDatasource"
:reason-list="reasonList"
/>
<component
:is="componentData.component"
v-if="datasetType"
ref="EditForm"
:key="componentData.key"
:config="componentData.config"
:dataset-id="datasetId"
:dataset-name="datasetName"
:type-id="typeId"
:is-edit="isEdit"
:app-code="appCode"
@back="back"
>
<template #output-field-table-column>
<slot name="output-field-table-column" />
</template>
</component>
</div>
</template>
<script>
import TypeTree from './TypeTree.vue'
import JsEditForm from './JsEditForm.vue'
import JsonEditForm from './JsonEditForm.vue'
import table from 'data-room-ui/js/utils/table.js'
import ScriptEditForm from './ScriptEditForm.vue'
import checkDatasource from 'data-room-ui/DataSourceManagement/src/checkDatasource.vue'
import CustomEditForm from './CustomEditForm.vue'
import { pageMixins } from 'data-room-ui/js/mixins/page'
import OriginalEditForm from './OriginalEditForm.vue'
import HttpEditForm from './HttpEditForm.vue'
import DatasetTypeDialog from './DatasetTypeDialog.vue'
import StoredProcedureEditForm from './StoredProcedureEditForm.vue'
import { datasetPage, datasetRemove, datasetCheck } from 'data-room-ui/js/utils/datasetConfigService'
import { getLabelList } from 'data-room-ui/js/utils/LabelConfigService'
export default {
name: 'DataSetManagement',
directives: {
table // 注册自定义指令
},
components: {
TypeTree,
DatasetTypeDialog,
OriginalEditForm,
CustomEditForm,
JsonEditForm,
StoredProcedureEditForm,
ScriptEditForm,
JsEditForm,
checkDatasource,
HttpEditForm
},
mixins: [pageMixins],
props: {
multiple: {
type: Boolean,
default: false
},
isDialog: {
type: Boolean,
default: false
},
dsValue: {
type: [Array, Object],
default: null
},
appCode: {
type: String,
default: ''
},
isBorder: {
type: Boolean,
default: false
},
toAdd: {
type: Boolean,
default: true
},
doEdit: {
type: Boolean,
default: true
},
isDelete: {
type: Boolean,
default: true
}
},
data () {
return {
reasonList: [],
datasetType: null,
isEdit: false,
categoryData: [],
tableData: [], // 表格数据
queryForm: {
name: '',
datasetType: '',
typeId: '', // 分类id
labelIds: []
}, // 查询条件
// 数据集类型
datasetTypeList: [],
labelList: [],
isPackUpTree: false,
transition: 0.1,
loadingText: '正在加载数据',
dataListLoading: false,
leftBox: null,
rightBox: null,
startX: null,
event: null,
endX: null,
resize: null,
datasetId: '', // 数据集Id用于详情与编辑
datasetName: '', // 数据集名称
typeId: '', // 详情typeId
curRow: null,
multipleSelection: [],
// 远程组件
componentData: {
component: null,
config: null,
key: new Date().getTime()
}
}
},
computed: {
allType () {
return this.datasetTypeList.map(item => item.datasetType).filter(item => item !== '')
}
},
watch: {
datasetType (value) {
if (value === null) {
this.datasetId = ''
this.datasetName = ''
this.isEdit = false
}
}
},
mounted () {
this.init()
if (/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)) {
// 当前浏览器为Safari浏览器
// 执行相关操作
document.addEventListener('mousemove', function (event) {
if (event.buttons === 1) {
event.preventDefault()
}
})
}
},
methods: {
getLabels (list) {
const arr = []
list?.forEach((item) => {
arr.push(this.labelList.filter(x => x.id === item)[0]?.labelName)
})
return arr
},
toggleRowSelection () {
this.$nextTick(() => {
const dsIds = this.multipleSelection.map(ds => ds.id)
this.$refs.userTable.clearSelection()
this.tableData.forEach(item => {
if (dsIds.includes(item.id)) {
this.$refs.userTable.toggleRowSelection(item, true)
}
})
})
},
// 全选
selectAll (selection) {
if (this.isDialog && this.multiple) {
if (selection.length) {
const dsIds = this.multipleSelection.map(ds => ds.id)
selection.forEach(ds => {
if (!dsIds.includes(ds.id)) {
this.multipleSelection.push(ds)
}
})
} else {
this.tableData.forEach(row => {
const dsIds = this.multipleSelection.map(ds => ds.id)
const i = dsIds.indexOf(row.id)
if (i > -1) this.multipleSelection.splice(i, 1)
})
}
}
},
// 手动勾选
selectDs (selection, row) {
if (this.isDialog && this.multiple) {
let dsIndex = null
const ds = this.multipleSelection.find((ds, index) => {
if (ds.id === row.id) {
dsIndex = index
return ds
}
})
if (!ds) {
this.multipleSelection.push(row)
} else {
this.multipleSelection.splice(dsIndex, 1)
}
}
},
// 获取选中数据集信息
getSelectDs () {
if (!this.isDialog) return
if (this.multiple) {
// 多选返回
return this.multipleSelection
} else {
// 单选返回
return this.curRow ? this.curRow : null
}
},
// 单选数据集
handleCurrentChange (currentRow) {
this.curRow = currentRow
},
// 删除数据集
delDataset (row) {
row.loading = true
datasetCheck(row.id).then((res) => {
row.loading = false
if (res.canDelete) {
this.$confirm('确定删除当前数据集吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
customClass: 'bs-el-message-box'
}).then(() => {
datasetRemove(row.id).then(res => {
this.init(false)
this.$message.success('删除成功')
})
}).catch(() => {
})
} else {
this.reasonList = res.reasons
this.$refs.checkDatasource.checkDatasourceVisible = true
}
})
},
// 详情
toPreview (id, type, name, typeId) {
this.datasetId = id
this.datasetType = type
this.datasetName = name
this.typeId = typeId
this.isEdit = false
},
toEdit (id, type, name, typeId) {
this.datasetId = id
this.datasetType = type
this.componentData = this.getComponents(this.datasetTypeList.find(item => item?.datasetType === type)?.componentName) ?? ''
this.datasetName = name
this.typeId = typeId
this.isEdit = true
},
// 回到管理端
back () {
this.datasetType = null
this.isEdit = false
},
// 新增数据集-类型
openAddForm (type, componentName) {
this.datasetType = type
this.componentData = this.getComponents(componentName)
this.typeId = this.queryForm.typeId
this.isEdit = true
},
showOperate (datasetType) {
return this.getComponents(this.datasetTypeList.find(type => type.datasetType === datasetType)?.componentName)?.config?.showOperate ?? true
},
getComponents (componentName) {
const components = Object.values(this.$options.components)
let remoteComponentData = null
if (window.BS_CONFIG?.customDatasetComponents && window.BS_CONFIG?.customDatasetComponents.length > 0) {
// 获取远程组件
remoteComponentData = window.BS_CONFIG?.customDatasetComponents.find(item => item.config.componentName === componentName)
}
return {
component: components.find(component => component.name === componentName) || remoteComponentData?.vueFile,
config: remoteComponentData?.config || null,
key: new Date().getTime()
}
},
// 初始化
init (temp = true) {
if (temp) {
this.getTreeList()
}
if (this.isDialog) {
if (this.multiple) {
this.multipleSelection = this.dsValue ? this.dsValue : []
} else {
this.curRow = this.dsValue
}
}
this.current = 1
const list = [
{ name: '全部', datasetType: '' },
{ name: '原始数据集', datasetType: 'original', componentName: 'OriginalEditForm', description: '直接查询某个数据库表' },
{ name: '自助数据集', datasetType: 'custom', componentName: 'CustomEditForm', description: '自定义SQL语句查询' },
{ name: '存储过程数据集', datasetType: 'storedProcedure', componentName: 'StoredProcedureEditForm', description: '调用数据库存储过程查询' },
{ name: 'JSON数据集', datasetType: 'json', componentName: 'JsonEditForm', description: '直接定义静态数据' },
{ name: 'JS数据集', datasetType: 'js', componentName: 'JsEditForm', description: '编写JS代码进行动态模拟数据创建' },
{ name: 'HTTP数据集', datasetType: 'http', componentName: 'HttpEditForm', description: '接入第三方HTTP服务查询' },
{ name: '脚本数据集', datasetType: 'script', componentName: 'ScriptEditForm', description: '支持ES、Mongodb、国产化数据库、自定义Java代码查询' }
]
if (window.BS_CONFIG?.datasetTypeList && window.BS_CONFIG?.datasetTypeList?.length !== 0) {
this.datasetTypeList = [{ name: '全部', datasetType: '' }, ...list.filter(item => window.BS_CONFIG?.datasetTypeList.findIndex(x => x === item.datasetType) !== -1)]
} else {
this.datasetTypeList = [
...list
]
}
if (window.BS_CONFIG?.customDatasetComponents && window.BS_CONFIG?.customDatasetComponents.length > 0) {
// 将获得到的远程数据集进行组装
window.BS_CONFIG?.customDatasetComponents.forEach((item) => {
this.datasetTypeList.push({ name: item.config.name, datasetType: item.config.datasetType, componentName: item.config.componentName })
})
}
this.getDataList()
// getLabelList().then(res => {
// this.labelList = res
// })
},
// 新增数据集
addDataset () {
this.$refs.DatasetTypeDialog.dialogVisible = true
},
selectChange () {
this.getDataList()
},
getTreeList () {
},
// 获取表格数据
getDataList () {
getLabelList().then(res => {
this.labelList = res
})
this.dataListLoading = true
datasetPage({
current: this.current,
size: this.size,
moduleCode: this.appCode,
...this.queryForm,
datasetType: this.queryForm.datasetType === '' ? [...this.allType] : [this.queryForm.datasetType]
}).then((data) => {
this.tableData = data.list
this.tableData.forEach(r => {
this.$set(r, 'loading', false)
})
if (this.isDialog) {
if (this.multiple && this.multipleSelection.length) {
this.toggleRowSelection()
} else if (this.curRow.id) {
const ds = this.tableData.find(item => item.id === this.curRow.id)
if (ds) this.curRow = ds
}
}
this.totalCount = data.totalCount
this.dataListLoading = false
}).catch(() => {
this.dataListLoading = false
})
},
expandedNodes (data) {
if (data && data > 50) {
this.transition = 0
} else {
this.transition = 0.1
}
},
nodeClick (row, type) {
this.current = 1
if (type === 'group') {
this.queryForm.typeId = row.id
this.queryForm.datasetType = ''
} else if (type === 'type') {
this.queryForm.typeId = ''
this.queryForm.datasetType = row
}
this.getDataList()
},
refreshData (node) {
if (node && node.id === this.queryForm.typeId) {
this.queryForm.typeId = ''
}
this.getDataList()
},
handleSearch () {
this.current = 1
this.queryForm.typeId = ''
// 清除左侧机构树的选中状态
this.$refs.datasetsTypeTree.ztreeObj.cancelSelectedNode()
this.getDataList()
},
// 拖拽修改div宽度
mousedown (e) {
this.resize = document.getElementsByClassName('resize')[0]
this.resize.left = document.getElementById('left-box').getBoundingClientRect().width
this.leftBox = document.getElementsByClassName('left-box')[0]
this.rightBox = document.getElementsByClassName('right-box')[0]
this.startX = e.clientX
},
mousemove (e) {
this.event = e
if (this.resize) {
const boxWidth = document.getElementById('box').getBoundingClientRect().width
this.endX = e.clientX
const offset = document.getElementById('box').getBoundingClientRect().left > 300 ? 0 : 25
const moveLen = this.resize.left + (this.endX - this.startX) + offset
this.leftBox.style.width = moveLen / boxWidth * 100 + '%'
this.rightBox.style.width = ((1 - moveLen / boxWidth) * 100) + '%'
this.isPackUpTree = false
if (moveLen < 100 && this.endX - this.startX < 0) {
this.isPackUpTree = true
this.leftBox.style.width = '0%'
this.rightBox.style.width = '100%'
} else if (moveLen / boxWidth > 0.5) {
this.leftBox.style.width = '50%'
this.rightBox.style.width = '50%'
}
}
},
packUpTree () {
this.$refs.datasetsTypeTree.expandedNodes()
this.isPackUpTree = !this.isPackUpTree
if (!this.isPackUpTree) {
this.leftBox.style.width = '25%'
this.rightBox.style.width = '75%'
} else {
this.leftBox.style.width = '0%'
this.rightBox.style.width = '100%'
}
},
mouseup () {
if (this.resize) {
this.resize = null
if (this.endX < 350 && this.endX - this.startX > 0) {
this.isPackUpTree = false
this.leftBox.style.width = '25%'
this.rightBox.style.width = '75%'
}
}
},
mousemoveOnBox (e) {
this.mousemove(e)
},
mouseupOnBox () {
this.resize = null
if (this.endX < 350 && this.endX - this.startX > 0) {
this.isPackUpTree = false
this.leftBox.style.width = '25%'
this.rightBox.style.width = '75%'
}
this.resize = null
}
}
}
</script>
<style lang="scss" scoped>
@import '../../assets/style/bsTheme.scss';
@import '../../assets/style/zTree/treePackUp.scss';
::v-deep .big-screen-router-view-wrap{
padding-left: 16px !important;
}
.bs-pagination {
padding: 0 !important;
right: 16px !important;
bottom: 16px !important;
position: absolute !important;
::v-deep .el-input__inner {
width: 110px !important;
border:none;
background: var(--bs-el-background-1);
}
}
.bs-container .inner-container .el-form .filter-item {
::v-deep .el-input__inner {
width: 200px;
}
}
::v-deep .left-tab-box {
span {
color: var(--bs-el-text);
}
}
::v-deep .left-tab-box ul li.tab-active {
background-color: var(--bs-el-background-3);
}
::v-deep .left-tab-box ul li:hover {
background-color: var(--bs-el-background-3);
}
.el-dialog {
.bs-container {
// max-height: calc(90vh - 236px) !important;
.el-table {
height: calc(100vh - 390px);
}
::v-deep .ztree {
max-height: calc(90vh - 325px) !important;
}
::v-deep .el-tabs__item.is-active {
border-bottom: none !important;
}
}
}
::v-deep .ztreeNodeMenu {
ul {
background-color: var(--bs-background-1);
}
li:hover {
background-color: var(--bs-el-background-3);
span {
color: var(--bs-el-color-primary);
}
}
span {
color: var(--bs-el-text);
}
.triangle {
background-color: var(--bs-background-1) !important;
}
}
.layout {
width: 100%;
height: 100%;
}
::v-deep .el-table__body-wrapper{
max-height: unset !important;
}
</style>