Files
SmartOpsWeb/src/views/custom-query/echarts-editor/components/AxisBox.vue
2024-08-18 22:21:18 +08:00

539 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<el-card class="box-card box-card-h">
<el-row justify="space-between" class="x-y-axis">
<el-text>值轴/{{ boxName }}</el-text>
<el-tooltip
effect="dark"
:content="boxName+',数据类型必须一致!'"
placement="bottom"
>
<el-icon>
<Warning/>
</el-icon>
</el-tooltip>
</el-row>
<div class="drag-block">
<draggable
class="list-group"
:list="dragList"
itemKey="id"
:group="group"
@start="startDrag"
@change="dragChartItem"
>
<template #item="{ element,index }">
<div :id="element.dataType==='value'?'card_'+index:''" tabindex="1"
@click.stop="handleClickValueCard(element,index)">
<el-card shadow="hover" class="cards x-y-cards"
:style="{borderWidth:1,borderColor:element.dataType==='value'?element.color:'#e4e7ed'}">
<el-col :span="3">
<div>{{ element.label }}</div>
</el-col>
<el-col :span="13">
<div v-if="element.dataType==='value'" class="update-color">
<div class="update-color" @click.stop>
<span>图形</span>
<el-color-picker v-model="element.color" :color="element.color"
@change="changeEchartsColor($event,index)" @active-change="handleActiveChange"/>
</div>
<div v-if="currentChart==='line'" class="update-color" @click.stop>
<span>阴影</span>
<el-color-picker v-model="element.lineStyle.shadowColor" :color="element.lineStyle.shadowColor"
@change="changeShadowColor($event,index)" @active-change="handleActiveChange"/>
</div>
<div v-if="currentChart==='bar'" class="update-color" @click.stop>
<span>背景: </span>
<el-color-picker v-model="element.backgroundStyle.color" :color="element.backgroundStyle.color"
@change="changeBackgroundColor($event,index)" @active-change="handleActiveChange"/>
</div>
<div v-if="currentChart==='bar'" class="update-color" @click.stop>
<span >描边: </span>
<el-color-picker v-model="element.backgroundStyle.borderColor" :color="element.backgroundStyle.borderColor"
@change="changeBackgroundBorderColor($event,index)" @active-change="handleActiveChange"/>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="cards-right">
<span>{{ element.dataType }}</span>
<el-icon size="20" color="red" @click.stop="handleCancelAxis(element,index)"
style="cursor: pointer">
<CircleClose/>
</el-icon>
</div>
</el-col>
</el-card>
</div>
</template>
</draggable>
</div>
</el-card>
</div>
</template>
<script setup>
import draggable from 'vuedraggable'
const emit = defineEmits(["editBasicSettingList"])
const props = defineProps({
//box名字
boxName: {
type: String,
default: ''
},
//可供拖动的选项列表
dragOptions: {
type: Array,
default: []
},
//用于拖拽区域存放选项列表
dragList: {
type: Array,
default: []
},
//用于X轴区域存放拖动的选项
xAxisList: {
type: Array,
default: []
},
//用于Y轴区域存放拖动的选项
yAxisList: {
type: Array,
default: []
},
//标记正在拖动选项的数据类型是否value
flag: {
type: Boolean,
default: false
},
//获取正在拖动选项的数据类型
startDataType: {
type: String,
default: ''
},
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
//当前echarts图形
currentChart: {
type: String,
default: 'line'
}
})
//基础设置列表
const lineChartBasicSettingList = ref()
const barChartBasicSettingList = ref()
//选中类型为value的item所处的list列表
const valueCardInList = ref([])
//简化代码
let xList = reactive(props.xAxisList)
let yList = reactive(props.yAxisList)
let option = reactive(props.chartOption)
//路由刷新
const reload = inject("reload")
//自定义X/Y分组的拖入拖出事件
const group = ref({
name: 'people',
pull: true,
put: props.flag === true ? false : (props.boxName === 'X轴' ? () => handleGroupPut(xList, yList) : () => handleGroupPut(yList, xList))
})
//将改变的数据传到父组件
watch(() => lineChartBasicSettingList.value, (newVal) => {
emit("getLineChartBasicSettingList", newVal)
})
//将改变的数据传到父组件
watch(() => barChartBasicSettingList.value, (newVal) => {
emit("getBarChartBasicSettingList", newVal)
})
onMounted(() => {
document.addEventListener('click', nullBlockClick)
})
onBeforeUnmount(() => {
document.removeEventListener('click', nullBlockClick)
})
/**
* 设置chart的lineStyle
* @param sItem chartItem
* @param opacity 透明度
*/
const handleChangeLineStyle = (sItem, opacity) => {
sItem.lineStyle = {
shadowColor: sItem.lineStyle.shadowColor,
shadowBlur: sItem.lineStyle.shadowBlur,
opacity: opacity
}
}
/**
* 用于取消charts选中透明度
*/
const handleChangeOpacity = (type, item) => {
if (props.currentChart === 'line') {
option.series.forEach((sItem) => {
if (type === 'more') {
if (sItem.name === item.label) {
handleChangeLineStyle(sItem, 1)
} else {
handleChangeLineStyle(sItem, 0.2)
}
} else if (type === 'single') {
handleChangeLineStyle(sItem, 1)
} else {
if (sItem.name !== item.label) {
handleChangeLineStyle(sItem, 1)
}
}
})
}
}
/**
* 点击空白处, 清除选项选中状态
*/
const nullBlockClick = () => {
if (valueCardInList.value.length === 0) return;
valueCardInList.value.forEach((aItem, aIndex) => {
const card = document.getElementById('card_' + aIndex)
card.classList.remove('card-active')
})
clearBasicSetting()
//加载echarts
props.initCharts()
}
/**
* 封装自定义X/Y分组的拖入事件
* @param aType 传入x/y区域数组
* @param bType 传入x/y区域数组
* @returns {boolean} 返回 true/false
*/
const handleGroupPut = (aType, bType) => {
let flag = false
let aLen = aType.length
let bLen = bType.length
if (aLen === 0 && bLen === 0) {
flag = props.startDataType === 'key';
} else if (aLen === 0 && bLen !== 0) {
flag = bType[0].dataType === 'key';
} else if (aLen !== 0 && bLen !== 0) {
const dragType = localStorage.getItem('dragType')
flag = props.startDataType === aType[0].dataType;
if (dragType === 'key') {
flag = aType[0].dataType !== 'value';
}
}
return flag
}
/**
* 封装切换坐标轴数据类型为Category
* @param item 拖动的项
* @param label 坐标轴名称
* @param type 切换x/y轴
*/
const changeTypeToCategory = (item, label, type) => {
let axis
if (type === 'xAxis') {
axis = option.xAxis
} else {
axis = option.yAxis
}
axis.type = 'category'
axis.name = label
axis.data = item.data
}
/**
* 封装清除坐标轴数据
* @param type 标志清除x/y轴
*/
const clearAxisData = (type) => {
let axis
if (type === 'xAxis') {
axis = option.xAxis
} else {
axis = option.yAxis
}
axis.name = ''
axis.data = []
}
/**
* 封装key拖入左侧时的重置事件
* @param aList x/yList
* @param type x/yAxis
* @param item 选项item
* @param label 选项名
*/
const restoreChart = (aList, type,item,label) => {
let axis
if (type === 'xAxis') {
axis = option.xAxis
} else {
axis = option.yAxis
}
if (aList[0].dataType === 'value') {
aList.map((item) => {
props.dragOptions.unshift(item)
option.legend.selected[item.label] = false
})
aList.splice(0, aList.length)
option.legend.data.splice(0, option.legend.data.length)
option.series.splice(0, option.series.length)
axis.name = ''
option.xAxis.type = 'category'
option.yAxis.type = 'value'
} else {
changeTypeToCategory(item, label, type)
}
}
/**
* 拖拽类型为key的选项事件
* @param item 选项item
* @param label 选项名
*/
const dragTypeToKey = (item, label) => {
if (xList.length !== 0 && yList.length === 0) {
restoreChart(xList, 'xAxis',item,label)
clearAxisData('yAxis')
} else if (xList.length === 0 && yList.length !== 0) {
restoreChart(yList, 'yAxis',item,label)
clearAxisData('xAxis')
} else if (xList.length === 0 && yList.length === 0) {
//移入左侧待选列表
clearAxisData('xAxis')
clearAxisData('yAxis')
}
}
/**
* 拖拽类型为value的选项事件
* @param label 选项名
*/
const dragTypeToValue = (label) => {
//删除选中选项的图例
const legendIndex = option.legend.data.findIndex(object => object === label);
option.legend.data.splice(legendIndex, 1)
//删除echarts配置项series中符合该拖拽选项的item
const objectIndex = option.series.findIndex(object => object.name === label);
option.legend.selected[label] = false
option.series.splice(objectIndex, 1)
if (xList.length === 0) {
option.xAxis.name = ''
} else if (yList.length === 0) {
option.yAxis.name = ''
}
clearBasicSetting()
handleDeleteClassName(xList, yList)
}
/**
* 封装清空基本设置
*/
const clearBasicSetting=()=>{
if(props.currentChart==='line'){
lineChartBasicSettingList.value = []
handleChangeOpacity('single')
}else if(props.currentChart==='bar'){
barChartBasicSettingList.value=[]
}
}
/**
* 开始拖拽事件
* @param event event事件
*/
const startDrag = (event) => {
localStorage.setItem('dragType', event.item._underlying_vm_.dataType)
}
/**
* 从X轴/Y轴区域移动选项到左/右侧结束事件
* @param event event事件
*/
const dragChartItem = (event) => {
if (event.removed === undefined) return;
let item = event.removed.element
let label = item.label
//拖动key的选项
if (item.dataType === "key") {
dragTypeToKey(item, label)
} else {
dragTypeToValue(label)
}
props.initCharts()
localStorage.removeItem('dragType')
}
/**
* 选中数据类型为value的点击事件
* @param item 点击的选项item
* @param index 点击选项的下标
*/
const handleClickValueCard = (item, index) => {
document.addEventListener('click', nullBlockClick)
if (item.dataType === 'value' ) {
if(props.currentChart === 'line'){
changeCardActive(props.dragList, item)
lineChartBasicSettingList.value = [item]
}else if(props.currentChart === 'bar'){
changeCardActive(props.dragList, item)
barChartBasicSettingList.value = [item]
}
}
props.initCharts()
}
/**
* 封装选中类型为value的数据高亮
* @param list x/y区域list
* @param item 点击选项的item
*/
const changeCardActive = (list, item) => {
valueCardInList.value = list
emit('getCardActiveList',list)
if (list.length !== 0 && list[0].dataType === 'value') {
handleChangeOpacity('more', item)
list.forEach((aItem, aIndex) => {
const card = document.getElementById('card_' + aIndex)
if (aItem.label === item.label) {
card.classList.add('card-active')
} else {
card.classList.remove('card-active')
}
})
}
}
/**
* 基础设置: 修改echarts数据颜色
* @param val 修改的标记大小
* @param index 修改的chart项下标
*/
const changeEchartsColor = (val, index) => {
document.addEventListener('click', nullBlockClick)
option.series[index].color = val
props.initCharts()
}
/**
* 当选择颜色时移除空白点击事件
*/
const handleActiveChange = () => {
document.removeEventListener('click', nullBlockClick)
}
/**
* 基础设置: 修改echarts数据颜色
* @param val 修改的标记大小
* @param index 修改的chart项下标
*/
const changeShadowColor = (val, index) => {
option.series[index].lineStyle.shadowColor = val
props.initCharts()
}
/**
* 基础设置:修改柱条背景颜色
* @param val 柱条颜色
* @param index 修改的chart项下标
*/
const changeBackgroundColor = (val, index) => {
option.series[index].backgroundStyle.color = val
props.initCharts()
}
/**
* 基础设置:修改柱条描边颜色
* @param val 柱条描边颜色
* @param index 修改的chart项下标
*/
const changeBackgroundBorderColor = (val, index) => {
option.series[index].backgroundStyle.borderColor = val
props.initCharts()
}
/**
* 封装从右侧区域拖出事件
* @param element 获取点击该拖出的选项事件
* @param index 点击该拖出选项的索引
* @param aList x/y区域的值
* @param bList x/y区域的值
* @param aAxis echarts配置项的x/y轴
* @param bAxis echarts配置项的x/y轴
*/
const handleCancel = (element, index, aList, bList, aAxis, bAxis) => {
aList.splice(index, 1)
props.dragOptions.push(element)
if (element.dataType === "key") {
aAxis.name = ''
aAxis.data = []
bAxis.name=''
bList.map((item) => {
props.dragOptions.unshift(item)
option.legend.selected[item.label] = false
})
bList.splice(0, bList.length)
option.legend.data.splice(0, option.legend.data.length)
option.series.splice(0, option.series.length)
// reload
props.initCharts()
} else {
if (bList.length !== 0 && aList.length === 0) {
if (bList[0].dataType === 'key') {
aAxis.name = ''
} else {
bAxis.name = ''
}
}
option.legend.data.splice(index, 1)
const objectIndex = option.series.findIndex(object => object.name === element.label);
option.legend.selected[element.label] = false
option.series.splice(objectIndex, 1)
props.initCharts()
}
if(props.currentChart==='line'){
handleChangeOpacity('not', element)
if (lineChartBasicSettingList.value === undefined) return;
lineChartBasicSettingList.value.splice(0, 1)
}else if(props.currentChart==='bar'){
if (barChartBasicSettingList.value === undefined) return;
barChartBasicSettingList.value.splice(0, 1)
}
// const basicIndex = lineChartBasicSettingList.value.findIndex(object => object.label === element.label)
// if (basicIndex !== -1) {
// lineChartBasicSettingList.value.splice(basicIndex, 1)
// }
handleDeleteClassName(aList, bList)
props.initCharts()
}
/**
* 拖拽选项后,清除选中选项阴影
* @param aList x/y list
* @param bList x/y list
*/
const handleDeleteClassName = (aList, bList) => {
let axis = []
if (aList.length !== 0 && aList[0].dataType === 'value') {
axis = aList
} else if (bList.length !== 0 && bList[0].dataType === 'value') {
axis = bList
}
axis.forEach((aItem, aIndex) => {
const card = document.getElementById('card_' + aIndex)
card.classList.remove('card-active')
})
}
/**
* 从右侧x/y轴区域取消选项
* @param element 该取消的项
* @param index 该取消项的下标
*/
const handleCancelAxis = (element, index) => {
if (props.boxName === 'X轴') {
handleCancel(element, index, xList, yList, option.xAxis, option.yAxis)
} else {
handleCancel(element, index, yList, xList, option.yAxis, option.xAxis)
}
}
</script>