Commit 7d3387cb by yuwei

项目初始化

parent b8f29b48
......@@ -32,6 +32,5 @@ public class ChartDto implements Serializable {
@ApiModelProperty(value = "图表缩略图(图片base64)")
private String chartThumbnail;
@ApiModelProperty(value = "图表配置")
@Valid
private ChartConfig chartConfig;
private String chartConfig;
}
package cn.datax.service.data.visual.api.entity;
import cn.datax.common.base.DataScopeBaseEntity;
import cn.datax.service.data.visual.api.dto.ChartConfig;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
......@@ -38,6 +36,6 @@ public class ChartEntity extends DataScopeBaseEntity {
/**
* 图表配置
*/
@TableField(value = "chart_json", typeHandler = JacksonTypeHandler.class)
private ChartConfig chartConfig;
@TableField(value = "chart_json")
private String chartConfig;
}
package cn.datax.service.data.visual.api.vo;
import cn.datax.service.data.visual.api.dto.ChartConfig;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
......@@ -27,5 +26,5 @@ public class ChartVo implements Serializable {
private String remark;
private String chartName;
private String chartThumbnail;
private ChartConfig chartConfig;
private String chartConfig;
}
......@@ -17,7 +17,7 @@
</resultMap>
<resultMap id="ExtendResultMap" type="cn.datax.service.data.visual.api.entity.ChartEntity" extends="BaseResultMap">
<result column="chart_json" property="chartConfig" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
<result column="chart_json" property="chartConfig" />
</resultMap>
<!-- 通用查询结果列 -->
......
......@@ -32,7 +32,7 @@
"sql-formatter": "^2.3.3",
"vue": "2.6.10",
"vue-codemirror": "^4.0.6",
"vue-grid-layout": "^2.3.8",
"vue-grid-layout": "^2.3.11",
"vue-router": "3.0.6",
"vuedraggable": "^2.24.0",
"vuex": "3.1.0"
......
......@@ -76,6 +76,7 @@ export default {
},
rowPaths() {
const _paths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
return _paths
......@@ -389,6 +390,7 @@ export default {
handleCalcData() {
if (!this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -428,7 +430,7 @@ export default {
.flat()
)
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -444,7 +446,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -41,6 +41,7 @@
:is-mirrored="false"
:vertical-compact="true"
:use-css-transforms="true"
:pane-container="false"
:margin="[10, 10]"
style="border: 1px dashed #999; height: 100%; overflow-x: hidden; overflow-y: auto;"
>
......@@ -63,7 +64,7 @@
<i class="el-icon-delete" @click="handleDeleteChart(item.i)" />
</div>
</div>
<chart-panel v-if="getChartItem(item.i).visible" :key="item.i" :ref="`charts${item.i}`" :chart-schema="getChartItem(item.i).chartConfig" :chart-data="getChartItem(item.i).data" :chart-style="{height: `${item.h * 30 + 10 * (item.h - 1) - 60}px`}" />
<chart-panel v-if="getChartItem(item.i).visible" :key="item.i" :ref="`charts${item.i}`" :chart-schema="getChartItem(item.i).chartSchema" :chart-data="getChartItem(item.i).data" :chart-style="{height: `${item.h * 30 + 10 * (item.h - 1) - 60}px`}" />
<div v-else :style="{height: `${item.h * 30 + 10 * (item.h - 1) - 60}px`}"></div>
</el-card>
</grid-item>
......@@ -136,13 +137,18 @@ export default {
},
parserChart(chart) {
this.$set(chart, 'loading', true)
dataParser(chart.chartConfig).then(response => {
if (response.success) {
this.$set(chart, 'visible', true)
this.$set(chart, 'loading', false)
this.$set(chart, 'data', response.data.data)
}
})
if (chart.chartConfig) {
dataParser(JSON.parse(chart.chartConfig)).then(response => {
if (response.success) {
this.$set(chart, 'data', response.data.data)
this.$set(chart, 'chartSchema', JSON.parse(chart.chartConfig))
this.$set(chart, 'loading', false)
this.$set(chart, 'visible', true)
}
})
} else {
this.$set(chart, 'loading', false)
}
},
getChartItem(id) {
return this.charts.find(chart => chart.id === id)
......@@ -220,6 +226,7 @@ export default {
window.close()
},
handleResize(i, newH, newW, newHPx, newWPx) {
console.log('handleResize', i)
if (this.charts.find(chart => chart.id === i).visible) {
this.$refs[`charts${i}`][0].$children[0].$emit('resized')
}
......
......@@ -31,7 +31,7 @@
<span>{{ getChartItem(item.i).chartName }}</span>
</div>
</div>
<chart-panel v-if="getChartItem(item.i).visible" :key="item.i" :ref="`charts${item.i}`" :chart-schema="getChartItem(item.i).chartConfig" :chart-data="getChartItem(item.i).data" :chart-style="{height: `${item.h * 30 + 10 * (item.h - 1) - 60}px`}" />
<chart-panel v-if="getChartItem(item.i).visible" :key="item.i" :ref="`charts${item.i}`" :chart-schema="getChartItem(item.i).chartSchema" :chart-data="getChartItem(item.i).data" :chart-style="{height: `${item.h * 30 + 10 * (item.h - 1) - 60}px`}" />
<div v-else :style="{height: `${item.h * 30 + 10 * (item.h - 1) - 60}px`}"></div>
</el-card>
</grid-item>
......@@ -69,7 +69,7 @@ export default {
if (response.success) {
this.dataBoard = response.data
this.layout = this.dataBoard.boardConfig ? JSON.parse(JSON.stringify(this.dataBoard.boardConfig.layout)) : []
const charts = this.dataBoard.charts
const charts = this.dataBoard.charts ? JSON.parse(JSON.stringify(this.dataBoard.charts)) : []
charts.forEach((item, index, arr) => {
this.parserChart(item)
})
......@@ -79,13 +79,18 @@ export default {
},
parserChart(chart) {
this.$set(chart, 'loading', true)
dataParser(chart.chartConfig).then(response => {
if (response.success) {
this.$set(chart, 'visible', true)
this.$set(chart, 'loading', false)
this.$set(chart, 'data', response.data.data)
}
})
if (chart.chartConfig) {
dataParser(JSON.parse(chart.chartConfig)).then(response => {
if (response.success) {
this.$set(chart, 'data', response.data.data)
this.$set(chart, 'chartSchema', JSON.parse(chart.chartConfig))
this.$set(chart, 'loading', false)
this.$set(chart, 'visible', true)
}
})
} else {
this.$set(chart, 'loading', false)
}
},
getChartItem(id) {
return this.charts.find(chart => chart.id === id)
......
......@@ -245,7 +245,7 @@ export default {
rows: [],
columns: [],
measures: [],
// 后期添加条件过滤
// 过滤条件
filters: [],
// 图表配置项
options: chartOptions,
......@@ -280,7 +280,7 @@ export default {
if (response.success) {
this.dataChart = response.data
if (this.dataChart.chartConfig) {
const chartConfig = JSON.parse(JSON.stringify(this.dataChart.chartConfig))
const chartConfig = JSON.parse(this.dataChart.chartConfig)
getDataSet(chartConfig.dataSetId).then(response => {
if (response.success) {
this.dataSet = response.data
......@@ -359,7 +359,7 @@ export default {
const data = {
id: this.dataChart.id,
chartThumbnail: this.dataChart.chartThumbnail,
chartConfig: this.widget
chartConfig: JSON.stringify(this.widget)
}
buildDataChart(data).then(response => {
if (response.success) {
......
......@@ -153,6 +153,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -324,7 +325,7 @@ export default {
option.xAxis.max = 100
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -340,7 +341,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -148,8 +148,9 @@ export default {
},
// 计算值
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
if (!this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -301,7 +302,7 @@ export default {
return params.seriesName + ' <br/>' + params.name + ' : ' + params.value + '<br>' + params.percent + '%'
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -317,7 +318,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -207,7 +207,7 @@ export default {
this.chart.setOption(option, true)
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -223,7 +223,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -153,6 +153,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -312,7 +313,7 @@ export default {
// }
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -328,7 +329,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -246,7 +246,7 @@ export default {
})
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -262,7 +262,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -150,6 +150,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -279,7 +280,7 @@ export default {
})
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -295,7 +296,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -152,6 +152,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -276,7 +277,7 @@ export default {
})
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -292,7 +293,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -141,6 +141,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -268,7 +269,7 @@ export default {
this.chart.setOption(option, true)
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -284,7 +285,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -145,6 +145,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -277,7 +278,7 @@ export default {
this.chart.setOption(option, true)
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -293,7 +294,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
......@@ -3,6 +3,9 @@
</template>
<script>
import echarts from 'echarts'
import { convertPathToMap, SEPARATOR } from '@/utils/visual-chart'
export default {
name: 'ChartTreemap',
props: {
......@@ -32,7 +35,8 @@ export default {
},
chartTheme: {
type: String,
require: true
require: true,
default: 'default'
},
chartOption: {
type: Object,
......@@ -49,8 +53,288 @@ export default {
}
}
},
data() {
return {
localRows: [],
localColumns: [],
localValues: [],
localData: [],
// 连接符
connector: '-',
chart: null,
calcOption: {
tooltip: {
trigger: 'item',
formatter: '{b} : {c}'
}
},
calcData: {
seriesObj: {}
}
}
},
computed: {
watchAllProps() {
const { rows, columns, values, data } = this
return { rows, columns, values, data }
}
},
watch: {
watchAllProps() {
this.init()
this.mergeChartOption()
},
chartTheme() {
this.mergeChartTheme()
},
chartOption: {
handler(newValue, oldValue) {
this.mergeChartOption()
},
deep: true
}
},
mounted() {
this.renderChart()
this.$on('resized', this.handleResize)
window.addEventListener('resize', this.handleResize)
},
created() {
console.log(this.data)
this.init()
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
}
window.removeEventListener('resize', this.handleResize)
},
methods: {
init() {
if (this.rows.length || this.columns.length || this.values.length) {
this.handleDataClone()
this.setValuesToColAndRow()
this.handleCalcData()
} else {
console.warn('[Warn]: props.rows, props.columns, props.values at least one is not empty.')
}
},
// clone data
handleDataClone() {
this.localRows = JSON.parse(JSON.stringify(this.rows))
this.localColumns = JSON.parse(JSON.stringify(this.columns))
this.localValues = JSON.parse(JSON.stringify(this.values))
this.localData = Object.freeze(this.data)
},
// set the `values` attribute to rows and columns
setValuesToColAndRow() {
const rowKeys = this.localRows.map(({ key }) => key)
const columnKeys = this.localColumns.map(({ key }) => key)
const rowValues = this._findCategory(rowKeys, this.localData)
const columnValues = this._findCategory(columnKeys, this.localData)
this.localRows.forEach((row) => {
const { key, values } = row
this.$set(row, 'values', values || rowValues[key] || [])
})
this.localColumns.forEach((column) => {
const { key, values } = column
this.$set(column, 'values', values || columnValues[key] || [])
})
},
// 计算值
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const seriesData = this.recursion(0, {}, this.localRows, this.localValues, this.localData)
const seriesObj = {}
const seriesName = 'treemap'
seriesObj[seriesName] = {
name: seriesName,
type: this.chartType,
leafDepth: 1,
visibleMin: 1,
label: { position: 'insideTopLeft' },
data: seriesData
}
this.calcData.seriesObj = seriesObj
},
// 递归
recursion(depth, conditions = {}, rows = [], values = [], data = []) {
const _result = []
if (depth < rows.length) {
const row = rows[depth]
row.values.forEach((val) => {
conditions[row.key] = val
const filters = Object.keys(conditions)
.filter((key, index) => index <= depth)
.reduce((obj, key) => {
obj[key] = conditions[key]
return obj
}, {})
const filterData = data.filter((item) => {
let status = true
for (const key in filters) {
if (filters[key] !== item[key]) {
status = false
return
}
}
return status
})
if (filterData.length) {
if (depth === (rows.length - 1)) {
values.forEach(({ key }) => {
const value = this._reduceValue(filterData, key)
_result.push({
name: val,
value: value
})
})
} else {
_result.push({
name: val,
children: this.recursion(depth + 1, conditions, rows, values, filterData)
})
}
}
})
}
return _result
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
},
renderChart() {
if (!this.$refs.chart) return
let option = Object.assign({}, this.chartOption, this.calcOption)
option = JSON.parse(JSON.stringify(option))
const series = JSON.parse(JSON.stringify(Object.values(this.calcData.seriesObj)))
this.parseChartSeries(option, series, this.chartSeriesType)
option.series = series
setTimeout(() => {
if (!this.chart) {
if (this.chartTheme !== 'default') {
require('./themes/' + this.chartTheme + '.js')
}
this.chart = echarts.init(this.$refs.chart, this.chartTheme)
}
this.chart.clear()
this.chart.setOption(option)
}, 0)
},
mergeChartTheme() {
if (!this.$refs.chart) return
if (this.chart) {
// 使用刚指定的配置项和数据显示图表
let option = Object.assign({}, this.chartOption, this.calcOption)
option = JSON.parse(JSON.stringify(option))
const series = JSON.parse(JSON.stringify(Object.values(this.calcData.seriesObj)))
this.parseChartSeries(option, series, this.chartSeriesType)
option.series = series
if (this.chartTheme !== 'default') {
require('./themes/' + this.chartTheme + '.js')
}
this.chart.dispose()
// 基于准备好的dom,初始化echarts实例
this.chart = echarts.init(this.$refs.chart, this.chartTheme)
this.chart.setOption(option)
}
},
mergeChartOption() {
if (!this.$refs.chart) return
if (this.chart) {
let option = Object.assign({}, this.chartOption, this.calcOption)
option = JSON.parse(JSON.stringify(option))
const series = JSON.parse(JSON.stringify(Object.values(this.calcData.seriesObj)))
this.parseChartSeries(option, series, this.chartSeriesType)
option.series = series
this.chart.clear()
this.chart.setOption(option, true)
}
},
parseChartSeries(option, series, type) {
series.forEach((item) => {
item.label.formatter = (params) => {
return params.name + '\n\nvalue : ' + params.value
}
})
},
_combineRowPaths(...arrays) {
const len = arrays.length
let _result = []
if (len) {
const rowPaths = arrays.reduce((prev, curr) => {
const arr = []
prev.values.forEach(_prevEl => {
const prevKey = prev.key.split(SEPARATOR)
curr.values.forEach(_currEl => {
const currKey = curr.key
const conditions = {}
prevKey.forEach((key, i) => {
conditions[key] = _prevEl.split(SEPARATOR)[i]
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
status = false
return
}
}
return status
})
if (filter) {
arr.push(_prevEl + SEPARATOR + _currEl)
}
})
})
return { key: prev.key + SEPARATOR + curr.key, values: arr }
}) || {}
_result = rowPaths.values || []
}
return _result
},
_combineColPaths(...arrays) {
return arrays.length ? arrays.reduce((prev, curr) => {
const arr = []
prev.forEach(_prevEl => {
curr.forEach(_currEl => {
arr.push(_prevEl + SEPARATOR + _currEl)
})
})
return arr
}) : arrays
},
_findCategory(keys = [], data = []) {
const _result = {}
data.forEach(item => {
keys.forEach(key => {
// Remove duplicates
_result[key] = _result[key] || []
_result[key].push(item[key])
_result[key] = [...new Set(_result[key])]
})
})
return _result
},
_reduceValue(data, key) {
if (!data.length) return 0
return data.reduce((sum, item) => { return sum + Number(item[key]) }, 0)
},
_filterData(conditions, data) {
return data.filter((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
status = false
return
}
}
return status
})
}
}
}
</script>
......
......@@ -142,6 +142,7 @@ export default {
handleCalcData() {
if (!this.localRows.length || !this.localValues.length) return
const _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
......@@ -242,7 +243,7 @@ export default {
this.chart.setOption(option, true)
}
},
_combineRowPaths(...arrays) {
_combineRowPaths(data, ...arrays) {
const len = arrays.length
let _result = []
if (len) {
......@@ -258,7 +259,7 @@ export default {
})
conditions[currKey] = _currEl
// 判断数据里是否有该项
const filter = this.localData.some((data) => {
const filter = data.some((data) => {
let status = true
for (const key in conditions) {
if (conditions[key] !== data[key]) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment