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.

367 lines
8.3 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.

<!--
* @description: 设置组件关联的公共组件
* @Date: 2023-01-04 14:42:51
* @Author: xing.heng
* @LastEditors: wujian
* @LastEditTime: 2023-06-02 15:35:43
-->
<template>
<div>
<div class="data-setting-data-box">
<div class="lc-field-head">
<div class="lc-field-title">
组件联动
</div>
</div>
<div class="lc-field-body">
<div class="select-item select-item-title">
<span class="input-wrap">目标组件</span>
<span class="input-wrap">操作</span>
</div>
<div
v-for="(field, index) in config.linkage.components"
:key="index"
class="select-item"
:class="{ 'select-item-active': field.componentKey === activeCode }"
@mouseenter="chooseComponent(field)"
>
<div class="input-wrap">
<el-form-item
label-width="0px"
>
<el-select
v-model="field.componentKey"
popper-class="bs-el-select"
class="bs-el-select"
size="mini"
@change="changeComponent(...arguments, index)"
>
<el-option
v-for="item in allComponentsExpectSelf(config.code)"
:key="item.componentKey"
:label="item.name"
:value="item.componentKey"
:disabled="currentLinkComponentKey.includes(item.componentKey)"
/>
</el-select>
</el-form-item>
</div>
<div class="input-wrap">
<div
class="select-line-icon option-add"
@click="setRelation(field)"
>
<el-tooltip
effect="dark"
content="组件联动设置"
placement="top"
>
<i class="el-icon-setting" />
</el-tooltip>
</div>
<div
class="select-line-icon option-delete"
@click="deleteLinkComponents(index)"
>
<i class="el-icon-remove-outline" />
</div>
</div>
</div>
<el-button
v-block
type="primary"
@click="addLinkComponents"
>
新增联动组件
</el-button>
</div>
</div>
<RelationSetting
:setting-visible.sync="settingVisible"
:config-map="configMap"
:source-field-list="sourceFieldList"
:target-field-list="targetFieldList"
@updateConfig="updateConfig"
/>
</div>
</template>
<script>
import RelationSetting from './RelationSetting.vue'
import cloneDeep from 'lodash/cloneDeep'
import { mapState } from 'vuex'
export default {
name: 'ComponentRelation',
components: {
RelationSetting
},
directives: {
block: {
bind (el, binding) {
el.style.width = binding.value || '100%'
}
}
},
props: {
config: {
type: Object,
default: () => {}
},
// 当前组件的联动字段
sourceFieldList: {
type: Array,
default: () => [
// {
// label: '字段1',
// value: 'field1'
// }
]
}
},
data () {
return {
// 关联设置弹窗
settingVisible: false,
cloneDeepConfig: cloneDeep(this.config),
configMap: {},
targetFieldList: [],
activeCode: null
}
},
computed: {
...mapState({
chartList: state => state.bigScreen.pageInfo.chartList
}),
// 当前已经关联的组件key
currentLinkComponentKey () {
return this.config.linkage.components?.map(item => item.componentKey) || []
}
},
mounted () {
},
beforeDestroy () {
},
methods: {
/**
* @description: 获取除自己之外的所有组件
*/
allComponentsExpectSelf (code) {
let layouts = cloneDeep(this.chartList)
const tabComponents = []
layouts?.map((ly) => {
if (ly.type === 'Tabs') {
ly?.tabList?.map(com => {
tabComponents.push(com.chart)
})
}
})
layouts = layouts?.filter(item => item.code !== code && item?.option?.displayOption?.dataAllocation?.enable)
layouts = [...layouts, ...tabComponents]?.map(item => ({
name: item.title,
componentKey: item.code
}))
return layouts
},
/**
* @description: 添加关联组件
*/
addLinkComponents () {
this.config.linkage.components.push({
componentKey: '',
maps: []
})
},
/**
* @description: 删除关联组件
*/
deleteLinkComponents (index) {
this.config.linkage.components.splice(index, 1)
},
/**
* @description: 改变关联组件
*/
changeComponent (componentKey, index) {
this.$set(
this.config.linkage.components,
index,
{
componentKey,
maps: []
}
)
},
/**
* @description: 设置关联弹窗打开
*/
setRelation (configMap) {
this.settingVisible = true
// 如果是tab页内部组件先平铺
let layouts = cloneDeep(this.chartList)
const tabComponents = []
layouts?.map((ly) => {
if (ly.type === 'Tabs') {
ly?.tabList?.map(com => {
tabComponents.push(com.chart)
})
}
})
layouts = layouts?.filter(item => item?.option?.displayOption?.dataAllocation?.enable)
layouts = [...layouts, ...tabComponents]
this.targetFieldList = layouts.find(
item => item.code === configMap.componentKey
)?.inParams?.map(item => ({
label: item.name,
value: item.code
}))
this.configMap = cloneDeep(configMap)
},
/**
* @description: 更新关联配置
*/
updateConfig (configMapConfig) {
const index = this.config.linkage.components?.findIndex(
item => item.componentKey === configMapConfig.componentKey
)
this.$set(
this.config.linkage.components,
index,
configMapConfig
)
},
/**
* @description: 选择组件
*/
chooseComponent (field) {
this.activeCode = field?.componentKey
}
}
}
</script>
<style scoped lang="scss">
::v-deep .el-tabs__nav-scroll {
display: flex;
justify-content: center;
}
::v-deep .el-tabs__nav-wrap::after {
height: 0;
}
::v-deep .el-collapse-item__header {
background: #f2f3f5;
height: 32px;
padding: 0 12px;
}
::v-deep .el-collapse-item__content {
padding-bottom: 0;
}
.lc-field-body {
padding: 12px;
}
::v-deep .el-tabs__nav-scroll {
display: flex;
justify-content: center;
}
::v-deep .el-tabs__nav-wrap::after {
height: 0;
}
.design-tab-warp {
padding: 10px;
}
::v-deep .el-tabs--top {
height: 100%;
}
::v-deep .el-tabs__content {
height: calc(100% - 40px);
overflow-y: auto;
}
.setting-body {
height: 100%;
}
//
.add-filter-box {
position: relative;
.add-filter {
margin-left: 90px;
margin-bottom: 10px;
}
.add-filter-btn {
position: absolute;
top: 0;
}
}
.select-item {
display: flex;
margin-bottom: 8px;
cursor: pointer;
align-items: center;
border: 1px solid #fff;
padding: 4px;
.input-wrap {
flex: 1;
display: flex;
justify-content: center;
margin-right: 2px;
::v-deep .el-form-item {
margin-bottom: 0 !important;
}
.el-input-number--mini {
width: 90px !important;
}
}
.input-wrap_left {
flex: 1;
display: flex;
align-items: center;
justify-content: left;
}
.select-line-icon {
width: 30px;
font-size: 18px;
cursor: pointer;
text-align: center;
}
.option-delete {
color: #f56c6c;
}
}
.select-item-active {
border: 1px solid var(--bs-el-color-primary);
background: var(--bs-el-background-3);
}
//
.data-setting-box{
.data-setting-data-box{
.lc-field-head{
height: 30px;
.lc-field-title{
position: relative;
padding-left: 12px;
line-height: 30px;
height: 30px;
&:after{
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
content: '';
width: 4px;
height: 14px;
background-color: var(--bs-el-color-primary);
}
}
}
}
}
</style>