初始化

This commit is contained in:
砂糖
2025-11-08 10:38:36 +08:00
commit 3beeec7296
1626 changed files with 198488 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
/** * @Description: 渐变色配置 * @author liu.shiyi * @date 2023/4/13 16:01 */
<template>
<div class="bs-gradual-wrap">
<el-color-picker
v-model="startColor"
class="bs-el-color-picker"
show-alpha
popper-class="bs-el-color-picker"
/>
<div class="el-icon-right" />
<el-color-picker
v-model="endColor"
class="bs-el-color-picker"
show-alpha
popper-class="bs-el-color-picker"
/>
</div>
</template>
<script>
export default {
name: 'GradualSetting',
model: {
prop: 'colors',
event: 'change'
},
props: {
colors: {
type: Array,
default: ()=>([])
}
},
data () {
return {
startColor: '', // 初始颜色
endColor: '', // 终止颜色
}
},
computed: {
},
watch: {
colors(){
this.init()
},
startColor () {
this.colorChange()
},
endColor () {
this.colorChange()
}
},
mounted () {
this.init()
},
methods: {
init () {
this.startColor = this.colors[0]
this.endColor = this.colors[1]
},
colorChange (val) {
const colorsValue = (this.startColor||this.endColor)?[this.startColor,this.endColor]:[]
this.$emit('change', colorsValue)
}
}
}
</script>
<style lang="scss" scoped>
.bs-gradual-wrap{
width: 100%;
display: flex;
align-items: center;
.el-icon-right{
width: 40px;
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,426 @@
<template>
<div>
<el-form-item
:label-width="labelWidth"
label="边框"
>
<el-input
v-model="title"
clearable
read-only
placeholder="请选择边框"
@focus="init"
>
<template slot="append">
<el-button
size="small"
type="primary"
@click="init"
>
选择
</el-button>
</template>
</el-input>
<BorderSelect
v-model="config.type"
ref="BorderSelect"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="上边距"
>
<el-input-number
v-model="config.padding[0]"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="右边距"
>
<el-input-number
v-model="config.padding[1]"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="下边距"
>
<el-input-number
v-model="config.padding[2]"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="左边距"
>
<el-input-number
v-model="config.padding[3]"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<div v-if="config.type">
<el-form-item
:label-width="labelWidth"
label="是否显示标题"
v-if="config.type!='GcBorder16'"
>
<el-switch
v-model="config.isTitle"
class="bs-el-switch"
:active-value="true"
:inactive-value="false"
/>
</el-form-item>
<el-form-item
v-if="config.isTitle&&config.type!='GcBorder11'"
:label-width="labelWidth"
label="标题高度"
>
<el-input-number
v-model="config.titleHeight"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
v-if="config.isTitle&&config.type!='GcBorder11'"
:label-width="labelWidth"
label="标题字体大小"
>
<el-input-number
v-model="config.fontSize"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
v-if="config.isTitle&&config.type!='GcBorder11'"
:label-width="labelWidth"
label="标题颜色"
>
<el-color-picker
v-model="config.fontColor"
popper-class="bs-el-color-picker"
class="bs-el-color-picker"
show-alpha
/>
</el-form-item>
<!-- <el-form-item
v-if="config.type=='GcBorder15'"
:label-width="labelWidth"
label="外侧边框线宽度"
>
<el-input-number
v-model="borderWidth"
class="bs-el-input-number"
:step="1"
:min="0"
:max="100000"
/>
</el-form-item> -->
<div
v-for="(setting, settingIndex) in list.setting"
:key="settingIndex+1"
>
<el-form-item
:label="setting.type=== 'padding' ? '' : setting.label"
:label-width="labelWidth"
>
<el-input
v-if="setting.type === 'input'"
v-model="config[setting.field]"
:placeholder="`请输入${setting.label}`"
clearable
/>
<el-input
v-model="config[setting.field]"
v-else-if="setting.type === 'background'"
clearable
placeholder="选择或输入链接"
>
<template slot="append">
<el-button
size="small"
type="primary"
@click="initCard"
>
选择
</el-button>
</template>
</el-input>
<el-button
v-else-if="setting.type === 'move'"
type="primary"
@click="initMove(config.imgUrl)"
>
图形切割
</el-button>
<el-select
v-else-if="setting.type === 'select'"
v-model="config[setting.field]"
popper-class="bs-el-select"
class="bs-el-select"
:placeholder="`请选择${setting.label}`"
:multiple="setting.multiple"
clearable
>
<el-option
v-for="(opt, optIndex) in setting.options"
:key="optIndex"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<template v-else-if="setting.type === 'colorSelect'">
<color-select
v-model="colorScheme"
@update="updateColorScheme"
/>
<div
style="
display: flex;
align-items: center;
flex-wrap: wrap;
"
class="color-picker-box"
>
<el-color-picker
v-for="(colorItem, colorItemIndex) in colors"
:key="colorItemIndex"
v-model="setting.value[colorItemIndex]"
popper-class="bs-el-color-picker"
show-alpha
class="start-color"
/>
<span
class="el-icon-circle-plus-outline"
style="color: #007aff; font-size: 20px"
@click="addColor"
/>
<span
v-if="colors.length"
class="el-icon-remove-outline"
style="color: #ea0b30; font-size: 20px"
@click="delColor()"
/>
</div>
</template>
<el-color-picker
v-else-if="setting.type === 'colorPicker'"
v-model="config[setting.field]"
popper-class="bs-el-color-picker"
class="bs-el-color-picker"
show-alpha
/>
<BorderColorSetting
v-else-if="setting.type === 'gradual'"
v-model="config[setting.field]"
/>
<el-input-number
v-else-if="setting.type === 'inputNumber'"
v-model="config[setting.field]"
class="bs-el-input-number"
:step="setting.step || 1"
:min="setting.min || 0"
:max="setting.max || 100000"
/>
<el-radio-group
v-else-if="setting.type === 'radio'"
v-model="config[setting.field]"
class="bs-el-radio-group"
>
<template v-for="(opt, optIndex) in setting.options">
<el-radio-button
:key="optIndex"
:label="opt.value"
>
{{ opt.label }}
</el-radio-button>
</template>
</el-radio-group>
<el-switch
v-else-if="setting.type === 'switch'"
v-model="config[setting.field]"
class="bs-el-switch"
:active-value="setting.active"
:inactive-value="setting.inactive"
/>
<el-slider
v-else-if="setting.type === 'slider'"
v-model="config[setting.field]"
:min="0"
:max="1"
:step="0.01"
/>
<PaddingSetting
v-else-if="setting.type === 'padding'"
v-model="config[setting.field]"
/>
</el-form-item>
</div>
<SourceDialog ref="SourceDialog" @getImg='changeImg' />
<MoveDialog @getArray='changeBorder' ref="MoveDialog"/>
</div>
</div>
</template>
<script>
import _ from 'lodash'
import plotList from 'data-room-ui/BorderComponents/settingList.js'
import BorderColorSetting from 'data-room-ui/BigScreenDesign/RightSetting/BorderColorSetting/index.vue'
import ColorSelect from 'data-room-ui/ColorMultipleSelect/index.vue'
import BorderSelect from 'data-room-ui/BorderSelect/index.vue'
import SourceDialog from '../SourceDialog/index.vue'
import MoveDialog from './MoveDialog/index.vue'
export default {
name: '',
components: {
BorderSelect,
ColorSelect,
BorderColorSetting,
SourceDialog,
MoveDialog
},
props: {
bigTitle:{
type: String,
default: ''
},
config: {
type: Object,
default: () => ({
type: '',
titleHeight: 0,
fontSize: 0,
h: 0,
})
},
labelWidth: {
type: String,
default: '100px'
}
},
watch:{
// borderWidth:{
// handler (val) {
// this.config.borderWidth=val
// }
// },
'config.type':{
handler (val) {
this.config.isTitle=this.list.isTitle
plotList[Symbol.iterator]=function*(){
let keys=Object.keys(plotList)
for(let k of keys){
yield [k,plotList[k]]
}
}
for(let [key,value] of plotList){
if(value.padding&&val==value.type){
this.config.padding=[...value.padding]
}
if(value.type==this.config.type){
value.setting.forEach((item)=>{
this.$set(this.config,item.field,item.value)
})
}
}
}
},
},
computed:{
title:{
set(){
this.config.type=''
this.config.padding=[16,16,16,16]
},
get(){
plotList[Symbol.iterator]=function*(){
let keys=Object.keys(plotList)
for(let k of keys){
yield [k,plotList[k]]
}
}
let name
for(let [key,value] of plotList){
if(value.type==this.config.type){
name=value.name
}
}
return name
}
},
list(){
plotList[Symbol.iterator]=function*(){
let keys=Object.keys(plotList)
for(let k of keys){
yield [k,plotList[k]]
}
}
let obj={}
for(let [key,value] of plotList){
if(value.type==this.config.type){
obj={setting:value.setting,isTitle:value.isTitle}
}
}
return obj
}
},
data () {
return {
// borderWidth:0
}
},
mounted () {
// if(this.config.borderWidth){
// this.borderWidth=this.config.borderWidth
// }
},
methods: {
changeBorder(val){
this.$set(this.config,'borderArray',val)
},
changeImg(val){
this.$set(this.config,'imgUrl',val.url)
},
init(){
this.$refs.BorderSelect.init()
},
initCard(){
this.$refs.SourceDialog.init()
},
initMove(val){
this.$refs.MoveDialog.init(val,this.config.borderArray)
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-color-picker__trigger {
border-color: var(--bs-el-border);
}
::v-deep .el-input--suffix .el-input__inner{
padding-right: 10px !important;
}
.color-picker-box{
::v-deep .el-color-picker__trigger {
width: 27px!important;
}
}
</style>

View File

@@ -0,0 +1,292 @@
<template>
<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.customize.bindComponents"
:key="index"
class="select-item"
:class="{ 'select-item-active': field.name === activeCode }"
@mouseenter="chooseComponent(field)"
>
<div class="input-wrap">
<el-form-item label-width="0px">
<el-select
v-model="field.name"
popper-class="bs-el-select"
class="bs-el-select"
size="mini"
clearable
@change="changeComponent(...arguments, index)"
>
<el-option
v-for="item in allComponentsExpectSelf(config.code)"
:key="item.name"
:label="item.comment"
:value="item.name"
:disabled="currentLinkComponentKey.includes(item.name)"
/>
</el-select>
</el-form-item>
</div>
<div class="input-wrap">
<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="addBindComponents"
>
新增绑定组件
</el-button>
</div>
</div>
</template>
<script>
// import _ from 'lodash'
import cloneDeep from 'lodash/cloneDeep'
import { mapState } from 'vuex'
export default {
name: 'ComponentBinding',
directives: {
block: {
bind (el, binding) {
el.style.width = binding.value || '100%'
}
}
},
props: {
config: {
type: Object,
default: () => {}
},
// 当前组件的联动字段
sourceFieldList: {
type: Array,
default: () => []
}
},
data () {
return {
// 关联设置弹窗
settingVisible: false,
configMap: {},
targetFieldList: [],
activeCode: null
}
},
computed: {
...mapState({
chartList: state => state.bigScreen.pageInfo.chartList
}),
// 当前已经关联的组件key
currentLinkComponentKey () {
return this.config.dataSource.dimensionFieldList?.map(item => item) || []
}
},
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 && !['Tabs', 'titles', 'currentTime', 'timeCountDown', 'iframeChart', 'linkChart', 'carousel', 'themeSwitcher', 'themeSelect', 'customHtml'].includes(item.type))
layouts = [...layouts, ...tabComponents]?.map(item => ({
name: item.code,
comment: item.title
}))
return layouts
},
/**
* @description: 添加关联组件
*/
addBindComponents () {
this.config.customize.bindComponents.push({
name: '',
comment: ''
})
},
/**
* @description: 删除关联组件
*/
deleteLinkComponents (index) {
this.config.customize.bindComponents.splice(index, 1)
},
/**
* @description: 改变关联组件
*/
changeComponent (data, index) {
this.$set(
this.config.dataSource.dimensionFieldList,
index,
data
)
this.$set(
this.config.customize.bindComponents,
index,
{
name: this.config.customize.bindComponents[index].name,
comment: this.allComponentsExpectSelf(this.config.code).find(item => item.name === data).comment
}
)
},
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>

View File

@@ -0,0 +1,201 @@
<!--
* @description: 设置联动的弹窗
* @Date: 2023-01-04 14:57:06
* @Author: xing.heng
* @LastEditors: wujian
* @LastEditTime: 2023-05-23 15:46:03
-->
<template>
<el-dialog
title="组件联动设置"
:visible.sync="settingVisible"
:close-on-click-modal="false"
:before-close="handleClose"
width="800px"
append-to-body
class="bs-dialog-wrap bs-el-dialog"
>
<el-form
ref="form"
label-width="100px"
class="bs-el-form"
>
<el-table
:data="configMapConfig.maps"
class="bs-table bs-el-table"
>
<el-empty />
<el-table-column
label="当前组件映射参数"
align="center"
>
<template #default="scope">
<el-select
v-model="configMapConfig.maps[scope.$index].sourceField"
popper-class="bs-el-select"
class="bs-el-select"
>
<el-option
v-for="sourceField in sourceFieldList"
:key="sourceField.value"
:label="sourceField.label"
:value="sourceField.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column
label="映射规则"
align="center"
>
<span>赋值给</span>
</el-table-column>
<el-table-column
label="目标组件接收参数"
align="center"
>
<template #default="scope">
<el-select
v-model="configMapConfig.maps[scope.$index].targetField"
popper-class="bs-el-select"
class="bs-el-select"
>
<el-option
v-for="targetField in targetFieldList"
:key="targetField.value"
:label="targetField.label"
:value="targetField.value"
:disabled="choosedTargetFields.includes(targetField.value)"
/>
</el-select>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
width="100px"
>
<template slot-scope="scope">
<el-button
type="text"
size="small"
@click="handleDelete(scope.$index)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-button
v-block
type="primary"
@click="addRelatedField"
>
新增联动字段
</el-button>
<div
slot="footer"
class="dialog-footer"
>
<el-button
class="bs-el-button-default"
@click="handleClose"
>
取消
</el-button>
<el-button
type="primary"
@click="updateConfig"
>
确定
</el-button>
</div>
</el-dialog>
</template>
<script>
import { operatorList } from 'data-room-ui/js/dict/chartDict'
export default {
name: 'RalationSetting',
components: {
},
directives: {
block: {
bind (el, binding) {
el.style.width = binding.value || '100%'
el.style.margin = '10px auto'
}
}
},
props: {
settingVisible: {
type: Boolean,
default: false
},
configMap: {
type: Object,
default: () => ({})
},
sourceFieldList: {
type: Array,
default: () => []
},
targetFieldList: {
type: Array,
default: () => []
}
},
data () {
return {
operatorList
}
},
computed: {
configMapConfig: {
get () {
return this.configMap || {
componentKey: '',
maps: []
}
},
set () { }
},
choosedTargetFields () {
return this.configMapConfig.maps.map(item => item.targetField)
}
},
mounted () { },
methods: {
/**
* @description: 关闭弹窗
*/
handleClose () {
this.$emit('update:settingVisible')
},
/**
* @description: 更新配置
*/
updateConfig () {
this.$emit('updateConfig', this.configMapConfig)
this.handleClose()
},
/**
* @description: 新增关联字段
*/
addRelatedField () {
this.configMapConfig.maps.push({
targetField: '',
sourceField: '',
queryRule: '='
})
},
handleDelete (index) {
this.configMapConfig.maps.splice(index, 1)
}
}
}
</script>
<style lang="scss" scoped>
@import '../../../assets/style/bsTheme.scss';
</style>

View File

@@ -0,0 +1,366 @@
<!--
* @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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,342 @@
<template>
<div class="bs-setting-wrap">
<el-form
ref="form"
:model="config"
:rules="customRules"
label-width="120px"
label-position="left"
class="setting-body bs-el-form"
>
<SettingTitle>基础</SettingTitle>
<div class="lc-field-body">
<el-form-item
label="标题"
label-width="120px"
>
<el-input
v-model="config.title"
placeholder="请输入标题"
clearable
/>
</el-form-item>
</div>
<SettingTitle>边框</SettingTitle>
<div class="lc-field-body">
<BorderSetting
v-if="config.border"
label-width="120px"
:config="config.border"
:bigTitle='config.title'
/>
</div>
<SettingTitle>位置</SettingTitle>
<div class="lc-field-body">
<PosWhSetting
label-width="120px"
:config="config"
/>
</div>
<SettingTitle>旋转</SettingTitle>
<div class="lc-field-body">
<RotateSetting
:config="config"
/>
</div>
<template v-for="group in groupList">
<div :key="group.groupName">
<SettingTitle> {{ group.groupName | filterGroupName }}</SettingTitle>
<div class="lc-field-body">
<div
v-for="(setting, settingIndex) in group.list"
:key="settingIndex+1"
>
<el-form-item
:label="setting.type=== 'padding' ? '' : setting.label"
:label-width="setting.type=== 'padding' ? '0px' :'120px'"
>
<el-input
v-if="setting.type === 'input'"
v-model="setting.value"
:placeholder="`请输入${setting.label}`"
clearable
/>
<el-select
v-else-if="setting.type === 'select'"
v-model="setting.value"
popper-class="bs-el-select"
class="bs-el-select"
:placeholder="`请选择${setting.label}`"
:multiple="setting.multiple"
clearable
>
<el-option
v-for="(opt, optIndex) in setting.options"
:key="optIndex"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<template v-else-if="setting.type === 'colorSelect'">
<color-select
v-model="setting.value"
@update="updateColorScheme"
/>
<div
style="
display: flex;
align-items: center;
flex-wrap: wrap;
"
class="color-picker-box"
>
<el-color-picker
v-for="(colorItem, colorItemIndex) in colors"
:key="colorItemIndex"
v-model="setting.value[colorItemIndex]"
popper-class="bs-el-color-picker"
show-alpha
class="start-color"
/>
<span
class="el-icon-circle-plus-outline"
style="color: #007aff; font-size: 20px"
@click="addColor"
/>
<span
v-if="colors.length"
class="el-icon-remove-outline"
style="color: #ea0b30; font-size: 20px"
@click="delColor()"
/>
</div>
</template>
<el-color-picker
v-else-if="setting.type === 'colorPicker'"
v-model="setting.value"
popper-class="bs-el-color-picker"
class="bs-el-color-picker"
show-alpha
/>
<el-input-number
v-else-if="setting.type === 'inputNumber'"
v-model="setting.value"
class="bs-el-input-number"
:step="setting.step || 1"
:min="setting.min || 0"
:max="setting.max || 100000"
/>
<el-radio-group
v-else-if="setting.type === 'radio'"
v-model="setting.value"
class="bs-el-radio-group"
>
<template v-for="(opt, optIndex) in setting.options">
<el-radio-button
:key="optIndex"
:label="opt.value"
>
{{ opt.label }}
</el-radio-button>
</template>
</el-radio-group>
<el-switch
v-else-if="setting.type === 'switch'"
v-model="setting.value"
class="bs-el-switch"
:active-value="setting.active"
:inactive-value="setting.inactive"
/>
<el-slider
v-else-if="setting.type === 'slider'"
v-model="setting.value"
:min="0"
:max="1"
:step="0.01"
/>
<PaddingSetting
v-else-if="setting.type === 'padding'"
v-model="setting.value"
/>
</el-form-item>
</div>
</div>
</div>
</template>
<!-- </div> -->
</el-form>
</div>
</template>
<script>
import BorderSetting from 'data-room-ui/BigScreenDesign/RightSetting/BorderSetting.vue'
import SettingTitle from 'data-room-ui/SettingTitle/index.vue'
import { chartSettingMixins } from 'data-room-ui/js/mixins/chartSettingMixins'
import ColorSelect from 'data-room-ui/ColorMultipleSelect/index.vue'
// import ColorPicker from 'data-room-ui/ColorPicker/index.vue'
import PaddingSetting from 'data-room-ui/BigScreenDesign/RightSetting/PaddingSetting/index.vue'
import PosWhSetting from 'data-room-ui/BigScreenDesign/RightSetting/PosWhSetting.vue'
import RotateSetting from 'data-room-ui/BigScreenDesign/RightSetting/RotateSetting.vue'
export default {
name: 'EchartsCustomSetting',
components: {
ColorSelect,
// ColorPicker,
PaddingSetting,
PosWhSetting,
BorderSetting,
SettingTitle,
RotateSetting
},
mixins: [chartSettingMixins],
data () {
return {
groupList: []
}
},
filters: {
filterGroupName (val) {
const settingGroup = {
basic: '基础',
position: '位置',
graph: '图表',
rotate: '旋转',
grid: '网格线',
legend: '图例',
xAxis: 'X轴',
yAxis: 'Y轴',
padding: '边距',
other: '其他'
}
return settingGroup[val]
}
},
computed: {
config: {
get () {
return this.$store.state.bigScreen.activeItemConfig
},
set (val) {
this.$store.commit('bigScreen/changeActiveItemConfig', val)
}
},
appCode: {
get () {
return this.$store.state.bigScreen.pageInfo.appCode
}
},
pageCode () {
return this.$route.query.code
}
},
watch: {
groupList: {
// 1、原数组2、修改后的数组只包含custom3、合并的时候xy的配置必须放在最前面
handler (val) {
const setList = [].concat(...val.map(item => item.list))
const newSetList = [...this.config.setting, ...setList]
let newArr = [] // 存新数组
const hash = {}
newArr = newSetList.reduce(function (acc, cru, index) {
if (!hash[cru.field]) {
hash[cru.field] = { index: index }
acc.push(cru)
} else {
acc.splice(hash[cru.field].index, 1, cru)
}
return acc
}, [])
this.$store.commit('bigScreen/changeActiveItemConfig', { ...this.config, setting: newArr })
},
deep: true
}
},
mounted () {
this.init()
const groupNameList = []
this.config.setting.filter(
(item) => item.tabName === 'custom'
).forEach(item => {
if (item.tabName === 'custom' && item.groupName) {
if (!groupNameList.includes(item.groupName)) {
groupNameList.push(item.groupName)
this.groupList.push({
groupName: item.groupName,
list: [item]
})
} else {
this.groupList.find(group => group.groupName === item.groupName).list.push(item)
}
} else {
if (this.groupList.find(group => group.groupName === 'other')) {
this.groupList.find(group => group.groupName === 'other').list.push(item)
} else {
this.groupList.push({
groupName: 'other',
list: [item]
})
}
}
})
for (let i = 0; i < this.groupList.length; i++) {
if (this.groupList[i].groupName === 'other') {
const otherObject = this.groupList.splice(i, 1)[0]
this.groupList.push(otherObject)
break
}
}
},
methods: {
init () {
this.config = this.$store.state.bigScreen.activeItemConfig
}
}
}
</script>
<style lang="scss" scoped>
@import '../../assets/style/settingWrap.scss';
@import '../../assets/style/bsTheme.scss';
// 筛选条件的按钮样式
.add-filter-box {
position: relative;
.add-filter {
margin-left: 90px;
margin-bottom: 10px;
}
.add-filter-btn {
position: absolute;
top: 0;
}
}
.lc-field-body {
padding:12px 16px;
}
.el-form-item{
margin-bottom: 6px !important;
}
.lc-field-title {
position: relative;
padding-left: 12px;
line-height: 30px;
height: 30px;
margin-bottom: 12px;
&:after {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
content: '';
width: 4px;
height: 14px;
background-color: var(--bs-el-color-primary);
}
}
::v-deep .el-color-picker__trigger {
border-color: var(--bs-el-border);
}
.color-picker-box{
::v-deep .el-color-picker__trigger {
width: 27px!important;
}
}
</style>

View File

@@ -0,0 +1,102 @@
<!--
* @Descripttion:
* @Author: liu.shiyi
* @Date: 2023-03-14 10:20:54
* @LastEditTime: 2023-05-23 15:14:47
-->
<template>
<el-select
ref="dragSelect"
v-model="selectVal"
v-bind="$attrs"
class="drag-select"
v-on="$listeners"
>
<slot />
</el-select>
</template>
<script>
import { EventBus } from 'data-room-ui/js/utils/eventBus'
import Sortable from 'sortablejs'
export default {
name: 'DragSelect',
props: {
value: {
type: [Array, String],
required: true
}
},
computed: {
selectVal: {
get () {
if (Array.isArray(this.value)) {
return [...this.value]
} else {
return this.value
}
},
set (val) {
if (Array.isArray(val)) {
this.$emit('input', [...val])
} else {
this.$emit('input', val)
}
}
}
},
watch: {
// 监听数组变化根据上次的数据的值判断这次拖拽后数据是否变化如果数据位置发生变化则出发emit事件
selectVal: {
handler (newVal, oldVal) {
if (Array.isArray(newVal) && Array.isArray(oldVal)) {
if ((newVal.length === oldVal.length) && (JSON.stringify(oldVal) !== JSON.stringify(newVal))) {
// 告诉右侧的数据配置面板选择器内的选项顺序发生变化修改config的数据顺序
this.$emit('valuePositionChange', newVal)
}
}
}
}
},
created () {
},
mounted () {
this.setSort()
},
methods: {
setSort () {
const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
if (el) {
this.sortable = Sortable.create(el, {
animation: 350,
ghostClass: 'sortable-ghost',
setData: function (dataTransfer) {
dataTransfer.setData('Text', '')
},
onEnd: (evt) => {
const targetRow = this.value.splice(evt.oldIndex, 1)[0]
this.value.splice(evt.newIndex, 0, targetRow)
}
})
}
}
}
}
</script>
<style lang="scss" scoped>
.drag-select {
::v-deep {
.sortable-ghost {
opacity: 0.8;
color: #fff !important;
background:var(--bs-el-color-primary) !important;
}
.el-tag {
cursor: move;
}
}
}
</style>

View File

@@ -0,0 +1,254 @@
<template>
<el-dialog
:close-on-click-modal="false"
title="表达式"
width="60%"
:visible.sync="formVisible"
class="bs-dialog-wrap bs-el-dialog"
>
<div class="main-box">
<div class="left-box">
<el-tree
ref="tree"
:data="treeData"
:indent="0"
:props="defaultProps"
:default-expand-all="true"
:highlight-current="true"
:expand-on-click-node="false"
class="bs-el-tree tree-box"
@node-click="handleNodeClick"
>
<template #default="{ node, data }">
<!-- Check if the node is a top-level node -->
<span
v-if="node.level === 1"
:class="{ 'disabled': node.disabled}"
>
<i
class="el-icon-folder"
/>
{{ data.label }}
</span>
<span
v-else
:class="{ 'disabled': node.disabled}"
style="padding-left: 20px"
>
{{ data.label }}
</span>
</template>
</el-tree>
</div>
<div class="right-box">
<div class="codemirror-wrap">
<codemirror
ref="codemirrorRef"
v-model="currentConfig.expression"
class="codemirror-box"
:options="codemirrorOption"
@dragover.prevent
/>
<el-button
class="btn-box"
type="primary"
@click="executeScript"
>
运行脚本
</el-button>
</div>
<div class="script-content-box">
{{ scriptContent }}
</div>
</div>
</div>
<div
slot="footer"
class="dialog-footer"
>
<el-button
class="bs-el-button-default cancel"
@click="cancel"
>
取消
</el-button>
<el-button
type="primary"
@click="sure"
>
确定
</el-button>
</div>
</el-dialog>
</template>
<script>
import { codemirror } from 'vue-codemirror'
import 'codemirror/mode/javascript/javascript'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/nord.css'
import { mapMutations, mapState } from 'vuex'
import cloneDeep from 'lodash/cloneDeep'
export default {
name: 'ExpressionDialog',
components: {
codemirror
},
props: {
config: {
type: Object,
default: () => {
}
}
},
data () {
return {
scriptContent: '', // 脚本执行的内容
expression: '123',
formVisible: false,
codemirrorOption: {
mode: 'text/javascript',
lineNumbers: true,
lineWrapping: true,
theme: 'nord',
extraKey: { Ctrl: 'autocomplete' },
hintOptions: {
completeSingle: true
}
},
defaultProps: { label: 'label', children: 'children' }
}
},
computed: {
...mapState({
dataset: state => state.bigScreen.dataset,
computedDatas: state => state.bigScreen.computedDatas
}),
// 获取树节点数据
treeData () {
const list = []
for (const item in this.dataset) {
let children = []
if (this.dataset[item][0]) {
const fields = Object.keys(this.dataset[item][0])
children = fields.map((field) => {
return {
label: field,
code: item,
value: `dataset['${item}'][0].${field}`,
disabled: item.includes(this.config.code)
}
})
}
list.push({
label: item.split('_')[0],
code: item,
value: `dataset['${item}']`,
disabled: item.includes(this.config.code),
children
})
}
for (const item in this.computedDatas) {
list.push({
label: item.split('_')[0],
code: item,
value: `computedDatas['${item}']`,
disabled: item.includes(this.config.code)
})
}
return list
},
currentConfig () {
return cloneDeep(this.config)
}
},
watch: {},
created () {},
mounted () {},
methods: {
...mapMutations({
changeChartConfig: 'bigScreen/changeChartConfig'
}),
init () {
this.formVisible = true
},
// 运行脚本
executeScript () {
// eslint-disable-next-line no-new-func
const result = new Function('dataset', 'computedDatas', this.currentConfig.expression)
this.scriptContent = result(this.dataset, this.computedDatas)
},
// 点击树节点将数据添加到脚本编辑器中
handleNodeClick (node, data, nodeObj) {
const str = node.value
const code = node.code
if (node.disabled) return
// 判断编辑器里面是return + 0或者多个空格 还是包含其他表达式,每次添加第一个表达式时不要加‘+,防止计算错误
const isInit = /^[\w\s]+$/.test(this.currentConfig.expression)
const newStr = isInit ? this.currentConfig.expression + str : this.currentConfig.expression + ' + ' + str
this.$refs.codemirrorRef.codemirror.setValue(newStr)
// 同时将点击的数据存在expressionCodes中
if (this.currentConfig.expressionCodes && Array.isArray(this.currentConfig.expressionCodes)) {
this.currentConfig.expressionCodes.push(code)
}
},
cancel () {
this.formVisible = false
},
sure () {
this.formVisible = false
this.changeChartConfig(this.currentConfig)
}
}
}
</script>
<style scoped lang="scss">
@import '../../assets/style/bsTheme.scss';
.bs-dialog-wrap{
::v-deep .el-dialog__body{
min-height: 500px;
}
}
.main-box{
width: 100%;
height: 500px;
display: flex;
.left-box{
flex: 1;
height: 100%;
.tree-box{
height: 100%;
overflow-y: auto;
}
}
.right-box{;
flex: 3 ;
height: 100%;
.codemirror-wrap{
height: 50%;
position: relative;
.btn-box{
position: absolute;
right: 10px;
bottom: 10px;
}
}
.codemirror-box {
height: 100% !important;
::v-deep .CodeMirror {
height: 100% !important;
font-family: Helvetica, Tahoma;
}
}
.script-content-box{
padding:10px
}
}
}
.disabled{
cursor: not-allowed;
color: #666666;
}
</style>

View File

@@ -0,0 +1,356 @@
<template>
<div class="bs-setting-wrap">
<el-form
ref="form"
:model="config"
:rules="customRules"
label-width="120px"
label-position="left"
class="setting-body bs-el-form"
>
<SettingTitle>基础</SettingTitle>
<div class="lc-field-body">
<el-form-item
label="标题"
label-width="120px"
>
<el-input
v-model="config.title"
placeholder="请输入标题"
clearable
/>
</el-form-item>
</div>
<SettingTitle>边框</SettingTitle>
<div class="lc-field-body">
<BorderSetting
v-if="config.border"
label-width="120px"
:config="config.border"
:big-title="config.title"
/>
</div>
<SettingTitle>位置</SettingTitle>
<div class="lc-field-body">
<PosWhSetting
label-width="120px"
:config="config"
/>
</div>
<SettingTitle>旋转</SettingTitle>
<div class="lc-field-body">
<RotateSetting
:config="config"
/>
</div>
<template v-for="group in groupList">
<div :key="group.groupName">
<SettingTitle> {{ group.groupName | filterGroupName }}</SettingTitle>
<div class="lc-field-body">
<div
v-for="(setting, settingIndex) in group.list"
:key="settingIndex+1"
>
<el-form-item
:label="['padding','appendPadding'].includes(setting.type)? '' : setting.label"
:label-width="['padding','appendPadding'].includes(setting.type)? '0px' :'120px'"
>
<el-input
v-if="setting.type === 'input'"
v-model="setting.value"
:placeholder="`请输入${setting.label}`"
clearable
/>
<el-select
v-else-if="setting.type === 'select'"
v-model="setting.value"
popper-class="bs-el-select"
class="bs-el-select"
:placeholder="`请选择${setting.label}`"
:filterable="setting.filterable"
:multiple="setting.multiple"
clearable
>
<el-option
v-for="(opt, optIndex) in setting.options"
:key="optIndex"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<template v-else-if="setting.type === 'colorSelect'">
<color-select
v-model="setting.value"
@update="updateColorScheme"
/>
<div
style="
display: flex;
align-items: center;
flex-wrap: wrap;
"
class="color-picker-box"
>
<el-color-picker
v-for="(colorItem, colorItemIndex) in colors"
:key="colorItemIndex"
v-model="setting.value[colorItemIndex]"
popper-class="bs-el-color-picker"
show-alpha
class="start-color"
/>
<span
class="el-icon-circle-plus-outline"
style="color: #007aff; font-size: 20px"
@click="addColor"
/>
<span
v-if="colors.length"
class="el-icon-remove-outline"
style="color: #ea0b30; font-size: 20px"
@click="delColor()"
/>
</div>
</template>
<el-color-picker
v-else-if="setting.type === 'colorPicker'"
v-model="setting.value"
popper-class="bs-el-color-picker"
class="bs-el-color-picker"
show-alpha
/>
<!-- 渐变色设置 -->
<GradualSetting
v-else-if="setting.type === 'gradual'"
v-model="setting.value"
/>
<el-input-number
v-else-if="setting.type === 'inputNumber'"
v-model="setting.value"
class="bs-el-input-number"
:step="setting.step || 1"
:min="setting.min || 0"
:max="setting.max || 100000"
/>
<el-radio-group
v-else-if="setting.type === 'radio'"
v-model="setting.value"
class="bs-el-radio-group"
>
<template v-for="(opt, optIndex) in setting.options">
<el-radio-button
:key="optIndex"
:label="opt.value"
>
{{ opt.label }}
</el-radio-button>
</template>
</el-radio-group>
<el-switch
v-else-if="setting.type === 'switch'"
v-model="setting.value"
class="bs-el-switch"
:active-value="setting.active"
:inactive-value="setting.inactive"
/>
<el-slider
v-else-if="setting.type === 'slider'"
v-model="setting.value"
:min="0"
:max="1"
:step="0.01"
/>
<PaddingSetting
v-else-if="setting.type === 'appendPadding'"
v-model="setting.value"
/>
</el-form-item>
</div>
</div>
</div>
</template>
<!-- </div> -->
</el-form>
</div>
</template>
<script>
import BorderSetting from 'data-room-ui/BigScreenDesign/RightSetting/BorderSetting.vue'
import SettingTitle from 'data-room-ui/SettingTitle/index.vue'
import { chartSettingMixins } from 'data-room-ui/js/mixins/chartSettingMixins'
import ColorSelect from 'data-room-ui/ColorMultipleSelect/index.vue'
// import ColorPicker from 'data-room-ui/ColorPicker/index.vue'
import PaddingSetting from 'data-room-ui/BigScreenDesign/RightSetting/PaddingSetting/index.vue'
import GradualSetting from 'data-room-ui/BigScreenDesign/RightSetting/GradualSetting/index.vue'
import PosWhSetting from 'data-room-ui/BigScreenDesign/RightSetting/PosWhSetting.vue'
import RotateSetting from 'data-room-ui/BigScreenDesign/RightSetting/RotateSetting.vue'
export default {
name: 'CustomComponentSetting',
components: {
ColorSelect,
// ColorPicker,
PaddingSetting,
GradualSetting,
PosWhSetting,
BorderSetting,
SettingTitle,
RotateSetting
},
mixins: [chartSettingMixins],
data () {
return {
groupList: []
}
},
filters: {
filterGroupName (val) {
const settingGroup = {
basic: '基础',
position: '位置',
graph: '图表',
grid: '网格线',
legend: '图例',
xAxis: 'X轴',
yAxis: 'Y轴',
padding: '边距',
appendPadding: '内边距',
other: '其他'
}
return settingGroup[val]
}
},
computed: {
config: {
get () {
return this.$store.state.bigScreen.activeItemConfig
},
set (val) {
this.$store.commit('bigScreen/changeActiveItemConfig', val)
}
},
appCode: {
get () {
return this.$store.state.bigScreen.pageInfo.appCode
}
},
pageCode () {
return this.$route.query.code
}
},
watch: {
groupList: {
// 1、原数组2、修改后的数组只包含custom3、合并的时候xy的配置必须放在最前面
handler (val) {
const setList = [].concat(...val.map(item => item.list))
const newSetList = [...this.config.setting, ...setList]
let newArr = [] // 存新数组
const hash = {}
newArr = newSetList.reduce(function (acc, cru, index) {
if (!hash[cru.field]) {
hash[cru.field] = { index: index }
acc.push(cru)
} else {
acc.splice(hash[cru.field].index, 1, cru)
}
return acc
}, [])
this.$store.commit('bigScreen/changeActiveItemConfig', { ...this.config, setting: newArr })
},
deep: true
}
},
mounted () {
this.init()
const groupNameList = []
this.config.setting.filter(
(item) => item.tabName === 'custom'
).forEach(item => {
if (item.tabName === 'custom' && item.groupName) {
if (!groupNameList.includes(item.groupName)) {
groupNameList.push(item.groupName)
this.groupList.push({
groupName: item.groupName,
list: [item]
})
} else {
this.groupList.find(group => group.groupName === item.groupName).list.push(item)
}
} else {
if (this.groupList.find(group => group.groupName === 'other')) {
this.groupList.find(group => group.groupName === 'other').list.push(item)
} else {
this.groupList.push({
groupName: 'other',
list: [item]
})
}
}
})
for (let i = 0; i < this.groupList.length; i++) {
if (this.groupList[i].groupName === 'other') {
const otherObject = this.groupList.splice(i, 1)[0]
this.groupList.push(otherObject)
break
}
}
},
methods: {
init () {
this.config = this.$store.state.bigScreen.activeItemConfig
}
}
}
</script>
<style lang="scss" scoped>
@import '../../assets/style/settingWrap.scss';
@import '../../assets/style/bsTheme.scss';
// 筛选条件的按钮样式
.add-filter-box {
position: relative;
.add-filter {
margin-left: 90px;
margin-bottom: 10px;
}
.add-filter-btn {
position: absolute;
top: 0;
}
}
.lc-field-body {
padding:12px 16px;
}
.el-form-item{
margin-bottom: 6px !important;
}
.lc-field-title {
position: relative;
padding-left: 12px;
line-height: 30px;
height: 30px;
margin-bottom: 12px;
&:after {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
content: '';
width: 4px;
height: 14px;
background-color: var(--bs-el-color-primary);
}
}
::v-deep .el-color-picker__trigger {
border-color: var(--bs-el-border);
}
.color-picker-box{
::v-deep .el-color-picker__trigger {
width: 27px!important;
}
}
</style>

View File

@@ -0,0 +1,115 @@
/** * @Description: 渐变色配置 * @author liu.shiyi * @date 2023/4/13 16:01 */
<template>
<div class="bs-gradual-wrap">
<el-color-picker
v-model="startColor"
class="bs-el-color-picker"
popper-class="bs-el-color-picker"
/>
<div :class="positionIcon" @click="positionChange" />
<el-color-picker
v-model="endColor"
class="bs-el-color-picker"
popper-class="bs-el-color-picker"
/>
</div>
</template>
<script>
export default {
name: 'GradualSetting',
model: {
prop: 'colors',
event: 'change'
},
props: {
colors: {
type: String,
default: ''
}
},
data () {
return {
startColor: '', // 初始颜色
endColor: '', // 终止颜色
position: '', // 渐变方向
colorsValue: '',// 拼接后的符合g2语法的颜色值
positionList: ['l(0)', 'l(90)', 'l(180)', 'l(270)'],
positionIconList: {
'l(0)': 'el-icon-right',
'l(90)': 'el-icon-bottom',
'l(180)': 'el-icon-back',
'l(270)': 'el-icon-top'
},
positionIcon: 'el-icon-right'
}
},
computed: {
},
watch: {
startColor () {
this.colorChange()
},
endColor () {
this.colorChange()
}
},
mounted () {
this.init()
},
methods: {
init () {
// color 格式是 'l(0) 0:#ffffff 1:#000000'
const arr = this.colors?.split(' ') || []
this.position = arr[0] || 'l(0)'
this.positionIcon = this.positionIconList[this.position] || 'el-icon-right'
const s = arr[1].split(':')[1] && arr[1].split(':')[1] !== 'null' ? arr[1].split(':')[1] : ''
const e = arr[2].split(':')[1] && arr[2].split(':')[1] !== 'null' ? arr[2].split(':')[1] : ''
this.startColor = s
this.endColor = e
},
colorChange (val) {
this.colorsValue = `${this.position} 0:${this.startColor} 1:${this.endColor}`
this.$emit('change', this.colorsValue)
},
positionChange(){
// 将position的值循环移动一位
const index = this.positionList.indexOf(this.position)
this.position = this.positionList[(index + 1) % 4]
this.positionIcon = this.positionIconList[this.position]
this.colorChange()
},
}
}
</script>
<style lang="scss" scoped>
.bs-gradual-wrap{
width: 100%;
display: flex;
align-items: center;
.el-icon-right{
width: 40px;
text-align: center;
cursor: pointer;
}
.el-icon-bottom{
width: 40px;
text-align: center;
cursor: pointer;
}
.el-icon-back{
width: 40px;
text-align: center;
cursor: pointer;
}
.el-icon-top {
width: 40px;
text-align: center;
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,351 @@
<template>
<el-dialog
title="点九图"
:visible.sync="dialogVisible"
:modal="true"
width="75%"
:modal-append-to-body="false"
:appen-to-body="false"
class="bs-dialog-wrap bs-el-dialog"
@closed="close"
@opened="getDom"
>
<div class="contentTable">
<table
border="1"
cellspacing="0"
>
<tr>
<th>方向</th>
<th>描述</th>
</tr>
<tr>
<td>左上角</td>
<td>不能拉伸</td>
</tr>
<tr>
<td>右上角</td>
<td>不能拉伸</td>
</tr>
<tr>
<td>左下角</td>
<td>不能拉伸</td>
</tr>
<tr>
<td>右下角</td>
<td>不能拉伸</td>
</tr>
<tr>
<td>左侧</td>
<td>宽度不变高度自动拉伸</td>
</tr>
<tr>
<td>右侧</td>
<td>宽度不变高度自动拉伸</td>
</tr>
<tr>
<td>顶部</td>
<td>高度不变宽度自动拉伸</td>
</tr>
<tr>
<td>底部</td>
<td>高度不变宽度自动拉伸</td>
</tr>
<tr>
<td>中部</td>
<td>宽度高度自动拉伸</td>
</tr>
</table>
</div>
<div
class="imgContent"
>
<div class="imgContainer">
<span class="toptitle">
<!-- <InputCom @changeStyle='changeTop' :Fx="['上','下']" :number="top" /> -->
<el-input-number
v-model="top"
class="bs-el-input-number"
:step=" 1"
:min="0"
:max="49"
@change="changeTop"
/>
</span>
<span class="righttitle">
<el-input-number
v-model="right"
class="bs-el-input-number"
:step=" 1"
:min="0"
:max="49"
@change="changeRight"
/>
</span>
<span class="bottomtitle">
<el-input-number
v-model="bottom"
class="bs-el-input-number"
:step=" 1"
:min="0"
:max="49"
@change="changeBottom"
/>
</span>
<span class="lefttitle">
<el-input-number
v-model="left"
class="bs-el-input-number"
:step=" 1"
:min="0"
:max="49"
@change="changeLeft"
/>
</span>
<el-image
style="max-width:550px;object-fit: cover;"
:src="imgUrl||url"
fit="cover"
/>
<div
id="top"
class="top"
@mousedown="onMouseDown"
@mouseup="onMouseUp"
@mousemove="onMousemove"
@click="changeSymbol('top')"
/>
<div
id="right"
class="right"
@click="changeSymbol('right')"
/>
<div
id="bottom"
class="bottom"
@click="changeSymbol('bottom')"
/>
<div
id="left"
class="left"
@click="changeSymbol('left')"
/>
</div>
</div>
<div
slot="footer"
class="dialog-footer"
>
<el-button
class="bs-el-button-default"
@click="dialogVisible = false"
>
取消
</el-button>
<el-button
type="primary"
@click="confirm"
>
确定
</el-button>
</div>
</el-dialog>
</template>
<script>
import { getFileUrl } from 'data-room-ui/js/utils/file'
export default {
name: 'SourceDialog',
data () {
return {
contentHeight: 300,
dialogVisible: false,
imgUrl: '',
top: 0,
right: 0,
bottom: 0,
left: 0,
symbol: '',
isDown: false,
x: 0,
y: 0,
l: 0,
t: 0
}
},
computed: {
url () {
return require('data-room-ui/BorderComponents/GcBorder16/component.png')
}
},
methods: {
confirm () {
this.$emit('getArray', [this.top, this.right, this.bottom, this.left])
this.dialogVisible = false
},
init (val, array) {
if (!val.startsWith('http')) {
this.imgUrl = getFileUrl(val)
} else {
this.imgUrl = val
}
if (array) {
[this.top, this.right, this.bottom, this.left] = array
this.$nextTick(() => {
this.changeTop(this.top)
this.changeRight(this.right)
this.changeBottom(this.bottom)
this.changeLeft(this.left)
})
}
this.dialogVisible = true
},
getDom () {
// const a=document.getElementById('top')
// const b=document.getElementById('right')
// const c=document.getElementById('bottom')
// const d=document.getElementById('left')
// this.top=getComputedStyle(a).top.slice(0,-2)
// this.right=getComputedStyle(b).right.slice(0,-2)
// this.bottom=getComputedStyle(c).bottom.slice(0,-2)
// this.left=getComputedStyle(d).left.slice(0,-2)
},
close () {
},
changeTop (val) {
const a = document.getElementById('top')
a.style.top = val + '%'
},
changeRight (val) {
const a = document.getElementById('right')
a.style.right = val + '%'
},
changeBottom (val) {
const a = document.getElementById('bottom')
a.style.bottom = val + '%'
},
changeLeft (val) {
const a = document.getElementById('left')
a.style.left = val + '%'
},
onMouseUp () {
// this.isDown=false;
},
onMousemove (e) {
// const a=document.getElementById('top')
// if(this.isDown==false){
// return
// }
// let ny=e.clientY-194;
// let nt=ny-(this.y-this.t);
// a.style.top=nt+"px"
// this.top=a.style.top
},
onMouseDown (e) {
// this.y=e.layerY
// this.t=this.top;
// this.isDown=true
},
changeSymbol (val) {
this.symbol = val
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog__body{
position: relative;
background-color: #232832;
min-height: 450px;
padding: 16px 16px 16px 16px !important;
overflow: auto;
}
.contentTable{
position: absolute;
top: 0;
left: 0;
width: 400px;
margin-top: 50px;
margin-left: 80px;
margin-right: 200px;
table{
color: #fff;
border: 1px solid #fff;
}
td,th{
padding: 8px 20px;
text-align: center;
vertical-align: middle;
}
}
.imgContent{
width: 400px;
position: absolute;
left: 600px;
top: 50%;
transform: translateY(-50%);
margin-top: 0px;
.imgContainer{
width: 100%;
height: 100%;
position: relative;
.toptitle{
position: absolute;
top: -43px;
left: 50%;
transform: translateX(-50%);
}
.righttitle{
position: absolute;
top: 50%;
transform: translateY(-50%);
right: -150px;
}
.bottomtitle{
position: absolute;
bottom: -43px;
left: 50%;
transform: translateX(-50%);
}
.lefttitle{
position: absolute;
top: 50%;
transform: translateY(-50%);
left: -150px;
}
// height: 100%;
.top{
position: absolute;
top: 0;
height: 1px;
background-color: #fff;
width: 100%;
}
.right{
position: absolute;
right: 0;
top: 0;
height: 100%;
background-color: #fff;
width: 1px;
}
.bottom{
position: absolute;
bottom: 0;
height: 1px;
background-color: #fff;
width: 100%;
}
.left{
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #fff;
width: 1px;
}
}
}
</style>

View File

@@ -0,0 +1,108 @@
<template>
<div class="bs-setting-wrap">
<div class="padding-box">
<el-form-item
label="上边距"
label-width="120px"
>
<el-input-number
v-model.number="paddingValue[0]"
class="bs-el-input-number input-top input-item"
size="mini"
:min="0"
:step="1"
@change="paddingChange"
/>
</el-form-item>
<el-form-item
label="下边距"
label-width="120px"
>
<el-input-number
v-model.number="paddingValue[2]"
class="bs-el-input-number input-bottom input-item"
size="mini"
:min="0"
:step="1"
@change="paddingChange"
/>
</el-form-item>
<el-form-item
label="左边距"
label-width="120px"
>
<el-input-number
v-model.number="paddingValue[3]"
class="bs-el-input-number input-left input-item"
size="mini"
:min="0"
:step="1"
@change="paddingChange"
/>
</el-form-item>
<el-form-item
label="右边距"
label-width="120px"
>
<el-input-number
v-model.number="paddingValue[1]"
class="bs-el-input-number input-right input-item"
size="mini"
:min="0"
:step="1"
@change="paddingChange"
/>
</el-form-item>
</div>
</div>
</template>
<script>
export default {
name: 'PaddingSetting',
model: {
prop: 'padding',
event: 'input'
},
props: {
padding: {
type: Array,
default: () => []
}
},
data () {
return {
position: 0
}
},
computed: {
paddingValue () {
return this.padding
}
},
methods: {
paddingChange () {
this.$emit('input', this.paddingValue)
}
}
}
</script>
<style lang="scss" scoped>
.bs-padding-setting{
.padding-box{
width: 160px;
height: 190px;
position: relative;
}
.padding-center{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 30%;
height: 30%;
background-color: var(--bs-background-1);
}
}
</style>

View File

@@ -0,0 +1,85 @@
<!--
* @description: 组件的宽高xy坐标设置
* @Date: 2023-05-29 14:49:54
-->
<template>
<div>
<el-form-item
:label-width="labelWidth"
label="宽度"
>
<el-input-number
v-model="config.w"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="高度"
>
<el-input-number
v-model="config.h"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="x坐标"
>
<el-input-number
v-model="config.x"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="y坐标"
>
<el-input-number
v-model="config.y"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
</div>
</template>
<script>
export default {
name: '',
props: {
config: {
type: Object,
default: () => ({
x: 0,
y: 0,
w: 0,
h: 0
})
},
labelWidth: {
type: String,
default: '100px'
}
},
data () {
return {
}
},
mounted () {},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,113 @@
<!--
* @description: 旋转的角度
-->
<template>
<div>
<el-form-item
:label-width="labelWidth"
label="透视距离"
>
<el-input-number
v-model="config.perspective"
class="bs-el-input-number"
:min="0"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="绕x轴旋转角度"
>
<el-input-number
v-model="config.rotateX"
class="bs-el-input-number"
:min="-180"
:max="180"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="绕y轴旋转角度"
>
<el-input-number
v-model="config.rotateY"
class="bs-el-input-number"
:min="-180"
:max="180"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="绕z轴旋转角度"
>
<el-input-number
v-model="config.rotateZ"
class="bs-el-input-number"
:min="-180"
:max="180"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="沿x轴扭曲角度"
>
<el-input-number
v-model="config.skewX"
class="bs-el-input-number"
:min="-180"
:max="180"
:step="1"
/>
</el-form-item>
<el-form-item
:label-width="labelWidth"
label="绕y轴扭曲角度"
>
<el-input-number
v-model="config.skewY"
class="bs-el-input-number"
:min="-180"
:max="180"
:step="1"
/>
</el-form-item>
</div>
</template>
<script>
export default {
name: '',
props: {
config: {
type: Object,
default: () => ({
rotateX: 0,
rotateY: 0,
rotateZ: 0,
perspective: 0,
skewX: 0,
skewY: 0
})
},
labelWidth: {
type: String,
default: '120px'
}
},
data () {
return {
}
},
mounted () {},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,142 @@
<template>
<div class="bs-gradual-wrap">
<el-form-item
:label="`${customLabel}渐变方向`"
label-width="100px"
>
<el-radio-group
v-model="position"
class="bs-el-radio-group"
>
<el-radio label="top">
上下
</el-radio>
<el-radio label="left">
左右
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
:label="`${customLabel}渐变颜色`"
label-width="100px"
>
<div class="color-picker-box">
<el-color-picker
v-model="startColor"
class="bs-el-color-picker"
popper-class="bs-el-color-picker"
/>
<div class="el-icon-right" />
<el-color-picker
v-model="endColor"
class="bs-el-color-picker"
popper-class="bs-el-color-picker"
/>
</div>
</el-form-item>
</div>
</template>
<script>
// import _ from 'lodash'
export default {
name: 'TextGradient',
model: {
prop: 'colors',
event: 'change'
},
props: {
colors: {
type: String,
default: '',
required: true
},
label: {
type: String,
default: ''
}
},
data () {
return {
startColor: '', // 初始颜色
endColor: '', // 终止颜色
position: '', // 渐变方向
colorsValue: ''// 拼接后的符合g2语法的颜色值
}
},
computed: {
// newColors:
// {
// get () {
// return this.colors
// },
// set (val) {
// this.$emit('change', val)
// }
// },
customLabel () {
return this.label || '文字'
}
},
watch: {
colors: {
handler (val) {
this.init()
},
immediate: true
},
position () {
this.colorChange()
},
startColor () {
this.colorChange()
},
endColor () {
this.colorChange()
}
},
mounted () {
this.init()
},
methods: {
init () {
const arr = this.colors.split(',').map(data => data.trim()) || []
this.position = arr[0] || 'left'
const s = arr[1] || '#ffffff'
const e = arr[2] || '#ffffff'
this.startColor = s
this.endColor = e
},
colorChange (val) {
if (!this.startColor && this.endColor) {
this.colorsValue = `${this.position} ,${this.endColor},${this.endColor}`
} else if (this.startColor && !this.endColor) {
this.colorsValue = `${this.position} ,${this.startColor} ,${this.startColor}`
} else if (!this.startColor && !this.endColor) {
this.colorsValue = `${this.position} ,#ffffff ,#ffffff`
} else {
this.colorsValue = `${this.position} ,${this.startColor} ,${this.endColor}`
}
this.$emit('change', this.colorsValue)
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../assets/style/bsTheme.scss";
.color-picker-box{
width: 100%;
display: flex;
align-items: center;
justify-content: left;
flex-wrap: nowrap;
.el-icon-right{
width: 40px;
text-align: center;
/*color: #778390;*/
}
}
</style>

View File

@@ -0,0 +1,272 @@
<template>
<div
class="bs-setting-wrap"
@click.stop
>
<el-tabs
v-if="config.option.displayOption.dataAllocation.enable"
v-model="activeName"
@tab-click="handleClick"
>
<el-tab-pane
label="数据"
name="data"
>
<DataSetting
ref="dataSetting"
:key="config.code"
>
<template #dataSetSelect="{value}">
<slot
name="dataSetSelect"
:value="value"
/>
</template>
</DataSetting>
</el-tab-pane>
<el-tab-pane
label="样式"
name="second"
>
<component
:is="resolveComponentType(config.type)"
ref="customSetting"
:key="config.code"
:config="config"
@closeRightPanel="close"
/>
</el-tab-pane>
</el-tabs>
<el-scrollbar
v-else
class="bs-setting-wrap bs-scrollbar"
>
<component
:is="resolveComponentType(config.type)"
ref="customSetting"
:key="config.code"
:config="config"
@closeRightPanel="close"
/>
</el-scrollbar>
</div>
</template>
<script>
import { resolveComponentType } from 'data-room-ui/js/utils'
import DataSetting from './DataSetting.vue'
import rightSetting from 'data-room-ui/js/utils/rightSettingImport'
import CustomComponent from './G2CustomSetting.vue'
import EchartsCustomSetting from './EchartsCustomSetting.vue'
import Svgs from 'data-room-ui/Svgs/setting.vue'
import { mapState, mapMutations } from 'vuex'
// import _ from 'lodash'
import isEqual from 'lodash/isEqual'
import cloneDeep from 'lodash/cloneDeep'
import { EventBus } from 'data-room-ui/js/utils/eventBus'
// 整体动态导入右侧设置组件,不用手动注册
const components = {}
for (const key in rightSetting) {
if (Object.hasOwnProperty.call(rightSetting, key)) {
const component = rightSetting[key]
components[key] = component
}
}
export default {
name: 'RightSetting',
components: {
...components,
DataSetting,
CustomComponent,
Svgs,
// 远程组件的样式配置也和g2Plot的样式配置一样采用属性配置, 故使用一个组件
RemoteComponent: CustomComponent,
EchartsComponent: EchartsCustomSetting
},
data () {
return {
activeName: 'data',
isOperationRollback: false
}
},
computed: {
...mapState({
activeCode: (state) => state.bigScreen.activeCode,
hoverCode: (state) => state.bigScreen.hoverCode,
config: (state) => state.bigScreen.activeItemConfig,
chartList: (state) => state.bigScreen.pageInfo.chartList
}),
pageCode () {
return this.$route.query.code
},
configDataSource () {
return {
dataSource: cloneDeep(this.config.dataSource),
linkage: cloneDeep(this.config?.linkage),
dataHandler: this.config?.dataHandler,
dataSourceSetting: cloneDeep(this.config?.setting?.filter(item => item.tabName === 'data')) || [],
code: this.config?.code
}
},
configStyle () {
return {
showTitle: this.config.showTitle,
title: cloneDeep(this.config?.title),
border: cloneDeep(this.config?.border),
w: this.config?.w,
h: this.config?.h,
x: this.config?.x,
y: this.config?.y,
z: this.config?.z,
rotateX: this.config?.rotateX,
rotateY: this.config?.rotateY,
rotateZ: this.config?.rotateZ,
perspective: this.config?.perspective,
skewX: this.config?.skewX,
skewY: this.config?.skewY,
setting: cloneDeep(this.config?.setting),
customize: cloneDeep(this.config?.customize),
url: this.config?.url,
dateFormat: this.config?.dateFormat,
endTime: this.config?.endTime
}
}
},
watch: {
// 只更新样式部分,不调用接口
configStyle: {
handler (val, oldValue) {
this.handleConfigChange(val, oldValue, 'configStyle')
},
deep: true
},
// 更新数据源部分,需要调用接口
configDataSource: {
handler (val, oldValue) {
this.handleConfigChange(val, oldValue, 'configDataSource')
},
deep: true
}
},
mounted () {
EventBus.$on('operationRollback', val => {
this.isOperationRollback = val
})
},
beforeDestroy () {
EventBus.$off('operationRollback')
},
methods: {
...mapMutations('bigScreen', [
'saveTimeLine'
]),
debounce (delay, obj) {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.timeout = setTimeout(() => {
this.$emit('updateSetting', { ...obj })
}, delay)
},
handleConfigChange (val, oldValue, type) {
if (val.code === oldValue.code) {
if (!isEqual(val, oldValue)) {
if (type === 'configStyle') {
if (this.config.type === 'iframeChart') {
this.debounce(500, { ...val, type: this.config.type, code: this.config.code, parentCode: this.config?.parentCode })
} else {
this.$emit('updateSetting', { ...val, type: this.config.type, code: this.config.code, theme: this.config.theme, parentCode: this.config?.parentCode })
}
} else {
this.$emit('updateDataSetting', this.config)
}
if (!this.isOperationRollback) {
this.saveTimeLine(`更新${val?.title ?? this.config.title}组件属性`)
this.isOperationRollback = false
}
}
}
},
close () {
this.$emit('closeRightPanel')
},
handleClick (val) {
this.$set(this, 'activeName', val.name)
},
resolveComponentType,
// 多个表单校验
getFormPromise (form) {
return new Promise((resolve) => {
form.validate((res) => {
resolve(res)
})
})
},
// 更新
update () {
// 有数据配置也有自定义配置的组件
if (this.config.option.displayOption.dataAllocation.enable) {
// 获取子组件的表单元素
const commonForm = this.$refs.dataSetting.$refs.form
const customForm = this.$refs.customSetting.$refs.form
Promise.all([commonForm, customForm].map(this.getFormPromise)).then(
async (res) => {
const vaildateResult = res.every((item) => !!item)
if (vaildateResult) {
if (this.$refs.dataSetting.params) {
const params = this.$refs.dataSetting.params
const paramsMap = params.reduce((obj, param) => {
obj[param.name] = param.value
return obj
}, {})
this.config.dataSource.params = paramsMap
}
this.$emit('updateDataSetting', this.config)
} else {
this.$message.warning('请完成数据配置')
return false
}
}
)
} else {
// 只有自定义配置的组件
if (this.$refs.customSetting?.$refs?.form?.validate) {
this.$refs.customSetting.$refs.form.validate((valid) => {
if (valid) {
this.$emit('updateSetting', this.config)
this.$message.success('更新成功')
} else {
this.$message.warning('请完成配置')
return false
}
})
} else {
// 边框装饰组件的右侧配置
this.$refs.customSetting.$refs.form.$refs.form.validate((valid) => {
if (valid) {
this.$emit('updateSetting', this.config)
this.$message.success('更新成功')
} else {
this.$message.warning('请完成配置')
return false
}
})
}
}
}
}
}
</script>
<style lang="scss" scoped>
@import '../../assets/style/settingWrap.scss';
.add-filter-box {
position: relative;
.add-filter {
margin-left: 100px;
}
.add-filter-btn {
position: absolute;
top: 0;
}
}
</style>