初始化
This commit is contained in:
@@ -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>
|
||||
426
frontend/packages/BigScreenDesign/RightSetting/BorderSetting.vue
Normal file
426
frontend/packages/BigScreenDesign/RightSetting/BorderSetting.vue
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
1001
frontend/packages/BigScreenDesign/RightSetting/DataSetting.vue
Normal file
1001
frontend/packages/BigScreenDesign/RightSetting/DataSetting.vue
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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、修改后的数组只包含custom,3、合并的时候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>
|
||||
102
frontend/packages/BigScreenDesign/RightSetting/ElDragSelect.vue
Normal file
102
frontend/packages/BigScreenDesign/RightSetting/ElDragSelect.vue
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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、修改后的数组只包含custom,3、合并的时候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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
113
frontend/packages/BigScreenDesign/RightSetting/RotateSetting.vue
Normal file
113
frontend/packages/BigScreenDesign/RightSetting/RotateSetting.vue
Normal 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>
|
||||
@@ -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>
|
||||
272
frontend/packages/BigScreenDesign/RightSetting/index.vue
Normal file
272
frontend/packages/BigScreenDesign/RightSetting/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user