This commit is contained in:
clay
2024-03-04 19:13:43 +08:00
commit e44edd71c0
350 changed files with 52288 additions and 0 deletions

View File

@@ -0,0 +1,233 @@
<template>
<div>
<EchartsEditor :info="initInfo" :line-data="lineChartsItem" :bar-data="barChartsItem" :pie-data="pieChartsItem"
:radar-data="radarChartsItem" :radar-indicator="indicator" @getFinalInfo="getFinalInfo"/>
</div>
</template>
<script setup>
import EchartsEditor from "./components/EchartsEditor.vue";
//入参
const lineChartsItem = ref([
{
id: 1,
unit: '年份',
type: '',
dataType: 'key',
color: '',
label: '年份',
symbol: "",
symbolSize: 0,
showSymbol: false,
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1
},
data: ['2013', '2014', '2015', '2016', '2017', '2018']
},
{
id: 2,
unit: '年销量',
type: 'line',
dataType: 'value',
color: '#9a60b4',//图形颜色
label: '华北',
symbol: "triangle",//标记的图形circle:圆形,rect:矩形,triangle:三角形,diamond:钻石形,roundRect:圆角矩形,pin:圆钉形,arrow:箭头形,none:不显示标记
symbolSize: 8,//标记的大小
showSymbol: true,//是否显示标记,如果 false 则只有在 tooltip hover 的时候显示。
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1//图形透明度
},
data: [40, 80, 20, 120, 140, 50]
},
{
id: 3,
unit: '年销量',
type: 'line',
dataType: 'value',
color: '#3ba272',
label: '华东',
symbol: "circle",
symbolSize: 8,
showSymbol: true,
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1
},
data: [140, 180, 120, 40, 50, 150]
},
{
id: 4,
unit: '年销量',
type: 'line',
dataType: 'value',
color: '#5470c6',
label: '华南',
symbol: "rect",
symbolSize: 8,
showSymbol: true,
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1
},
data: [110, 143, 68, 90, 120, 130]
}
])
const barChartsItem = ref([
{
id: 1,
unit: '年份',
type: '',
dataType: 'key',
color: '',
label: '年份',
showBackground: false,
backgroundStyle: {
color: '',
borderWidth: 0,
borderColor: '',
borderType: 'solid',
},
data: ['2013', '2014', '2015', '2016', '2017', '2018']
},
{
id: 2,
unit: '销售金额',
type: 'bar',
dataType: 'value',
color: '#9a60b4',//图形颜色
label: '王五',
showBackground: true,//是否显示柱条的背景色
backgroundStyle: {
color: '#e5e2e2',//柱条的颜色
borderWidth: 0,//柱条的描边宽度,默认不描边。
borderColor: '#000',//柱条的描边颜色
borderType: 'dotted',//柱条的描边类型,默认为实线,支持 'dashed', 'dotted'
},
data: [40, 80, 20, 120, 140, 50]
},
{
id: 3,
unit: '销售金额',
type: 'bar',
dataType: 'value',
color: '#3ba272',
label: '李四',
showBackground: true,
backgroundStyle: {
color: '#e5e2e2',
borderWidth: 0,
borderColor: '#000',
borderType: 'dashed',
},
data: [140, 180, 120, 40, 50, 150]
},
{
id: 4,
unit: '销售金额',
type: 'bar',
dataType: 'value',
color: '#2644a4',
label: '张三',
showBackground: true,
backgroundStyle: {
color: '#e5e2e2',
borderWidth: 0,
borderColor: '#000',
borderType: 'solid',
},
data: [110, 143, 68, 90, 120, 130]
}
])
const pieChartsItem = ref([
{id: 1, label: '京东', dataType: 'value', value: 335},
{id: 2, label: '菜鸟', dataType: 'value', value: 310},
{id: 3, label: '总部', dataType: 'value', value: 234},
{id: 4, label: '小电商', dataType: 'value', value: 135},
])
const radarChartsItem = ref([
{label: 'Allocated Budget', dataType: 'value', data: [4200, 3000, 20000, 35000, 50000, 18000]},
{label: 'Actual Spending', dataType: 'value', data: [5000, 14000, 28000, 26000, 42000, 21000]},
])
//定义好echarts的配置数据
let initInfo = reactive({
xValueAxis: [],
yValueAxis: [],
//echarts配置数据
echartsOptions: {
//图例
legend: {
data: [],
selected: {},
selectedMode: false
},
//离容器四侧的距离
grid: {
left: 40, // 左边距
right: 60, // 右边距
top: 40, // 顶边距
bottom: 20, // 底边距
// containLabel: true,
},
//提示框组件
tooltip: {
show: true,
trigger: 'axis'
},
//工具栏
// toolbox: {
// feature: {
// //重置按钮显示
// restore: {
// show: true,
// title: '重置'
// }
// }
// },
//X轴
xAxis: {
name: '',
type: 'category',
data: [],
axisLine: {
show: true
}
},
//Y轴
yAxis: {
name: '',
type: 'value',
data: [],
axisLine: {
show: true
}
},
radar: {
// shape: 'circle',
},
//配置项
series: []
}
})
const indicator= ref([
{ name: 'Sales', max: 6500 },
{ name: 'Administration', max: 16000 },
{ name: 'Information Technology', max: 30000 },
{ name: 'Customer Support', max: 38000 },
{ name: 'Development', max: 52000 },
{ name: 'Marketing', max: 25000 }
])
//获取到拖拽后的数据
const getFinalInfo = (val) => {
// console.log('父组件获取最终数据', val)
if (val !== undefined) {
initInfo = val
}
}
getFinalInfo()
</script>

View File

@@ -0,0 +1,538 @@
<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>

View File

@@ -0,0 +1,307 @@
<template>
<div>
<el-card class="box-card">
<div class="drag-block">
<draggable
class="list-group"
:list="dragOptions"
itemKey="id"
group="people"
@start="startDrag"
@change="changeChartItem"
>
<template #item="{element}">
<el-card shadow="hover" class="cards">
<el-row justify="space-between">
<span>{{ element.label }}</span>
<span>{{ element.dataType }}</span>
</el-row>
</el-card>
</template>
</draggable>
</div>
</el-card>
</div>
</template>
<script setup>
import draggable from 'vuedraggable'
import {ElMessage} from "element-plus";
const emit = defineEmits(["editValueFlag", "editStartDataType"])
const props = defineProps({
//可供拖动的选项列表
dragOptions: {
type: Array,
default: []
},
//echarts的配置属性
chartOption: {
type: Object,
default: {}
},
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//用于X轴区域存放拖动的选项
xAxisList: {
type: Array,
default: []
},
//用于Y轴区域存放拖动的选项
yAxisList: {
type: Array,
default: []
},
//当前echarts图形
currentChart: {
type: String,
default: 'line'
},
//雷达图指示器
radarIndicator: {
type: Array,
default: []
}
})
//简化代码
let xList = reactive(props.xAxisList)
let yList = reactive(props.yAxisList)
let option = reactive(props.chartOption)
let chart = reactive(props.currentChart)
//获取正在拖动选项的数据类型
const startDragType = ref()
//标记正在拖动选项的数据类型是否value
const flag = ref(false)
//将改变的数据传到父组件
watch(() => flag.value, (newVal) => {
emit("editValueFlag", newVal)
})
watch(() => props.currentChart, (newVal) => {
chart = newVal
})
watch(() => startDragType.value, (newVal) => {
emit("editStartDataType", newVal)
})
/**
* 设置修改后的echarts属性
* @param item 拖动的项
* @param label 拖拽选项的名称
* @returns Object
*/
const settingChartItem = (item, label) => {
if (chart === 'line') {
return {
id: item.id,//组件 ID
name: label,
// type: echartsValue.value ? echartsValue.value : item.type,
type: chart,
data: item.data,
smooth: true,
color: item.color,
symbol: item.symbol,
symbolSize: item.symbolSize,
showSymbol: item.showSymbol,
lineStyle: item.lineStyle,
// emphasis: item.emphasis
}
} else if (chart === 'bar') {
return {
id: item.id,
name: label,
type: chart,
data: item.data,
color: item.color,
showBackground: item.showBackground,
backgroundStyle: item.backgroundStyle
}
}
}
/**
* 封拖拽数据类型为value
* @param item 拖动的项
* @param label 拖拽选项的名称
* @param selectedObj 图例选中状态表
*/
const dragValue = (item, label, selectedObj) => {
dragChart(item, label, 2)
option.legend.data.push(label)
let chartItem = settingChartItem(item, label)
option.series.push(chartItem)
for (const propertyName in selectedObj) {
if (propertyName === label) {
selectedObj[propertyName] = true
}
}
}
/**
* 封装切换坐标轴数据类型为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 = item.unit
axis.data = item.data
}
/**
* 封装切换坐标轴数据类型为Value
* @param item 拖动的项item
* @param type 切换x/y轴
*/
const changeTypeToValue = (item, type) => {
let axis
if (type === 'xAxis') {
axis = option.xAxis
} else {
axis = option.yAxis
}
axis.type = 'value'
axis.name = item.unit
}
/**
* 封装拖拽选项修改echarts属性
* @param item 拖动的项
* @param label 拖拽选项的名称
* @param index 区分拖的选项数据:1是key,2是value
*/
const dragChart = (item, label, index) => {
if (xList.length !== 0 && yList.length === 0) {
// console.log('x轴有值')
if (index === 1) {
changeTypeToCategory(item, label, 'xAxis')
} else {
changeTypeToValue(item, 'xAxis')
option.yAxis.type = 'category'
}
} else if (xList.length !== 0 && yList.length !== 0) {
// console.log('xy有值')
if (xList[0].dataType === 'value') {
if (index === 1) {
changeTypeToCategory(item, label)
}
changeTypeToValue(item, 'xAxis')
} else if (yList[0].dataType === 'value') {
if (index === 1) {
changeTypeToCategory(item, label, 'xAxis')
}
changeTypeToValue(item)
}
} else if (xList.length === 0 && yList.length !== 0) {
// console.log('y轴有值')
if (index === 1) {
changeTypeToCategory(item, label, 'yAxis')
} else {
option.xAxis.type = 'category'
changeTypeToValue(item)
}
}
}
/**
* 从左侧区域移动选项到右侧
* @param event 拖拽成功event事件
*/
const changeChartItem = (event) => {
if (event.removed === undefined) return;
let item = event.removed.element
if (chart === 'line'||chart === 'bar') {
let label = item.label
let selectedObj = option.legend.selected
if (item.dataType === "key") {
dragChart(item, label, 1)
} else {
if (flag.value) return;
dragValue(item, label, selectedObj)
}
} else if (chart === 'pie') {
let arr = []
xList.forEach(item => {
let obj = {
name: item.label,
value: item.value
}
arr.push(obj)
})
for (const propertyName in option.legend.selected) {
if (propertyName === item.label) {
option.legend.selected[propertyName] = true
}
}
if (item.dataType !== "key") {
option.legend.data.push(item.label)
}
option.series = [
{
type: 'pie',
radius: '50%',
data: arr
}
]
} else if (chart === 'radar') {
let arr = []
xList.forEach(item => {
let obj = {
name: item.label,
value: item.data
}
arr.push(obj)
})
console.log('arr',arr)
for (const propertyName in option.legend.selected) {
if (propertyName === item.label) {
option.legend.selected[propertyName] = true
}
}
if (item.dataType !== "key") {
option.legend.data.push(item.label)
}
option.radar={
indicator:props.radarIndicator
}
option.series = [
{
type: 'radar',
data: arr
}
]
}
props.initCharts()
}
/**
* 左侧区域开始拖拽事件
* @param event 开始拖拽的event事件
*/
const startDrag = (event) => {
startDragType.value = event.item._underlying_vm_.dataType
if (xList.length === 0 && yList.length === 0) {
if (chart === 'line' || chart === 'bar') {
if (startDragType.value === "value") {
flag.value = true
ElMessage({
message: '请先拖动数据类型为key的选项到x轴/y轴.',
type: 'warning',
})
} else {
flag.value = false
}
} else if (chart === 'pie') {
console.log('拖动饼图')
flag.value = false
}else if (chart === 'radar') {
console.log('拖动雷达')
flag.value = false
}
}
}
</script>

View File

@@ -0,0 +1,307 @@
<template>
<div>
<el-row :gutter="6">
<el-col :span="6">
<el-select v-model="echartsValue" filterable placeholder="请选择图形状" style="width: 100%" size="large"
@change="handleChangeEcharts">
<el-option v-for="chartItem in chartType"
:key="chartItem.value"
:label="chartItem.label"
:value="chartItem.value"/>
</el-select>
<!--左侧选项区域-->
<charts-options @editValueFlag="editValueFlag" @editStartDataType="editStartDataType"
:drag-options="ChartsItem" :chart-option="option" :init-charts="initChart"
:x-axis-list="xValueAxis" :y-axis-list="yValueAxis"
:current-chart="echartsValue" :radar-indicator="radarIndicator"/>
</el-col>
<!--X轴区域-->
<el-col :span="9" v-if="echartsValue==='bar'||echartsValue==='line'">
<axis-box :box-name="'X轴'" :drag-list="xValueAxis" :drag-options="ChartsItem" :x-axis-list="xValueAxis"
:y-axis-list="yValueAxis" :flag="valueFlag"
:start-data-type="startDataType" :chart-option="option" :init-charts="initChart"
@getLineChartBasicSettingList="getLineChartBasicSettingList"
@getBarChartBasicSettingList="getBarChartBasicSettingList" :current-chart="echartsValue"/>
</el-col>
<!--Y轴区域-->
<el-col :span="9" v-if="echartsValue==='bar'||echartsValue==='line'">
<axis-box :box-name="'Y轴'" :drag-list="yValueAxis" :drag-options="ChartsItem" :x-axis-list="xValueAxis"
:y-axis-list="yValueAxis" :flag="valueFlag"
:start-data-type="startDataType" :chart-option="option" :init-charts="initChart"
@getLineChartBasicSettingList="getLineChartBasicSettingList"
@getBarChartBasicSettingList="getBarChartBasicSettingList" :current-chart="echartsValue"/>
</el-col>
<el-col :span="9" v-if="echartsValue==='pie'">
<pie-box :drag-list="xValueAxis" :init-charts="initChart" :chart-option="option"/>
</el-col>
<el-col :span="9" v-if="echartsValue==='radar'">
<radar-box :drag-list="xValueAxis" :init-charts="initChart" :chart-option="option"/>
</el-col>
</el-row>
<el-button @click.stop="saveData">保存</el-button>
<el-button v-if="echartsValue==='line'" @click.stop="openAdvancedSettings">高级设置</el-button>
<el-row :gutter="6">
<el-col :span="16">
<div id="container" ref="chart" @click.stop></div>
</el-col>
<!--基础设置-->
<el-col :span="8">
<!-- 折线图基础设置-->
<line-chart-basic-setting v-if="echartsValue==='line'" :basic-list="lineChartBasicSettingList"
:init-charts="initChart"
:chart-option="option"/>
<!-- 柱状图基础设置-->
<bar-chart-basic-setting v-if="echartsValue==='bar'" :basic-list="barChartBasicSettingList"
:init-charts="initChart"
:chart-option="option"/>
<!-- 饼图基础设置-->
<!-- <pie-chart-basic-setting v-if="echartsValue==='pie'"/>-->
</el-col>
</el-row>
<!--高级设置-->
<!-- 折线图高级设置-->
<line-chart-advanced-settings v-if="echartsValue==='line'" ref="advancedSettings" :init-charts="initChart"
:chart-option="option"/>
</div>
</template>
<script setup>
import * as echarts from 'echarts'
import draggable from 'vuedraggable'
import ChartsOptions from "./ChartsOptions.vue";
import AxisBox from "./AxisBox.vue";
import LineChartBasicSetting from "./lineChart/BasicSetting.vue";
import LineChartAdvancedSettings from "./lineChart/AdvancedSettings.vue";
import BarChartBasicSetting from "./barChart/BasicSetting.vue";
// import PieChartBasicSetting from "./pieChart/BasicSetting.vue";
import PieBox from "./pieChart/PieBox.vue";
import RadarBox from "./radarChart/RadarBox.vue";
// import BarChartAdvancedSettings from "./barChart/AdvancedSettings.vue";
const emit = defineEmits(["getFinalInfo"])
const props = defineProps({
info: {
type: Object,
default: {}
},
lineData: {
type: Array,
default: []
},
barData: {
type: Array,
default: []
},
pieData: {
type: Array,
default: []
},
radarData: {
type: Array,
default: []
},
radarIndicator: {
type: Array,
default: []
}
})
//图形: 1:折线图 2.柱状图 3.饼图
const chartType = reactive([
{
value: 'line',
label: '折线图',
},
{
value: 'bar',
label: '柱状图',
},
{
value: 'pie',
label: '饼图',
},
{
value: 'radar',
label: '雷达图',
}
])
//基础设置列表
const lineChartBasicSettingList = ref([])
const barChartBasicSettingList = ref([])
const advancedSettings = ref()
//获取父组件传来的初始数据
const initInfo = reactive(props.info)
//从左侧获取拖动的选项的数据类型
const startDataType = ref()
//标记从左侧拖动选项数据类型是否是value
const valueFlag = ref(false)
//简化代码
let xValueAxis = reactive(initInfo.xValueAxis)
let yValueAxis = reactive(initInfo.yValueAxis)
const line_data = reactive(props.lineData)
const bar_data = reactive(props.barData)
const pie_data = reactive(props.pieData)
const radar_data = reactive(props.radarData)
let option = reactive(initInfo.echartsOptions)
//页面左上角select选择框绑定数据
const echartsValue = ref('line')
//可供拖动的选项列表
const ChartsItem = ref([])
//获取到container容器实例
const chart = ref(null);
//定义echarts实例
let myEcharts = reactive({});
onMounted(() => {
if (ChartsItem.value.length === 0) {
ChartsItem.value = line_data
}
//初始化echarts(不显示图)
let selectLegend = {}
ChartsItem.value.forEach(item => {
if (item.dataType !== 'key') {
selectLegend[item.label] = false
}
})
option.legend.selected = selectLegend
if (echartsValue.value === 'pie'||echartsValue.value === 'radar') {
isShowAxisLine(false)
} else {
isShowAxisLine(true)
}
//加载echarts
initChart();
})
/**
* 修改valueFlag
* @param val 子组件传的动态值
*/
const editValueFlag = (val) => {
valueFlag.value = val
}
/**
* 修改startDataType
* @param str 子组件传的动态值
*/
const editStartDataType = (str) => {
startDataType.value = str
}
/**
* 用于其他组件获取基础设置列表
* @param str 子组件传的动态值
*/
const getLineChartBasicSettingList = (str) => {
lineChartBasicSettingList.value = str
}
/**
* 修改option
* @param str 子组件传的动态值
*/
const getBarChartBasicSettingList = (str) => {
barChartBasicSettingList.value = str
}
/**
* 切换echarts图类型事件
* @param e event事件
*/
const handleChangeEcharts = (e) => {
if (xValueAxis.length !== 0 || yValueAxis.length !== 0) {
xValueAxis.map((item) => {
ChartsItem.value.unshift(item)
option.legend.selected[item.label] = false
})
xValueAxis.splice(0, xValueAxis.length)
yValueAxis.map((item) => {
ChartsItem.value.unshift(item)
option.legend.selected[item.label] = false
})
yValueAxis.splice(0, yValueAxis.length)
option.legend.data.splice(0, option.legend.data.length)
option.series.splice(0, option.series.length)
option.xAxis.name = ''
option.xAxis.data = []
option.xAxis.type = 'category'
option.yAxis.name = ''
option.yAxis.data = []
option.yAxis.type = 'value'
initChart()
}
echartsValue.value = e
if (e === 'line') {
ChartsItem.value = line_data
isShowAxisLine(true)
option.radar={}
} else if (e === 'bar') {
ChartsItem.value = bar_data
isShowAxisLine(true)
option.radar={}
} else if (e === 'pie') {
ChartsItem.value = pie_data
isShowAxisLine(false)
option.radar={}
}else if (e === 'radar') {
ChartsItem.value = radar_data
isShowAxisLine(false)
option.radar.indicator = props.radarIndicator
}
let selectLegend = {}
ChartsItem.value.forEach(item => {
if (item.dataType !== 'key') {
selectLegend[item.label] = false
}
})
option.legend.selected = selectLegend
initChart()
}
/**
* 是否显示x/y轴线
* @param type
*/
const isShowAxisLine = (type) => {
option.xAxis.axisLine.show = type
option.yAxis.axisLine.show = type
if (type === false) {
option.tooltip.trigger = 'item'
} else {
option.tooltip.trigger = 'axis'
}
}
/**
* 初始化echarts实例方法
*/
const initChart = () => {
console.log('initChartoption', option)
//3.初始化container容器
myEcharts = echarts.init(chart.value);
//5.传入数据
myEcharts.setOption(option,true);
//图表大小自适应窗口大小变化
window.onresize = () => {
myEcharts.resize();
}
//点击事件
// myEcharts.on('click', function (params) {
// console.log('dddd点击事件', params);
// });
// myEcharts.restore();
localStorage.removeItem('dragType')
}
/**
* 保存数据
*/
const saveData = () => {
console.log('最终initInfo', initInfo)
emit("getFinalInfo", initInfo)
}
/**
* 打开高级设置弹框
*/
const openAdvancedSettings = () => {
advancedSettings.value.showDrawer()
}
</script>

View File

@@ -0,0 +1,86 @@
<template>
<el-drawer v-model="drawerVisible" direction="rtl">
<template #header>
<h4>高级设置</h4>
</template>
<template #default>
<el-form :model="settingsForm" class="advanced-setting">
<el-form-item label="是否点击图例改变图显示状态">
<el-switch active-text="" inactive-text="" v-model="settingsForm.isClickLegendToShow"
@change="changeIsClickLegend"/>
</el-form-item>
<el-form-item label="是否显示提示框组件">
<el-switch active-text="" inactive-text="" v-model="settingsForm.isShowTooltip"
@change="changeIsShowTooltip"/>
</el-form-item>
</el-form>
</template>
<template #footer>
<el-button @click="cancelSettings">取消</el-button>
<el-button type="primary" @click="confirmSettings">确认</el-button>
</template>
</el-drawer>
</template>
<script setup>
const props = defineProps({
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
})
let option = reactive(props.chartOption)
//高级设置抽屉是否展开
const drawerVisible = ref(false)
//高级设置属性
const settingsForm = reactive({
isClickLegendToShow: option.legend.selectedMode,//打开点击图例改变图显示状态
isShowTooltip: option.tooltip.show//是否显示提示框组件
})
/**
* 打开高级设置弹窗
*/
const showDrawer = () => {
drawerVisible.value = true
}
/**
* 高级设置: 取消按钮
*/
const cancelSettings = () => {
drawerVisible.value = false
}
/**
* 高级设置: 确认按钮
*/
const confirmSettings = () => {
drawerVisible.value = false
props.initCharts()
}
/**
* 高级设置:打开点击图例改变图显示状态
* @param val
*/
const changeIsClickLegend = (val) => {
option.legend.selectedMode = val
}
/**
* 高级设置:是否显示提示框组件
* @param val
*/
const changeIsShowTooltip = (val) => {
option.tooltip.show = val
}
defineExpose({
showDrawer
})
</script>

View File

@@ -0,0 +1,140 @@
<template>
<el-scrollbar height="450px">
<div class="basic-setup" @click.stop>
柱状图基本设置
</div>
<div v-for="(settingItem) in basicList" class="setting" @click.stop>
<div class="setting-title">{{ settingItem.label }}</div>
<div class="setting-item">
<span>显示柱条背景: </span>
<el-switch active-text="" inactive-text="" v-model="settingItem.showBackground"
@change="changeIsShowBackground($event,settingItem)"/>
</div>
<div v-if="settingItem.showBackground!==false">
<div class="setting-item">
<span>柱条描边宽度: </span>
<el-input-number v-model="settingItem.backgroundStyle.borderWidth" :min="0"
@change="changeBorderWidth($event,settingItem)"/>
</div>
<!-- <div class="setting-item" v-if="settingItem.backgroundStyle.borderWidth!==0">-->
<!-- <span>柱条描边颜色: </span>-->
<!-- <el-color-picker v-model="settingItem.backgroundStyle.borderColor"-->
<!-- :color="settingItem.backgroundStyle.borderColor"-->
<!-- @change="changeBorderColor($event,settingItem)"/>-->
<!-- </div>-->
<div class="setting-item" v-if="settingItem.backgroundStyle.borderWidth!==0">
<span>柱条描边类型: </span>
<el-select v-model="settingItem.backgroundStyle.borderType" @change="switchBorderType($event,settingItem)">
<el-option
v-for="symbolItem in borderTypeList"
:key="symbolItem.value"
:label="symbolItem.label"
:value="symbolItem.value"
/>
</el-select>
</div>
</div>
</div>
</el-scrollbar>
</template>
<script setup>
const props = defineProps({
//基础设置列表
basicList: {
type: Array,
default: []
},
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
})
let option = reactive(props.chartOption)
//图形标记列表
const borderTypeList = ref([
{value: 'solid', label: '实线'},
{value: 'dashed', label: '虚线'},
{value: 'dotted', label: '点线'}
])
/**
* 封装基本设置修改echarts属性事件
* @param item 修改的项
* @param type option.series中的属性名
* @param val 获取修改的值
*/
const changeSingleParams = (item, type, val) => {
option.series.forEach((sItem, sIndex) => {
if (sItem.name === item.label) {
getSeriesParams(type, sIndex, val)
}
})
}
/**
* 根据changeSingleParams方法传的动态type,封装数据修改事件
* @param type option.series中的属性名
* @param index 修改某项属性的下标
* @param val 获取修改的值
*/
const getSeriesParams = (type, index, val) => {
let seriesItem = option.series[index]
switch (type) {
case 'showBackground':
return seriesItem.showBackground = val
case 'color':
return seriesItem.backgroundStyle.color = val
case 'borderWidth':
return seriesItem.backgroundStyle.borderWidth = val
case 'borderColor':
return seriesItem.backgroundStyle.borderColor = val
case 'borderType':
return seriesItem.backgroundStyle.borderType = val
}
}
/**
* 基础设置:修改是否显示柱条背景
* @param val 是否显示
* @param item 修改的chart项
*/
const changeIsShowBackground = (val, item) => {
changeSingleParams(item, 'showBackground', val)
props.initCharts()
}
/**
* 基础设置:修改柱条描边宽度
* @param val 宽度
* @param item 修改的chart项
*/
const changeBorderWidth = (val, item) => {
changeSingleParams(item, 'borderWidth', val)
props.initCharts()
}
/**
* 基础设置:修改柱条的描边颜色
* @param val 颜色
* @param item 修改的chart项
*/
const changeBorderColor = (val, item) => {
changeSingleParams(item, 'borderColor', val)
props.initCharts()
}
/**
* 基础设置:修改柱条的描边类型
* @param val 类型
* @param item 修改的chart项
*/
const switchBorderType = (val, item) => {
changeSingleParams(item, 'borderType', val)
props.initCharts()
}
</script>

View File

@@ -0,0 +1,86 @@
<template>
<el-drawer v-model="drawerVisible" direction="rtl">
<template #header>
<h4>高级设置</h4>
</template>
<template #default>
<el-form :model="settingsForm" class="advanced-setting">
<el-form-item label="是否点击图例改变图显示状态">
<el-switch active-text="" inactive-text="" v-model="settingsForm.isClickLegendToShow"
@change="changeIsClickLegend"/>
</el-form-item>
<el-form-item label="是否显示提示框组件">
<el-switch active-text="" inactive-text="" v-model="settingsForm.isShowTooltip"
@change="changeIsShowTooltip"/>
</el-form-item>
</el-form>
</template>
<template #footer>
<el-button @click="cancelSettings">取消</el-button>
<el-button type="primary" @click="confirmSettings">确认</el-button>
</template>
</el-drawer>
</template>
<script setup>
const props = defineProps({
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
})
let option = reactive(props.chartOption)
//高级设置抽屉是否展开
const drawerVisible = ref(false)
//高级设置属性
const settingsForm = reactive({
isClickLegendToShow: option.legend.selectedMode,//打开点击图例改变图显示状态
isShowTooltip: option.tooltip.show//是否显示提示框组件
})
/**
* 打开高级设置弹窗
*/
const showDrawer = () => {
drawerVisible.value = true
}
/**
* 高级设置: 取消按钮
*/
const cancelSettings = () => {
drawerVisible.value = false
}
/**
* 高级设置: 确认按钮
*/
const confirmSettings = () => {
drawerVisible.value = false
props.initCharts()
}
/**
* 高级设置:打开点击图例改变图显示状态
* @param val
*/
const changeIsClickLegend = (val) => {
option.legend.selectedMode = val
}
/**
* 高级设置:是否显示提示框组件
* @param val
*/
const changeIsShowTooltip = (val) => {
option.tooltip.show = val
}
defineExpose({
showDrawer
})
</script>

View File

@@ -0,0 +1,160 @@
<template>
<el-scrollbar height="450px">
<div class="basic-setup" @click.stop>
折线图基本设置
</div>
<div v-for="(settingItem) in basicList" class="setting" @click.stop>
<div class="setting-title">{{ settingItem.label }}</div>
<!-- <div class="setting-item">-->
<!-- <span>图形: </span>-->
<!-- <el-select v-model="settingItem.type" @change="switchChart($event,settingItem)">-->
<!-- <el-option-->
<!-- v-for="chartItem in [{value: 'line',label: '折线图'},{value: 'bar',label: '柱状图'}]"-->
<!-- :key="chartItem.value"-->
<!-- :label="chartItem.label"-->
<!-- :value="chartItem.value"-->
<!-- />-->
<!-- </el-select>-->
<!-- </div>-->
<div class="setting-item">
<span>显示标记: </span>
<el-switch active-text="" inactive-text="" v-model="settingItem.showSymbol"
@change="changeIsShowSymbol($event,settingItem)"/>
</div>
<div class="setting-item" v-if="settingItem.showSymbol===true">
<span>标记: </span>
<el-select v-model="settingItem.symbol" @change="switchSymbol($event,settingItem)">
<el-option
v-for="symbolItem in symbolList"
:key="symbolItem.value"
:label="symbolItem.label"
:value="symbolItem.value"
/>
</el-select>
</div>
<div class="setting-item" v-if="settingItem.showSymbol===true">
<span>标记大小: </span>
<el-input-number v-model="settingItem.symbolSize" :min="1" @change="changeSymbolSize($event,settingItem)"/>
</div>
<div class="setting-item">
<span>阴影模糊大小: </span>
<el-input-number v-model="settingItem.lineStyle.shadowBlur" :min="0" @change="changeShadowBlur($event,settingItem)"/>
</div>
</div>
</el-scrollbar>
</template>
<script setup>
const props = defineProps({
//基础设置列表
basicList: {
type: Array,
default: []
},
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
})
//图形标记列表
const symbolList = ref([
{value: 'none', label: '不显示标记'},
{value: 'circle', label: '圆形'},
{value: 'rect', label: '矩形'},
{value: 'triangle', label: '三角形'},
{value: 'diamond', label: '钻石形'},
{value: 'roundRect', label: '圆角矩形'},
{value: 'pin', label: '圆钉形'},
{value: 'arrow', label: '箭头形'},
])
let option = reactive(props.chartOption)
/**
* 封装基本设置修改echarts属性事件
* @param item 修改的项
* @param type option.series中的属性名
* @param val 获取修改的值
*/
const changeSingleParams = (item, type, val) => {
option.series.forEach((sItem, sIndex) => {
if (sItem.name === item.label) {
getSeriesParams(type, sIndex, val)
}
})
}
/**
* 根据changeSingleParams方法传的动态type,封装数据修改事件
* @param type option.series中的属性名
* @param index 修改某项属性的下标
* @param val 获取修改的值
*/
const getSeriesParams = (type, index, val) => {
let seriesItem = option.series[index]
switch (type) {
case 'type':
return seriesItem.type = val
case 'showSymbol':
return seriesItem.showSymbol = val
case 'symbol':
return seriesItem.symbol = val
case 'symbolSize':
return seriesItem.symbolSize = val
case 'shadowBlur':
return seriesItem.lineStyle.shadowBlur = val
}
}
/**
* 基础设置:是否显示标记
* @param val 修改的标记大小
* @param item 修改的chart项
*/
const changeIsShowSymbol = (val, item) => {
changeSingleParams(item, 'showSymbol', val)
props.initCharts()
}
/**
* 基础设置:切换chart的形状
* @param val 修改的标记大小
* @param item 修改的chart项
*/
const switchChart = (val, item) => {
changeSingleParams(item, 'type', val)
props.initCharts()
}
/**
* 基础设置:修改标记
* @param val 修改的标记大小
* @param item 修改的chart项
*/
const switchSymbol = (val, item) => {
changeSingleParams(item, 'symbol', val)
props.initCharts()
}
/**
* 基础设置:修改标记大小
* @param val 修改的标记大小
* @param item 修改的chart项
*/
const changeSymbolSize = (val, item) => {
changeSingleParams(item, 'symbolSize', val)
props.initCharts()
}
/**
* 基础设置:修改图形阴影的模糊大小
* @param val 修改的阴影的模糊大小
* @param item 修改的chart项
*/
const changeShadowBlur = (val, item) => {
changeSingleParams(item, 'shadowBlur', val)
props.initCharts()
}
</script>

View File

@@ -0,0 +1,17 @@
<template>
<el-scrollbar height="450px">
<div class="basic-setup" @click.stop>
饼图基本设置
</div>
</el-scrollbar>
</template>
<script>
export default {
name: "BasicSetting"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,116 @@
<template>
<el-card class="box-card box-card-h">
<el-row justify="space-between" class="x-y-axis">
<el-text>饼图数据项</el-text>
<el-tooltip
effect="dark"
:content="'数据类型必须是数字!'"
placement="bottom"
>
<el-icon>
<Warning/>
</el-icon>
</el-tooltip>
</el-row>
<div class="drag-block">
<draggable
class="list-group"
:list="dragList"
itemKey="id"
group="people"
@start="startDrag"
@change="dragChartItem"
>
<template #item="{ element,index }">
<div>
<el-card shadow="hover" class="cards x-y-cards">
<el-col :span="8">
<div>{{ element.label }}</div>
</el-col>
<el-col :span="8">
</el-col>
<el-col :span="8">
<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>
</template>
<script setup>
import draggable from 'vuedraggable'
const props = defineProps({
//用于拖拽区域存放选项列表
dragList: {
type: Array,
default: []
},
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
})
let option = reactive(props.chartOption)
/**
* 开始拖拽事件
* @param event event事件
*/
const startDrag = (event) => {
}
/**
* 从X轴/Y轴区域移动选项到左/右侧结束事件
* @param event event事件
*/
const dragChartItem = (event) => {
console.log('dragChartItem',event)
if (event.removed === undefined) return;
let item = event.removed.element
let label = item.label
dragTypeToValue(label)
props.initCharts()
// localStorage.removeItem('dragType')
}
/**
* 拖拽类型为value的选项事件
* @param label 选项名
*/
const dragTypeToValue = (label) => {
console.log('dragTypeToValue',label,option)
//删除选中选项的图例
const legendIndex = option.legend.data.findIndex(object => object === label);
option.legend.data.splice(legendIndex, 1)
//删除echarts配置项series中符合该拖拽选项的item
const objectIndex = option.series[0].data.findIndex(object => object.name === label);
option.legend.selected[label] = false
option.series[0].data.splice(objectIndex, 1)
if(option.series[0].data.length===0){
option.series.splice(0,1)
}
// clearBasicSetting()
}
const handleCancelAxis = (element, index) => {
console.log('拖出xxx')
dragTypeToValue(element.label)
props.initCharts()
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,110 @@
<template>
<el-card class="box-card box-card-h">
<el-row justify="space-between" class="x-y-axis">
<el-text>雷达图数据项</el-text>
<el-tooltip
effect="dark"
:content="'数据类型必须是数字!'"
placement="bottom"
>
<el-icon>
<Warning/>
</el-icon>
</el-tooltip>
</el-row>
<div class="drag-block">
<draggable
class="list-group"
:list="dragList"
itemKey="id"
group="people"
@start="startDrag"
@change="dragChartItem"
>
<template #item="{ element,index }">
<div>
<el-card shadow="hover" class="cards x-y-cards">
<el-col :span="8">
<div>{{ element.label }}</div>
</el-col>
<el-col :span="8">
</el-col>
<el-col :span="8">
<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>
</template>
<script setup>
import draggable from 'vuedraggable'
const props = defineProps({
//用于拖拽区域存放选项列表
dragList: {
type: Array,
default: []
},
//初始化加载echarts函数
initCharts: {
type: Function,
default: null
},
//echarts的配置属性
chartOption: {
type: Array,
default: []
},
})
let option = reactive(props.chartOption)
/**
* 开始拖拽事件
* @param event event事件
*/
const startDrag = (event) => {
}
/**
* 从X轴/Y轴区域移动选项到左/右侧结束事件
* @param event event事件
*/
const dragChartItem = (event) => {
console.log('dragChartItem',event)
if (event.removed === undefined) return;
let item = event.removed.element
let label = item.label
dragTypeToValue(label)
props.initCharts()
// localStorage.removeItem('dragType')
}
/**
* 拖拽类型为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[0].data.findIndex(object => object.name === label);
option.legend.selected[label] = false
option.series[0].data.splice(objectIndex, 1)
// clearBasicSetting()
if(option.series[0].data.length===0){
option.series.splice(0,1)
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,233 @@
<template>
<div>
<EchartsEditor :info="initInfo" :line-data="lineChartsItem" :bar-data="barChartsItem" :pie-data="pieChartsItem"
:radar-data="radarChartsItem" :radar-indicator="indicator" @getFinalInfo="getFinalInfo"/>
</div>
</template>
<script setup>
import EchartsEditor from "./components/EchartsEditor.vue";
//入参
const lineChartsItem = ref([
{
id: 1,
unit: '年份',
type: '',
dataType: 'key',
color: '',
label: '年份',
symbol: "",
symbolSize: 0,
showSymbol: false,
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1
},
data: ['2013', '2014', '2015', '2016', '2017', '2018']
},
{
id: 2,
unit: '年销量',
type: 'line',
dataType: 'value',
color: '#9a60b4',//图形颜色
label: '华北',
symbol: "triangle",//标记的图形circle:圆形,rect:矩形,triangle:三角形,diamond:钻石形,roundRect:圆角矩形,pin:圆钉形,arrow:箭头形,none:不显示标记
symbolSize: 8,//标记的大小
showSymbol: true,//是否显示标记,如果 false 则只有在 tooltip hover 的时候显示。
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1//图形透明度
},
data: [40, 80, 20, 120, 140, 50]
},
{
id: 3,
unit: '年销量',
type: 'line',
dataType: 'value',
color: '#3ba272',
label: '华东',
symbol: "circle",
symbolSize: 8,
showSymbol: true,
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1
},
data: [140, 180, 120, 40, 50, 150]
},
{
id: 4,
unit: '年销量',
type: 'line',
dataType: 'value',
color: '#5470c6',
label: '华南',
symbol: "rect",
symbolSize: 8,
showSymbol: true,
lineStyle: {
shadowColor: '',//阴影颜色
shadowBlur: 0,//图形阴影的模糊大小
opacity: 1
},
data: [110, 143, 68, 90, 120, 130]
}
])
const barChartsItem = ref([
{
id: 1,
unit: '年份',
type: '',
dataType: 'key',
color: '',
label: '年份',
showBackground: false,
backgroundStyle: {
color: '',
borderWidth: 0,
borderColor: '',
borderType: 'solid',
},
data: ['2013', '2014', '2015', '2016', '2017', '2018']
},
{
id: 2,
unit: '销售金额',
type: 'bar',
dataType: 'value',
color: '#9a60b4',//图形颜色
label: '王五',
showBackground: true,//是否显示柱条的背景色
backgroundStyle: {
color: '#e5e2e2',//柱条的颜色
borderWidth: 0,//柱条的描边宽度,默认不描边。
borderColor: '#000',//柱条的描边颜色
borderType: 'dotted',//柱条的描边类型,默认为实线,支持 'dashed', 'dotted'
},
data: [40, 80, 20, 120, 140, 50]
},
{
id: 3,
unit: '销售金额',
type: 'bar',
dataType: 'value',
color: '#3ba272',
label: '李四',
showBackground: true,
backgroundStyle: {
color: '#e5e2e2',
borderWidth: 0,
borderColor: '#000',
borderType: 'dashed',
},
data: [140, 180, 120, 40, 50, 150]
},
{
id: 4,
unit: '销售金额',
type: 'bar',
dataType: 'value',
color: '#2644a4',
label: '张三',
showBackground: true,
backgroundStyle: {
color: '#e5e2e2',
borderWidth: 0,
borderColor: '#000',
borderType: 'solid',
},
data: [110, 143, 68, 90, 120, 130]
}
])
const pieChartsItem = ref([
{id: 1, label: '京东', dataType: 'value', value: 335},
{id: 2, label: '菜鸟', dataType: 'value', value: 310},
{id: 3, label: '总部', dataType: 'value', value: 234},
{id: 4, label: '小电商', dataType: 'value', value: 135},
])
const radarChartsItem = ref([
{label: 'Allocated Budget', dataType: 'value', data: [4200, 3000, 20000, 35000, 50000, 18000]},
{label: 'Actual Spending', dataType: 'value', data: [5000, 14000, 28000, 26000, 42000, 21000]},
])
//定义好echarts的配置数据
let initInfo = reactive({
xValueAxis: [],
yValueAxis: [],
//echarts配置数据
echartsOptions: {
//图例
legend: {
data: [],
selected: {},
selectedMode: false
},
//离容器四侧的距离
grid: {
left: 40, // 左边距
right: 60, // 右边距
top: 40, // 顶边距
bottom: 20, // 底边距
// containLabel: true,
},
//提示框组件
tooltip: {
show: true,
trigger: 'axis'
},
//工具栏
// toolbox: {
// feature: {
// //重置按钮显示
// restore: {
// show: true,
// title: '重置'
// }
// }
// },
//X轴
xAxis: {
name: '',
type: 'category',
data: [],
axisLine: {
show: true
}
},
//Y轴
yAxis: {
name: '',
type: 'value',
data: [],
axisLine: {
show: true
}
},
radar: {
// shape: 'circle',
},
//配置项
series: []
}
})
const indicator= ref([
{ name: 'Sales', max: 6500 },
{ name: 'Administration', max: 16000 },
{ name: 'Information Technology', max: 30000 },
{ name: 'Customer Support', max: 38000 },
{ name: 'Development', max: 52000 },
{ name: 'Marketing', max: 25000 }
])
//获取到拖拽后的数据
const getFinalInfo = (val) => {
// console.log('父组件获取最终数据', val)
if (val !== undefined) {
initInfo = val
}
}
getFinalInfo()
</script>