Commit 1aba0ffa by yuwei

项目初始化

parent 7d3387cb
......@@ -519,16 +519,11 @@ table {
border-collapse: collapse;
border-spacing: 0;
border: none;
thead th {
background-color: #CCE8EB;
thead {
background-color: rgba(255, 255, 255, 0.1);
}
tbody {
tr:nth-child(odd) {
background: #fff;
}
tr:nth-child(even) {
background: #F5FAFA;
}
background-color: rgba(255, 255, 255, 0.1);
}
td, th {
border: 1px solid #ccc;
......@@ -548,7 +543,7 @@ table {
min-height: 36px;
cursor: default;
&.col-corner-bg {
background: #f1f7fd;
background-color: rgba(255, 255, 255, 0.1);
}
}
}
......
......@@ -99,13 +99,13 @@ export const chartTypes = [
}
},
{
name: '地图', value: 'geo', icon: 'chart_geo',
name: '地图', value: 'map', icon: 'chart_geo',
status: true,
component: 'ChartGeo',
component: 'ChartMap',
rule: {
text: '1个或多个 行维;0个或多个 列维;1个或多个 指标',
text: '1 行维;0 列维;1 指标',
check(rows, columns, measures) {
return rows.length >= 1 && columns.length >= 0 && measures.length >= 1
return rows.length === 1 && columns.length === 0 && measures.length === 1
}
}
},
......@@ -153,39 +153,6 @@ export const chartTypes = [
}
}
}
// {
// name: '树图', value: 'tree', icon: 'chart_tree',
// status: false,
// component: 'ChartTree',
// rule: {
// text: '0 行维;0 列维;0 指标',
// check(rows, columns, measures) {
// return rows.length === 0 && columns.length === 0 && measures.length === 0
// }
// }
// },
// {
// name: '旭日图', value: 'sunburst', icon: 'chart_sunburst',
// status: false,
// component: 'ChartSunburst',
// rule: {
// text: '0 行维;0 列维;0 指标',
// check(rows, columns, measures) {
// return rows.length === 0 && columns.length === 0 && measures.length === 0
// }
// }
// },
// {
// name: '极区图', value: 'polar', icon: 'chart_polar',
// status: false,
// component: 'ChartPolar',
// rule: {
// text: '0 行维;0 列维;0 指标',
// check(rows, columns, measures) {
// return rows.length === 0 && columns.length === 0 && measures.length === 0
// }
// }
// }
]
export const chartOptions = {
......@@ -277,6 +244,10 @@ export const chartSeriesTypes = {
{ name: '菱形', value: 'diamond' },
{ name: '大头针形', value: 'pin' },
{ name: '箭头形', value: 'arrow' }
],
'map': [
{ name: '基础地图', value: 'map' },
{ name: '视觉映射', value: 'visualMap' }
]
}
......
......@@ -53,10 +53,11 @@
:w="item.w"
:h="item.h"
:i="item.i"
drag-allow-from=".vue-draggable-handle"
@resized="handleResize"
>
<el-card v-loading="getChartItem(item.i).loading" class="widget-center-card" body-style="padding: 10px;">
<div slot="header" class="widget-center-card-header">
<div slot="header" class="widget-center-card-header vue-draggable-handle">
<div>
<span>{{ getChartItem(item.i).chartName }}</span>
</div>
......
......@@ -28,7 +28,7 @@ import ChartTreemap from './widgets/ChartTreemap'
import ChartWordCloud from './widgets/ChartWordCloud'
import ChartLiquidFill from './widgets/ChartLiquidFill'
import ChartSankey from './widgets/ChartSankey'
import ChartGeo from './widgets/ChartGeo'
import ChartMap from './widgets/ChartMap'
import ChartTree from './widgets/ChartTree'
import ChartSunburst from './widgets/ChartSunburst'
import ChartPolar from './widgets/ChartPolar'
......@@ -39,7 +39,7 @@ export default {
ChartTable, ChartLine, ChartBar, ChartPie,
ChartKpi, ChartRadar, ChartFunnel, ChartScatter,
ChartGauge, ChartTreemap, ChartWordCloud, ChartLiquidFill,
ChartSankey, ChartGeo, ChartTree, ChartSunburst, ChartPolar
ChartSankey, ChartMap, ChartTree, ChartSunburst, ChartPolar
},
props: {
chartSchema: {
......
......@@ -68,6 +68,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
xAxis: { type: 'category' },
yAxis: { type: 'value' },
tooltip: { trigger: 'axis' }
......
......@@ -68,6 +68,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
......
......@@ -62,6 +62,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
......
<template>
<div ref="chart" :style="chartStyle">ChartGeo</div>
</template>
<script>
export default {
name: 'ChartGeo',
props: {
data: {
type: Array,
required: true,
default: () => []
},
rows: {
type: Array,
required: true,
default: () => []
},
columns: {
type: Array,
required: true,
default: () => []
},
values: {
type: Array,
required: true,
default: () => []
},
chartType: {
type: String,
required: true
},
chartTheme: {
type: String,
require: true
},
chartOption: {
type: Object,
require: false,
default: () => ({})
},
chartStyle: {
type: Object,
require: false,
default: () => {
return {
height: '200px'
}
}
}
},
created() {
console.log(this.data)
}
}
</script>
<style lang="scss" scoped>
</style>
......@@ -68,6 +68,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
xAxis: { type: 'category' },
yAxis: { type: 'value' },
tooltip: { trigger: 'axis' }
......
......@@ -69,6 +69,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
......
<template>
<div ref="chart" :style="chartStyle">ChartGeo</div>
</template>
<script>
import echarts from 'echarts'
import { convertPathToMap, SEPARATOR } from '@/utils/visual-chart'
export default {
name: 'ChartGeo',
props: {
data: {
type: Array,
required: true,
default: () => []
},
rows: {
type: Array,
required: true,
default: () => []
},
columns: {
type: Array,
required: true,
default: () => []
},
values: {
type: Array,
required: true,
default: () => []
},
chartType: {
type: String,
required: true
},
chartTheme: {
type: String,
require: true,
default: 'default'
},
chartSeriesType: {
type: String,
require: true,
default: ''
},
chartOption: {
type: Object,
require: false,
default: () => ({})
},
chartStyle: {
type: Object,
require: false,
default: () => {
return {
height: '200px'
}
}
}
},
data() {
return {
localRows: [],
localColumns: [],
localValues: [],
localData: [],
// 连接符
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
areaCode: '100000',
seriesObj: {}
}
}
},
computed: {
watchAllProps() {
const { rows, columns, values, data } = this
return { rows, columns, values, data }
}
},
watch: {
watchAllProps() {
this.init()
this.mergeChartOption()
},
chartTheme() {
this.mergeChartTheme()
},
chartSeriesType() {
this.mergeChartOption()
},
chartOption: {
handler(newValue, oldValue) {
this.mergeChartOption()
},
deep: true
}
},
mounted() {
this.renderChart()
this.$on('resized', this.handleResize)
window.addEventListener('resize', this.handleResize)
},
created() {
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 _rowPaths = this._combineRowPaths(
this.localData,
...this.localRows.map(({ key, values }) => { return { key, values } })
)
const _rowKeys = this.localRows.map(({ key }) => key)
const _colPaths = this._combineColPaths(
...this.localColumns.map(({ values }) => values)
)
const _colKeys = this.localColumns.map(({ key }) => key)
// 行对应的条件
const rowConditions = convertPathToMap(_rowPaths, _rowKeys)
// 列对应的条件
const colConditions = convertPathToMap(_colPaths, _colKeys)
// 针对没传入行或列的处理
!colConditions.length && colConditions.push({})
!rowConditions.length && rowConditions.push({})
const seriesData = []
this.localValues.forEach(({ key }) => {
rowConditions.forEach((rowCondition, rowConditionIndex) => {
// 当前单元对应的条件
const conditions = Object.assign({}, rowCondition)
// 通过当前单元对应的条件,过滤数据
const filterData = this._filterData(conditions, this.localData)
if (filterData.length) {
// 多个值,多条数据
const value = this._reduceValue(filterData, key)
seriesData.push(
{ name: Object.values(rowCondition).join(this.connector), value: value }
)
}
})
})
const seriesObj = {}
const seriesName = this.localValues[0].key
seriesObj[seriesName] = {
name: seriesName,
type: this.chartType,
map: this.calcData.areaCode,
roam: true,
selectedMode: 'single',
showLegendSymbol: false,
aspectScale: 0.75,
zoom: 3,
itemStyle: {
normal: {
areaColor: 'transparent',
borderColor: '#B5B5B5',
borderWidth: 1,
shadowColor: 'rgba(63, 218, 255, 0.5)',
shadowBlur: 30
},
emphasis: {
areaColor: '#2B91B7'
}
},
data: seriesData
}
this.calcData.seriesObj = seriesObj
},
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)
}
const rawGeoJson = require('./maps/' + this.calcData.areaCode + '.json')
echarts.registerMap(this.calcData.areaCode, rawGeoJson)
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) {
if (type === 'visualMap') {
option.visualMap = [{
type: 'continuous',
inRange: {
color: ['#e0ffff', '#006edd']
},
calculable: true,
pieces: [
{ gt: 100 },
{ gt: 10, lte: 99 },
{ gt: 0, lte: 9 }
]
}]
}
},
_combineRowPaths(data, ...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 = data.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>
<style lang="scss" scoped>
</style>
......@@ -68,6 +68,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
......
......@@ -68,6 +68,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
radar: { indicator: [] },
tooltip: { trigger: 'item' }
},
......
......@@ -63,6 +63,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
......
......@@ -63,6 +63,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
xAxis: {},
yAxis: {},
tooltip: { trigger: 'item' }
......
......@@ -63,6 +63,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: {
trigger: 'item',
formatter: '{b} : {c}'
......
......@@ -64,6 +64,7 @@ export default {
connector: '-',
chart: null,
calcOption: {
backgroundColor: 'rgba(255, 255, 255, 0.1)',
tooltip: { trigger: 'item' }
},
calcData: {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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