forked from github/dataease
feat(系统管理): 定时报告增加视图选择器前端组件
This commit is contained in:
parent
87907beff3
commit
a1f4e93f72
32
frontend/src/components/DeViewSelect/dom.js
Normal file
32
frontend/src/components/DeViewSelect/dom.js
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
export const on = (function() {
|
||||
if (document.addEventListener) {
|
||||
return function(element, event, handler) {
|
||||
if (element && event && handler) {
|
||||
element.addEventListener(event, handler, false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return function(element, event, handler) {
|
||||
if (element && event && handler) {
|
||||
element.attachEvent('on' + event, handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
export const off = (function() {
|
||||
if (document.removeEventListener) {
|
||||
return function(element, event, handler) {
|
||||
if (element && event) {
|
||||
element.removeEventListener(event, handler, false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return function(element, event, handler) {
|
||||
if (element && event) {
|
||||
element.detachEvent('on' + event, handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
226
frontend/src/components/DeViewSelect/index.vue
Normal file
226
frontend/src/components/DeViewSelect/index.vue
Normal file
@ -0,0 +1,226 @@
|
||||
<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>
|
@ -149,7 +149,7 @@ export default {
|
||||
return style
|
||||
},
|
||||
componentActiveFlag() {
|
||||
return (this.curComponent && this.config === this.curComponent) && !this.previewVisible && !this.showPosition.includes('multiplexing')
|
||||
return (this.curComponent && this.config === this.curComponent) && !this.previewVisible && !this.showPosition.includes('multiplexing') && !this.showPosition.includes('email-task')
|
||||
},
|
||||
curGap() {
|
||||
return (this.canvasStyleData.panel.gap === 'yes' && this.config.auxiliaryMatrix) ? this.componentGap : 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="bar-main">
|
||||
<div v-if="!positionCheck('multiplexing')">
|
||||
<div v-if="!positionCheck('multiplexing') && !positionCheck('email-task')">
|
||||
<span v-if="isEdit" :title="$t('panel.edit')">
|
||||
<i class="icon iconfont icon-edit" @click.stop="edit" />
|
||||
</span>
|
||||
@ -14,6 +14,9 @@
|
||||
<div v-if="positionCheck('multiplexing')" style="margin-right: -1px;width: 18px;z-index: 5">
|
||||
<el-checkbox v-model="multiplexingCheckModel" size="medium" @change="multiplexingCheck" />
|
||||
</div>
|
||||
<div v-if="positionCheck('email-task')" style="margin-right: -1px;width: 18px;z-index: 5">
|
||||
<el-checkbox v-model="isTaskChecked" size="medium" @change="emailTaskCheck" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -40,6 +43,14 @@ export default {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'NotProvided'
|
||||
},
|
||||
panelId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
chartTitle: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -51,7 +62,8 @@ export default {
|
||||
'view',
|
||||
'custom'
|
||||
],
|
||||
timer: null
|
||||
timer: null,
|
||||
isTaskChecked: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -67,14 +79,29 @@ export default {
|
||||
'linkageSettingStatus',
|
||||
'componentData',
|
||||
'canvasStyleData',
|
||||
'componentGap'
|
||||
])
|
||||
'componentGap',
|
||||
'panelViews'
|
||||
]),
|
||||
|
||||
taskChecked() {
|
||||
const panelId = this.panelId
|
||||
return !!this.panelViews && !!this.panelViews[panelId] && !!this.panelViews[panelId].some(view => view.viewId === this.viewId)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
taskChecked(val) {
|
||||
this.isTaskChecked = val
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.showPosition === 'multiplexing-view') {
|
||||
this.multiplexingCheckModel = true
|
||||
this.multiplexingCheck(this.multiplexingCheckModel)
|
||||
}
|
||||
if (this.showPosition === 'email-task') {
|
||||
this.isTaskChecked = !!this.taskChecked
|
||||
// this.emailTaskCheck(this.isTaskChecked)
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
},
|
||||
@ -104,6 +131,13 @@ export default {
|
||||
// remove
|
||||
this.$store.commit('removeCurMultiplexingComponentWithId', this.viewId)
|
||||
}
|
||||
},
|
||||
emailTaskCheck(val) {
|
||||
if (val) {
|
||||
this.$store.dispatch('task/addView', { 'panelId': this.panelId, 'viewId': this.viewId, 'title': this.chartTitle })
|
||||
} else {
|
||||
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': this.viewId })
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
v-if="editBarViewShowFlag"
|
||||
:element="element"
|
||||
:show-position="showPosition"
|
||||
:panel-id="panelInfo.id"
|
||||
:chart-title="chart.title || chart.name"
|
||||
:is-edit="isEdit"
|
||||
:view-id="element.propValue.viewId"
|
||||
@showViewDetails="openChartDetailsDialog"
|
||||
@ -234,7 +236,7 @@ export default {
|
||||
}
|
||||
},
|
||||
editBarViewShowFlag() {
|
||||
return (this.active && this.inTab && !this.mobileLayoutStatus) || this.showPosition.includes('multiplexing')
|
||||
return (this.active && this.inTab && !this.mobileLayoutStatus) || this.showPosition.includes('multiplexing') || this.showPosition.includes('email-task')
|
||||
},
|
||||
charViewShowFlag() {
|
||||
return this.httpRequest.status && this.chart.type && !this.chart.type.includes('table') && !this.chart.type.includes('text') && this.chart.type !== 'label' && this.renderComponent() === 'echarts'
|
||||
|
@ -30,6 +30,7 @@ const getters = {
|
||||
uiInfo: state => state.user.uiInfo,
|
||||
conditions: state => state.conditions.conditions,
|
||||
msgTypes: state => state.msg.msgTypes,
|
||||
geoMap: state => state.map.geoMap
|
||||
geoMap: state => state.map.geoMap,
|
||||
panelViews: state => state.task.panelViews
|
||||
}
|
||||
export default getters
|
||||
|
@ -21,6 +21,7 @@ import event from '@/components/canvas/store/event'
|
||||
import layer from '@/components/canvas/store/layer'
|
||||
import snapshot from '@/components/canvas/store/snapshot'
|
||||
import lock from '@/components/canvas/store/lock'
|
||||
import task from './modules/task'
|
||||
import { valueValid, formatCondition } from '@/utils/conditionUtil'
|
||||
import { Condition } from '@/components/widget/bean/Condition'
|
||||
|
||||
@ -44,6 +45,7 @@ const data = {
|
||||
...layer.state,
|
||||
...snapshot.state,
|
||||
...lock.state,
|
||||
...task.state,
|
||||
// 编辑器模式 edit preview
|
||||
editMode: 'edit',
|
||||
// 当前页面全局数据 包括扩展公共样式 公共的仪表板样式,用来实时响应样式的变化
|
||||
@ -696,7 +698,8 @@ const data = {
|
||||
application,
|
||||
lic,
|
||||
msg,
|
||||
map
|
||||
map,
|
||||
task
|
||||
},
|
||||
getters
|
||||
}
|
||||
|
49
frontend/src/store/modules/task.js
Normal file
49
frontend/src/store/modules/task.js
Normal file
@ -0,0 +1,49 @@
|
||||
import Vue from 'vue'
|
||||
const state = {
|
||||
panelViews: {}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
|
||||
ADD_VIEW: (state, { panelId, viewId, title }) => {
|
||||
if (!state.panelViews[panelId]) {
|
||||
Vue.set(state.panelViews, panelId, [])
|
||||
}
|
||||
const views = state.panelViews[panelId]
|
||||
if (views.some(item => item.viewId === viewId)) {
|
||||
return
|
||||
}
|
||||
views.push({ viewId, title })
|
||||
state.panelViews[panelId] = views
|
||||
},
|
||||
|
||||
DEL_VIEW: (state, { panelId, viewId }) => {
|
||||
const views = state.panelViews[panelId]
|
||||
if (!views || !views.length) return
|
||||
let len = views.length
|
||||
while (len--) {
|
||||
const item = views[len]
|
||||
if (viewId === item.viewId) {
|
||||
views.splice(len, 1)
|
||||
}
|
||||
}
|
||||
state.panelViews[panelId] = views
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
addView({ commit }, data) {
|
||||
commit('ADD_VIEW', data)
|
||||
},
|
||||
delView({ commit }, data) {
|
||||
commit('DEL_VIEW', data)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
@ -833,3 +833,6 @@ div:focus {
|
||||
.fu-operator-component__label {
|
||||
width: 100px !important;
|
||||
}
|
||||
.view-select-option {
|
||||
display: none !important;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user