dataease/frontend/src/views/chart/view/ChartEdit.vue

529 lines
17 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>
<!--TODO 慢慢完善写个DEMO-->
<el-row style="height: 100%;overflow-y: hidden;width: 100%;">
<span v-show="false">{{ tableId }}</span>
<span v-show="false">{{ sceneId }}</span>
<span v-show="false">{{ vId }}</span>
<el-row style="height: 40px;" class="padding-lr">
<span style="line-height: 40px;">{{ view.name }}</span>
<span style="float: right;line-height: 40px;">
<el-button size="mini" @click="closeEdit">
{{ $t('chart.close') }}
</el-button>
<!-- <el-button type="primary" size="mini" @click="save">-->
<!-- {{ $t('chart.confirm') }}-->
<!-- </el-button>-->
</span>
</el-row>
<el-row style="display: flex;height: 100%">
<el-col
style="height: 100%;width: 20%;min-width: 180px;max-width:220px;border: 1px solid #E6E6E6;border-left: 0 solid;"
>
<div style="height: 45%;border-bottom: 1px solid #E6E6E6;" class="padding-lr">
<span>{{ $t('chart.dimension') }}</span>
<draggable
v-model="dimension"
:options="{group:{name: 'dimension',pull:'clone'},sort: true}"
animation="300"
:move="onMove"
style="height: 90%;overflow:auto"
@end="end1"
@start="start1"
>
<transition-group>
<span v-for="item in dimension" :key="item.id" class="item">{{ item.name }}</span>
</transition-group>
</draggable>
</div>
<div style="height: 45%;" class="padding-lr">
<span>{{ $t('chart.quota') }}</span>
<draggable
v-model="quota"
:options="{group:{name: 'quota',pull:'clone'},sort: true}"
animation="300"
:move="onMove"
style="height: 90%;overflow:auto"
@end="end1"
@start="start1"
>
<transition-group>
<span v-for="item in quota" :key="item.id" class="item">{{ item.name }}</span>
</transition-group>
</draggable>
</div>
</el-col>
<el-col
style="height: 100%;width: 25%;min-width: 200px;max-width:240px;border: 1px solid #E6E6E6;border-left: 0 solid;"
>
<div style="border-bottom: 1px solid #E6E6E6;overflow-y:hidden;" class="padding-lr">
<el-row>
<span>{{ $t('chart.title') }}</span>
<el-button style="float: right;padding: 0;margin: 8px 0 0 0;font-size: 12px;" type="text" @click="save">{{ $t('chart.confirm') }}</el-button>
</el-row>
<el-form>
<el-form-item class="form-item">
<el-input
v-model="view.title"
size="mini"
:placeholder="$t('chart.title')"
prefix-icon="el-icon-search"
clearable
/>
</el-form-item>
</el-form>
</div>
<div style="height: 25%;overflow:auto" class="padding-lr">
<span>{{ $t('chart.chart_type') }}</span>
<el-row>
<div class="chart-type">
<!--TODO 这里要替换好看点的图标UI标签可以重新定义-->
<el-radio-group
v-model="view.type"
style="width: 100%"
@change="save"
>
<div style="width: 100%;display: flex;display: -webkit-flex;justify-content: space-between;flex-direction: row;flex-wrap: wrap;">
<el-radio value="bar" label="bar"><svg-icon icon-class="bar" class="chart-icon" /></el-radio>
<el-radio value="bar-stack" label="bar-stack"><svg-icon icon-class="bar-stack" class="chart-icon" /></el-radio>
<el-radio value="bar-horizontal" label="bar-horizontal"><svg-icon icon-class="bar-horizontal" class="chart-icon" /></el-radio>
<el-radio value="bar-horizontal-stack" label="bar-horizontal-stack"><svg-icon icon-class="bar-stack-horizontal" class="chart-icon" /></el-radio>
<el-radio value="line" label="line"><svg-icon icon-class="line" class="chart-icon" /></el-radio>
</div>
<div style="width: 100%;display: flex;display: -webkit-flex;justify-content: space-between;flex-direction: row;flex-wrap: wrap;">
<el-radio value="line-stack" label="line-stack"><svg-icon icon-class="line-stack" class="chart-icon" /></el-radio>
<el-radio value="pie" label="pie"><svg-icon icon-class="pie" class="chart-icon" /></el-radio>
<el-radio value="funnel" label="funnel"><svg-icon icon-class="funnel" class="chart-icon" /></el-radio>
<el-radio value="radar" label="radar"><svg-icon icon-class="radar" class="chart-icon" /></el-radio>
<el-radio value="" label="" disabled class="disabled-none-cursor"><svg-icon icon-class="" class="chart-icon" /></el-radio>
</div>
</el-radio-group>
</div>
</el-row>
</div>
<div style="height: 45%;overflow:auto;border-top: 1px solid #e6e6e6">
<el-tabs type="card" :stretch="true" class="tab-header">
<el-tab-pane :label="$t('chart.shape_attr')" class="padding-lr">
<color-selector class="attr-selector" :chart="chart" @onColorChange="onColorChange" />
<size-selector class="attr-selector" :chart="chart" @onSizeChange="onSizeChange" />
</el-tab-pane>
<el-tab-pane :label="$t('chart.module_style')" class="padding-lr">
<title-selector class="attr-selector" :chart="chart" @onTextChange="onTextChange" />
<legend-selector class="attr-selector" :chart="chart" @onLegendChange="onLegendChange" />
</el-tab-pane>
</el-tabs>
</div>
<div style="height: 30%;overflow:auto;border-top: 1px solid #e6e6e6" class="padding-lr">
<span>{{ $t('chart.result_filter') }}</span>
<div>TODO</div>
</div>
</el-col>
<el-col style="height: 100%;min-width: 500px;border-top: 1px solid #E6E6E6;">
<el-row style="width: 100%;height: 100%;" class="padding-lr">
<el-row style="margin-top: 10px;">
<el-row style="display:flex;height: 32px;">
<span style="line-height: 32px;width: 60px;text-align: right;">{{ $t('chart.dimension') }}</span>
<draggable
v-model="view.xaxis"
group="dimension"
animation="300"
:move="onMove"
style="width:100%;height: 100%;margin:0 10px;border-radius: 4px;border: 1px solid #DCDFE6;overflow-x: auto;display: flex;align-items: center;"
@end="end2"
>
<transition-group class="draggable-group">
<dimension-item v-for="(item) in view.xaxis" :key="item.id" :item="item" />
</transition-group>
</draggable>
</el-row>
<el-row style="display:flex;height: 32px;margin-top: 10px;">
<span style="line-height: 32px;width: 60px;text-align: right;">{{ $t('chart.quota') }}</span>
<draggable
v-model="view.yaxis"
group="quota"
animation="300"
:move="onMove"
style="width:100%;height: 100%;margin:0 10px;border-radius: 4px;border: 1px solid #DCDFE6;overflow-x: auto;display: flex;align-items: center;"
@end="end2"
>
<transition-group class="draggable-group">
<quota-item v-for="(item) in view.yaxis" :key="item.id" :item="item" @onQuotaItemChange="quotaItemChange" />
</transition-group>
</draggable>
</el-row>
</el-row>
<chart-component :chart-id="chart.id" :chart="chart" style="height: 80%" />
</el-row>
</el-col>
</el-row>
</el-row>
</template>
<script>
import { post } from '@/api/dataset/dataset'
import draggable from 'vuedraggable'
import DimensionItem from '../components/DimensionItem'
import QuotaItem from '../components/QuotaItem'
import ChartComponent from '../components/ChartComponent'
// shape attr,component style
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE, DEFAULT_TITLE_STYLE, DEFAULT_LEGEND_STYLE } from '../chart/chart'
import ColorSelector from '../components/shape_attr/ColorSelector'
import SizeSelector from '../components/shape_attr/SizeSelector'
import TitleSelector from '../components/component_style/TitleSelector'
import LegendSelector from '../components/component_style/LegendSelector'
export default {
name: 'ChartEdit',
components: { LegendSelector, TitleSelector, SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
data() {
return {
table: {},
dimension: [],
quota: [],
view: {
xaxis: [],
yaxis: [],
show: true,
type: 'bar',
title: '',
customAttr: {
color: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE
},
customStyle: {
text: DEFAULT_TITLE_STYLE,
legend: DEFAULT_LEGEND_STYLE
}
},
// 定义要被拖拽对象的数组
arr1: [
{ id: 1, name: 'id' },
{ id: 2, name: '名称' },
{ id: 3, name: '类型' },
{ id: 5, name: '状态' },
{ id: 4, name: '指标指标指标' }
],
arr2: [
{ id: 11, name: '容量' }
],
moveId: -1,
chart: {
id: 'echart'
}
}
},
computed: {
tableId() {
// console.log(this.$store.state.chart.tableId);
this.initTableData(this.$store.state.chart.tableId)
return this.$store.state.chart.tableId
},
sceneId() {
// console.log(this.$store.state.chart.sceneId);
return this.$store.state.chart.sceneId
},
vId() {
// console.log(this.$store.state.chart.viewId);
this.getData(this.$store.state.chart.viewId)
return this.$store.state.chart.viewId
}
},
watch: {
},
created() {
// this.get(this.$store.state.chart.viewId);
},
mounted() {
// this.get(this.$store.state.chart.viewId);
this.getData(this.$store.state.chart.viewId)
// this.myEcharts();
},
activated() {
},
methods: {
initTableData(id) {
if (id != null) {
post('/dataset/table/get/' + id, null).then(response => {
this.table = response.data
this.initTableField(id)
})
}
},
initTableField(id) {
post('/dataset/table/getFieldsFromDE', this.table).then(response => {
this.dimension = response.data.dimension
this.quota = response.data.quota
})
},
save() {
const view = JSON.parse(JSON.stringify(this.view))
view.id = this.view.id
view.sceneId = this.sceneId
view.name = this.table.name
view.tableId = this.$store.state.chart.tableId
view.xaxis.forEach(function(ele) {
if (!ele.summary || ele.summary === '') {
ele.summary = 'sum'
}
})
view.yaxis.forEach(function(ele) {
if (!ele.summary || ele.summary === '') {
ele.summary = 'sum'
}
})
if (view.type.startsWith('pie') || view.type.startsWith('funnel')) {
if (view.yaxis.length > 1) {
view.yaxis.splice(1, view.yaxis.length)
}
}
view.xaxis = JSON.stringify(view.xaxis)
view.yaxis = JSON.stringify(view.yaxis)
view.customAttr = JSON.stringify(view.customAttr)
view.customStyle = JSON.stringify(view.customStyle)
post('/chart/view/save', view).then(response => {
// this.get(response.data.id);
this.getData(response.data.id)
this.$store.dispatch('chart/setChartSceneData', null)
this.$store.dispatch('chart/setChartSceneData', this.sceneId)
})
},
closeEdit() {
this.$emit('switchComponent', { name: '' })
},
getData(id) {
if (id) {
post('/chart/view/getData/' + id, null).then(response => {
this.view = JSON.parse(JSON.stringify(response.data))
this.view.xaxis = this.view.xaxis ? JSON.parse(this.view.xaxis) : []
this.view.yaxis = this.view.yaxis ? JSON.parse(this.view.yaxis) : []
this.view.customAttr = this.view.customAttr ? JSON.parse(this.view.customAttr) : {}
this.view.customStyle = this.view.customStyle ? JSON.parse(this.view.customStyle) : {}
// 将视图传入echart组件
this.chart = response.data
})
} else {
this.view = {}
}
},
// 左边往右边拖动时的事件
start1(e) {
console.log(e)
e.clone.className = 'item-on-move'
e.item.className = 'item-on-move'
},
end1(e) {
console.log(e)
e.clone.className = 'item'
e.item.className = 'item'
this.refuseMove(e)
this.removeCheckedKey(e)
this.save()
},
// 右边往左边拖动时的事件
start2(e) {
console.log(e)
},
end2(e) {
console.log(e)
this.removeDuplicateKey(e)
this.save()
},
removeCheckedKey(e) {
const that = this
const xItems = this.view.xaxis.filter(function(m) {
return m.id === that.moveId
})
const yItems = this.view.yaxis.filter(function(m) {
return m.id === that.moveId
})
if (xItems && xItems.length > 1) {
this.view.xaxis.splice(e.newDraggableIndex, 1)
}
if (yItems && yItems.length > 1) {
this.view.yaxis.splice(e.newDraggableIndex, 1)
}
},
refuseMove(e) {
const that = this
const xItems = this.dimension.filter(function(m) {
return m.id === that.moveId
})
const yItems = this.quota.filter(function(m) {
return m.id === that.moveId
})
if (xItems && xItems.length > 1) {
this.dimension.splice(e.newDraggableIndex, 1)
}
if (yItems && yItems.length > 1) {
this.quota.splice(e.newDraggableIndex, 1)
}
},
removeDuplicateKey(e) {
const that = this
const xItems = this.dimension.filter(function(m) {
return m.id === that.moveId
})
const yItems = this.quota.filter(function(m) {
return m.id === that.moveId
})
if (xItems && xItems.length > 1) {
this.dimension.splice(e.newDraggableIndex, 1)
}
if (yItems && yItems.length > 1) {
this.quota.splice(e.newDraggableIndex, 1)
}
},
// move回调方法
onMove(e, originalEvent) {
console.log(e)
this.moveId = e.draggedContext.element.id
// //不允许停靠
// if (e.relatedContext.element.id == 1) return false;
// //不允许拖拽
// if (e.draggedContext.element.id == 4) return false;
// if (e.draggedContext.element.id == 11) return false;
return true
},
quotaItemChange(item) {
// 更新item
// this.view.yaxis.forEach(function(ele) {
// if (ele.id === item.id) {
// ele.summary = item.summary
// }
// })
this.save()
},
onColorChange(val) {
this.view.customAttr.color = val
this.save()
},
onSizeChange(val) {
this.view.customAttr.size = val
this.save()
},
onTextChange(val) {
this.view.customStyle.text = val
this.save()
},
onLegendChange(val) {
this.view.customStyle.legend = val
this.save()
}
}
}
</script>
<style scoped lang="scss">
.padding-lr {
padding: 0 6px;
}
.itxst {
margin: 10px;
text-align: left;
}
.col {
width: 40%;
flex: 1;
padding: 10px;
border: solid 1px #eee;
border-radius: 5px;
float: left;
}
.col + .col {
margin-left: 10px;
}
.item {
padding: 2px 10px;
margin: 2px 2px 0 2px;
border: solid 1px #eee;
text-align: left;
color: #606266;
background-color: rgba(35,46,64,.05);
display: block;
}
.item-on-move {
padding: 2px 10px;
margin: 2px 2px 0 2px;
border: solid 1px #eee;
text-align: left;
color: #606266;
background-color: rgba(35,46,64,.05);
}
.item + .item {
margin-top: 2px;
}
.item:hover {
color: #1890ff;
background: #e8f4ff;
border-color: #a3d3ff;
cursor: pointer;
}
.el-form-item {
margin-bottom: 0;
}
span {
font-size: 12px;
}
.tab-header>>>.el-tabs__item{
font-size: 12px;
}
.draggable-group {
display: inline-block;
width: 100%;
height: calc(100% - 6px);
}
.chart-type{
padding: 4px;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.chart-icon{
width: 20px;
height: 20px;
}
.chart-type>>>.el-radio__input{
display: none;
}
.el-radio{
margin:6px;
}
.el-radio>>>.el-radio__label{
padding-left: 0;
}
.attr-selector{
margin: 2px 0;
}
.disabled-none-cursor{
cursor: not-allowed;
pointer-events:none;
}
</style>