mirror of
https://github.com/dataease/dataease.git
synced 2025-02-28 07:05:48 +08:00
227 lines
5.9 KiB
Vue
227 lines
5.9 KiB
Vue
![]() |
<template>
|
|||
|
<div class="el-view-select" :class="selectClass">
|
|||
|
<el-select
|
|||
|
ref="select"
|
|||
|
v-model="innerValues"
|
|||
|
v-popover:popover
|
|||
|
:title="labels"
|
|||
|
popper-class="view-select-option"
|
|||
|
style="width: 100%;"
|
|||
|
multiple
|
|||
|
clearable
|
|||
|
@remove-tag="_selectRemoveTag"
|
|||
|
@clear="_selectClearFun"
|
|||
|
@focus="_popoverShowFun"
|
|||
|
>
|
|||
|
<el-option
|
|||
|
v-for="item in selectedViews"
|
|||
|
:key="item.viewId"
|
|||
|
:label="item.title"
|
|||
|
:value="item.viewId"
|
|||
|
/>
|
|||
|
</el-select>
|
|||
|
|
|||
|
<el-popover ref="popover" v-model="visible" :placement="placement" :transition="transition" :popper-class="popperClass" :width="width" trigger="click">
|
|||
|
<el-scrollbar tag="div" wrap-class="el-select-dropdown__wrap" view-class="el-select-dropdown__list" class="is-empty">
|
|||
|
<div :style="{'height': panelHeight + 'px'}">
|
|||
|
<Preview
|
|||
|
v-if="viewLoaded"
|
|||
|
:component-data="componentData"
|
|||
|
:canvas-style-data="canvasStyleData"
|
|||
|
:panel-info="panelInfo"
|
|||
|
:show-position="showPosition"
|
|||
|
/>
|
|||
|
</div>
|
|||
|
</el-scrollbar>
|
|||
|
|
|||
|
</el-popover>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import { on, off } from './dom'
|
|||
|
import Preview from '@/components/canvas/components/Editor/Preview'
|
|||
|
export default {
|
|||
|
name: 'DeViewSelect',
|
|||
|
components: { Preview },
|
|||
|
props: {
|
|||
|
value: {
|
|||
|
type: Array,
|
|||
|
default: () => []
|
|||
|
},
|
|||
|
viewLoaded: {
|
|||
|
type: Boolean,
|
|||
|
default: false
|
|||
|
},
|
|||
|
viewPropData: {
|
|||
|
type: Object,
|
|||
|
default: null
|
|||
|
}
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
labels: [],
|
|||
|
visible: false,
|
|||
|
placement: 'bottom',
|
|||
|
transition: 'el-zoom-in-top',
|
|||
|
width: 500,
|
|||
|
selectClass: 'my-top-class',
|
|||
|
innerValues: [],
|
|||
|
panelHeight: 450,
|
|||
|
showPosition: 'email-task'
|
|||
|
}
|
|||
|
},
|
|||
|
computed: {
|
|||
|
popperClass() {
|
|||
|
const _c = 'el-view-select-popper ' + this.popoverClass
|
|||
|
return this.disabled ? _c + ' disabled ' : _c
|
|||
|
},
|
|||
|
componentData() {
|
|||
|
return this.viewLoaded && this.viewPropData && this.viewPropData.componentData || null
|
|||
|
},
|
|||
|
canvasStyleData() {
|
|||
|
return this.viewLoaded && this.viewPropData && this.viewPropData.canvasStyleData || null
|
|||
|
},
|
|||
|
panelInfo() {
|
|||
|
return this.viewLoaded && this.viewPropData && this.viewPropData.panelInfo || null
|
|||
|
},
|
|||
|
panelId() {
|
|||
|
return this.viewLoaded && this.panelInfo && this.panelInfo.id
|
|||
|
},
|
|||
|
|
|||
|
selectedViews() {
|
|||
|
return this.$store.getters.panelViews[this.panelId]
|
|||
|
}
|
|||
|
},
|
|||
|
watch: {
|
|||
|
value(val, old) {
|
|||
|
this.innerValues = val
|
|||
|
},
|
|||
|
innerValues(val, old) {
|
|||
|
if (val !== old) {
|
|||
|
this.$emit('input', val)
|
|||
|
}
|
|||
|
},
|
|||
|
panelId(val, old) {
|
|||
|
if (val !== old) { this.$store.dispatch('panel/setPanelInfo', this.panelInfo) }
|
|||
|
},
|
|||
|
selectedViews: {
|
|||
|
handler(val) {
|
|||
|
if (!this.viewLoaded) return
|
|||
|
if (!val || !JSON.stringify(val)) {
|
|||
|
this.labels = []
|
|||
|
this.innerValues = []
|
|||
|
return
|
|||
|
}
|
|||
|
const views = JSON.parse(JSON.stringify(val))
|
|||
|
const viewIds = []
|
|||
|
const names = []
|
|||
|
views.forEach(item => {
|
|||
|
viewIds.push(item.viewId)
|
|||
|
names.push(item.title)
|
|||
|
})
|
|||
|
this.innerValues = JSON.parse(JSON.stringify(viewIds))
|
|||
|
this.labels = JSON.parse(JSON.stringify(names))
|
|||
|
},
|
|||
|
deep: true
|
|||
|
}
|
|||
|
},
|
|||
|
mounted() {
|
|||
|
this._updateH()
|
|||
|
this.$nextTick(() => {
|
|||
|
on(document, 'mouseup', this._popoverHideFun)
|
|||
|
})
|
|||
|
},
|
|||
|
beforeDestroy() {
|
|||
|
off(document, 'mouseup', this._popoverHideFun)
|
|||
|
},
|
|||
|
methods: {
|
|||
|
|
|||
|
// 更新宽度
|
|||
|
_updateH() {
|
|||
|
this.$nextTick(() => {
|
|||
|
this.width = this.$refs.select.$el.getBoundingClientRect().width
|
|||
|
this.panelHeight = this.width * 9 / 16
|
|||
|
})
|
|||
|
},
|
|||
|
// 显示弹出框的时候容错,查看是否和el宽度一致
|
|||
|
_popoverShowFun(val) {
|
|||
|
this._updateH()
|
|||
|
this.$emit('onFoucs')
|
|||
|
},
|
|||
|
// 判断是否隐藏弹出框
|
|||
|
_popoverHideFun(e) {
|
|||
|
const path = this._getEventPath(e)
|
|||
|
const isInside = path.some(list => {
|
|||
|
// 鼠标在弹出框内部,阻止隐藏弹出框
|
|||
|
return list.className && typeof list.className === 'string' && list.className.indexOf('el-view-select') !== -1
|
|||
|
})
|
|||
|
if (!isInside) {
|
|||
|
this.visible = false
|
|||
|
}
|
|||
|
},
|
|||
|
// 获取MouseEvent.path 针对浏览器兼容性兼容ie11,edge,chrome,firefox,safari
|
|||
|
_getEventPath(evt) {
|
|||
|
const path = (evt.composedPath && evt.composedPath()) || evt.path
|
|||
|
const target = evt.target
|
|||
|
if (path != null) {
|
|||
|
return path.indexOf(window) < 0 ? path.concat(window) : path
|
|||
|
}
|
|||
|
if (target === window) {
|
|||
|
return [window]
|
|||
|
}
|
|||
|
function getParents(node, memo) {
|
|||
|
memo = memo || []
|
|||
|
const parentNode = node.parentNode
|
|||
|
if (!parentNode) {
|
|||
|
return memo
|
|||
|
} else {
|
|||
|
return getParents(parentNode, memo.concat(parentNode))
|
|||
|
}
|
|||
|
}
|
|||
|
return [target].concat(getParents(target), window)
|
|||
|
},
|
|||
|
_selectRemoveTag(viewId) {
|
|||
|
this.selectedViews.forEach(item => {
|
|||
|
if (item.viewId === viewId) {
|
|||
|
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': item.viewId })
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
_selectClearFun() {
|
|||
|
const views = JSON.parse(JSON.stringify(this.selectedViews))
|
|||
|
views.forEach(item => {
|
|||
|
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': item.viewId })
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss" scoped>
|
|||
|
.el-view-select .view-select-option {
|
|||
|
display: none !important;
|
|||
|
}
|
|||
|
|
|||
|
.el-view-select-popper {
|
|||
|
max-height: 800px;
|
|||
|
overflow: auto;
|
|||
|
}
|
|||
|
.el-view-select-popper.disabled {
|
|||
|
display: none !important;
|
|||
|
}
|
|||
|
.el-view-select-popper .el-button--small {
|
|||
|
width: 25px !important;
|
|||
|
min-width: 25px !important;
|
|||
|
}
|
|||
|
|
|||
|
.el-view-select-popper[x-placement^='bottom'] {
|
|||
|
margin-top: 5px;
|
|||
|
}
|
|||
|
|
|||
|
.my-top-class {
|
|||
|
width: 100%;
|
|||
|
}
|
|||
|
</style>
|