Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
datax-cloud
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
黄营
datax-cloud
Commits
b8f29b48
Commit
b8f29b48
authored
Nov 30, 2020
by
yuwei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
项目初始化
parent
b4dcc1c4
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
935 additions
and
81 deletions
+935
-81
visual-chart.js
datax-ui/src/utils/visual-chart.js
+5
-11
ChartPanel.vue
...x-ui/src/views/visual/datachart/components/ChartPanel.vue
+1
-3
ChartDonut.vue
.../views/visual/datachart/components/widgets/ChartDonut.vue
+0
-60
ChartFunnel.vue
...views/visual/datachart/components/widgets/ChartFunnel.vue
+328
-2
ChartSankey.vue
...views/visual/datachart/components/widgets/ChartSankey.vue
+295
-2
ChartScatter.vue
...iews/visual/datachart/components/widgets/ChartScatter.vue
+304
-2
ChartWordCloud.vue
...ws/visual/datachart/components/widgets/ChartWordCloud.vue
+2
-1
No files found.
datax-ui/src/utils/visual-chart.js
View file @
b8f29b48
...
@@ -165,17 +165,6 @@ export const chartTypes = [
...
@@ -165,17 +165,6 @@ export const chartTypes = [
// }
// }
// },
// },
// {
// {
// name: '环形图', value: 'donut', icon: 'chart_donut',
// status: false,
// component: 'ChartDonut',
// 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',
// name: '旭日图', value: 'sunburst', icon: 'chart_sunburst',
// status: false,
// status: false,
// component: 'ChartSunburst',
// component: 'ChartSunburst',
...
@@ -275,6 +264,11 @@ export const chartSeriesTypes = {
...
@@ -275,6 +264,11 @@ export const chartSeriesTypes = {
{
name
:
'基础雷达图'
,
value
:
'radar'
},
{
name
:
'基础雷达图'
,
value
:
'radar'
},
{
name
:
'区域雷达图'
,
value
:
'arearadar'
}
{
name
:
'区域雷达图'
,
value
:
'arearadar'
}
],
],
'funnel'
:
[
{
name
:
'基础漏斗图'
,
value
:
'funnel'
},
{
name
:
'金字塔漏斗图'
,
value
:
'pyramidfunnel'
},
{
name
:
'对比漏斗图'
,
value
:
'contrastfunnel'
}
],
'liquidFill'
:
[
'liquidFill'
:
[
{
name
:
'圆形'
,
value
:
'circle'
},
{
name
:
'圆形'
,
value
:
'circle'
},
{
name
:
'矩形'
,
value
:
'rect'
},
{
name
:
'矩形'
,
value
:
'rect'
},
...
...
datax-ui/src/views/visual/datachart/components/ChartPanel.vue
View file @
b8f29b48
...
@@ -30,7 +30,6 @@ import ChartLiquidFill from './widgets/ChartLiquidFill'
...
@@ -30,7 +30,6 @@ import ChartLiquidFill from './widgets/ChartLiquidFill'
import
ChartSankey
from
'./widgets/ChartSankey'
import
ChartSankey
from
'./widgets/ChartSankey'
import
ChartGeo
from
'./widgets/ChartGeo'
import
ChartGeo
from
'./widgets/ChartGeo'
import
ChartTree
from
'./widgets/ChartTree'
import
ChartTree
from
'./widgets/ChartTree'
import
ChartDonut
from
'./widgets/ChartDonut'
import
ChartSunburst
from
'./widgets/ChartSunburst'
import
ChartSunburst
from
'./widgets/ChartSunburst'
import
ChartPolar
from
'./widgets/ChartPolar'
import
ChartPolar
from
'./widgets/ChartPolar'
...
@@ -40,8 +39,7 @@ export default {
...
@@ -40,8 +39,7 @@ export default {
ChartTable
,
ChartLine
,
ChartBar
,
ChartPie
,
ChartTable
,
ChartLine
,
ChartBar
,
ChartPie
,
ChartKpi
,
ChartRadar
,
ChartFunnel
,
ChartScatter
,
ChartKpi
,
ChartRadar
,
ChartFunnel
,
ChartScatter
,
ChartGauge
,
ChartTreemap
,
ChartWordCloud
,
ChartLiquidFill
,
ChartGauge
,
ChartTreemap
,
ChartWordCloud
,
ChartLiquidFill
,
ChartSankey
,
ChartGeo
,
ChartTree
,
ChartDonut
,
ChartSankey
,
ChartGeo
,
ChartTree
,
ChartSunburst
,
ChartPolar
ChartSunburst
,
ChartPolar
},
},
props
:
{
props
:
{
chartSchema
:
{
chartSchema
:
{
...
...
datax-ui/src/views/visual/datachart/components/widgets/ChartDonut.vue
deleted
100644 → 0
View file @
b4dcc1c4
<
template
>
<div
ref=
"chart"
:style=
"chartStyle"
>
ChartDonut
</div>
</
template
>
<
script
>
export
default
{
name
:
'ChartDonut'
,
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
>
datax-ui/src/views/visual/datachart/components/widgets/ChartFunnel.vue
View file @
b8f29b48
...
@@ -3,6 +3,9 @@
...
@@ -3,6 +3,9 @@
</
template
>
</
template
>
<
script
>
<
script
>
import
echarts
from
'echarts'
import
{
convertPathToMap
,
SEPARATOR
}
from
'@/utils/visual-chart'
export
default
{
export
default
{
name
:
'ChartFunnel'
,
name
:
'ChartFunnel'
,
props
:
{
props
:
{
...
@@ -32,7 +35,13 @@ export default {
...
@@ -32,7 +35,13 @@ export default {
},
},
chartTheme
:
{
chartTheme
:
{
type
:
String
,
type
:
String
,
require
:
true
require
:
true
,
default
:
'default'
},
chartSeriesType
:
{
type
:
String
,
require
:
true
,
default
:
''
},
},
chartOption
:
{
chartOption
:
{
type
:
Object
,
type
:
Object
,
...
@@ -49,8 +58,325 @@ export default {
...
@@ -49,8 +58,325 @@ export default {
}
}
}
}
},
},
data
()
{
return
{
localRows
:
[],
localColumns
:
[],
localValues
:
[],
localData
:
[],
// 连接符
connector
:
'-'
,
chart
:
null
,
calcOption
:
{
tooltip
:
{
trigger
:
'item'
}
},
calcData
:
{
legendData
:
[],
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
()
{
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
_rowPaths
=
this
.
_combineRowPaths
(
...
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
legendData
=
[]
this
.
localValues
.
forEach
(({
key
})
=>
{
legendData
.
push
(
key
)
})
const
seriesObj
=
{}
rowConditions
.
forEach
((
rowCondition
,
index
)
=>
{
const
seriesName
=
Object
.
values
(
rowCondition
).
join
(
this
.
connector
)
||
''
seriesObj
[
seriesName
]
=
{
name
:
seriesName
,
type
:
this
.
chartType
,
label
:
{
show
:
true
,
position
:
'inside'
},
sort
:
'descending'
,
data
:
[]
}
})
// 计算每个series数据
rowConditions
.
forEach
((
rowCondition
,
rowConditionIndex
)
=>
{
const
seriesName
=
Object
.
values
(
rowCondition
).
join
(
this
.
connector
)
||
''
const
seriesData
=
[]
colConditions
.
forEach
((
colCondition
,
colConditionIndex
)
=>
{
// 当前单元对应的条件
const
conditions
=
Object
.
assign
({},
rowCondition
,
colCondition
)
// 通过当前单元对应的条件,过滤数据
const
filterData
=
this
.
_filterData
(
conditions
,
this
.
localData
)
// 多个值,多条数据
this
.
localValues
.
forEach
(({
key
})
=>
{
const
seriesDataValue
=
{
name
:
''
,
value
:
''
}
seriesDataValue
.
name
=
key
const
value
=
this
.
_reduceValue
(
filterData
,
key
)
seriesDataValue
.
value
=
value
seriesData
.
push
(
seriesDataValue
)
})
})
seriesObj
[
seriesName
].
data
=
seriesData
})
this
.
calcData
.
legendData
=
legendData
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
.
legend
.
data
=
this
.
calcData
.
legendData
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
.
legend
.
data
=
this
.
calcData
.
legendData
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
.
legend
.
data
=
this
.
calcData
.
legendData
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
)
{
const
b
=
100
/
(
series
.
length
*
9
+
1
)
if
(
type
===
'funnel'
)
{
series
.
forEach
((
item
,
index
)
=>
{
item
.
left
=
b
+
index
*
b
*
9
+
'%'
item
.
width
=
b
*
8
+
'%'
item
.
maxSize
=
'100%'
item
.
label
.
formatter
=
(
params
)
=>
{
return
params
.
value
+
'
\
n'
+
params
.
percent
+
'%'
}
})
}
if
(
type
===
'pyramidfunnel'
)
{
series
.
forEach
((
item
,
index
)
=>
{
item
.
sort
=
'ascending'
item
.
left
=
b
+
index
*
b
*
9
+
'%'
item
.
width
=
b
*
8
+
'%'
item
.
maxSize
=
'100%'
item
.
label
.
formatter
=
(
params
)
=>
{
return
params
.
value
+
'
\
n'
+
params
.
percent
+
'%'
}
})
}
else
if
(
type
===
'contrastfunnel'
)
{
let
percent
=
100
series
.
forEach
((
item
,
index
)
=>
{
if
(
index
===
0
)
{
item
.
label
.
position
=
'outside'
}
else
{
item
.
label
.
formatter
=
(
params
)
=>
{
return
params
.
value
+
'
\
n'
+
params
.
percent
+
'%'
}
}
item
.
maxSize
=
percent
+
'%'
percent
*=
0.8
})
}
option
.
tooltip
.
formatter
=
(
params
)
=>
{
return
params
.
seriesName
+
' <br/>'
+
params
.
name
+
' : '
+
params
.
value
+
'<br>'
+
params
.
percent
+
'%'
}
},
_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
>
</
script
>
...
...
datax-ui/src/views/visual/datachart/components/widgets/ChartSankey.vue
View file @
b8f29b48
...
@@ -3,6 +3,9 @@
...
@@ -3,6 +3,9 @@
</
template
>
</
template
>
<
script
>
<
script
>
import
echarts
from
'echarts'
import
{
convertPathToMap
,
SEPARATOR
}
from
'@/utils/visual-chart'
export
default
{
export
default
{
name
:
'ChartSankey'
,
name
:
'ChartSankey'
,
props
:
{
props
:
{
...
@@ -32,7 +35,8 @@ export default {
...
@@ -32,7 +35,8 @@ export default {
},
},
chartTheme
:
{
chartTheme
:
{
type
:
String
,
type
:
String
,
require
:
true
require
:
true
,
default
:
'default'
},
},
chartOption
:
{
chartOption
:
{
type
:
Object
,
type
:
Object
,
...
@@ -49,8 +53,297 @@ export default {
...
@@ -49,8 +53,297 @@ export default {
}
}
}
}
},
},
data
()
{
return
{
localRows
:
[],
localColumns
:
[],
localValues
:
[],
localData
:
[],
// 连接符
connector
:
'-'
,
chart
:
null
,
calcOption
:
{
tooltip
:
{
trigger
:
'item'
}
},
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
()
{
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
_rowPaths
=
this
.
_combineRowPaths
(
...
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
=
[]
const
seriesLinks
=
[]
rowConditions
.
forEach
((
rowCondition
,
rowConditionIndex
)
=>
{
seriesData
.
push
({
name
:
Object
.
values
(
rowCondition
).
join
(
this
.
connector
)
})
})
// 判断没传入列的处理
if
(
!
this
.
localColumns
.
length
)
{
this
.
localValues
.
forEach
(({
key
})
=>
{
seriesData
.
push
({
name
:
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
)
seriesLinks
.
push
(
{
source
:
Object
.
values
(
rowCondition
).
join
(
this
.
connector
),
target
:
key
,
value
:
value
}
)
}
})
})
}
else
{
colConditions
.
forEach
((
colCondition
,
colConditionIndex
)
=>
{
seriesData
.
push
({
name
:
Object
.
values
(
colCondition
).
join
(
this
.
connector
)
})
rowConditions
.
forEach
((
rowCondition
,
rowConditionIndex
)
=>
{
// 当前单元对应的条件
const
conditions
=
Object
.
assign
({},
rowCondition
,
colCondition
)
// 通过当前单元对应的条件,过滤数据
const
filterData
=
this
.
_filterData
(
conditions
,
this
.
localData
)
if
(
filterData
.
length
)
{
// 多个值,多条数据
this
.
localValues
.
forEach
(({
key
})
=>
{
const
value
=
this
.
_reduceValue
(
filterData
,
key
)
seriesLinks
.
push
(
{
source
:
Object
.
values
(
rowCondition
).
join
(
this
.
connector
),
target
:
Object
.
values
(
colCondition
).
join
(
this
.
connector
),
value
:
value
}
)
})
}
})
})
}
const
seriesObj
=
{}
const
seriesName
=
'sankey'
seriesObj
[
seriesName
]
=
{
name
:
seriesName
,
type
:
this
.
chartType
,
layout
:
'none'
,
draggable
:
false
,
links
:
seriesLinks
,
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
)))
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
)))
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
)))
option
.
series
=
series
this
.
chart
.
clear
()
this
.
chart
.
setOption
(
option
,
true
)
}
},
_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
>
</
script
>
...
...
datax-ui/src/views/visual/datachart/components/widgets/ChartScatter.vue
View file @
b8f29b48
...
@@ -3,6 +3,9 @@
...
@@ -3,6 +3,9 @@
</
template
>
</
template
>
<
script
>
<
script
>
import
echarts
from
'echarts'
import
{
convertPathToMap
,
SEPARATOR
}
from
'@/utils/visual-chart'
export
default
{
export
default
{
name
:
'ChartScatter'
,
name
:
'ChartScatter'
,
props
:
{
props
:
{
...
@@ -32,7 +35,8 @@ export default {
...
@@ -32,7 +35,8 @@ export default {
},
},
chartTheme
:
{
chartTheme
:
{
type
:
String
,
type
:
String
,
require
:
true
require
:
true
,
default
:
'default'
},
},
chartOption
:
{
chartOption
:
{
type
:
Object
,
type
:
Object
,
...
@@ -49,8 +53,306 @@ export default {
...
@@ -49,8 +53,306 @@ export default {
}
}
}
}
},
},
data
()
{
return
{
localRows
:
[],
localColumns
:
[],
localValues
:
[],
localData
:
[],
// 连接符
connector
:
'-'
,
chart
:
null
,
calcOption
:
{
xAxis
:
{},
yAxis
:
{},
tooltip
:
{
trigger
:
'item'
}
},
calcData
:
{
legendData
:
[],
xAxisData
:
[],
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
()
{
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
_rowPaths
=
this
.
_combineRowPaths
(
...
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
xAxisData
=
[]
const
legendData
=
[]
const
seriesObj
=
{}
rowConditions
.
forEach
((
rowCondition
)
=>
{
xAxisData
.
push
(
Object
.
values
(
rowCondition
).
join
(
this
.
connector
))
})
colConditions
.
forEach
((
colCondition
)
=>
{
const
seriesName
=
Object
.
values
(
colCondition
).
join
(
this
.
connector
)
||
''
legendData
.
push
(
seriesName
)
seriesObj
[
seriesName
]
=
{
name
:
seriesName
,
type
:
this
.
chartType
,
data
:
[]
}
})
// 计算每个series数据
colConditions
.
forEach
((
colCondition
,
colConditionIndex
)
=>
{
const
seriesName
=
Object
.
values
(
colCondition
).
join
(
this
.
connector
)
||
''
const
seriesData
=
[]
rowConditions
.
forEach
((
rowCondition
,
rowConditionIndex
)
=>
{
const
seriesDataName
=
Object
.
values
(
rowCondition
).
join
(
this
.
connector
)
const
seriesDataValue
=
{
name
:
''
,
value
:
[]
}
seriesDataValue
.
name
=
seriesDataName
seriesDataValue
.
value
.
push
(
seriesDataName
)
// 当前单元对应的条件
const
conditions
=
Object
.
assign
({},
rowCondition
,
colCondition
)
// 通过当前单元对应的条件,过滤数据
const
filterData
=
this
.
_filterData
(
conditions
,
this
.
localData
)
// 多个值,多条数据
this
.
localValues
.
forEach
(({
key
})
=>
{
const
value
=
this
.
_reduceValue
(
filterData
,
key
)
seriesDataValue
.
value
.
push
(
value
)
})
seriesData
.
push
(
seriesDataValue
)
})
seriesObj
[
seriesName
].
data
=
seriesData
})
this
.
calcData
.
legendData
=
legendData
this
.
calcData
.
xAxisData
=
xAxisData
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
.
legend
.
data
=
this
.
calcData
.
legendData
option
.
xAxis
.
data
=
this
.
calcData
.
xAxisData
option
=
JSON
.
parse
(
JSON
.
stringify
(
option
))
const
series
=
JSON
.
parse
(
JSON
.
stringify
(
Object
.
values
(
this
.
calcData
.
seriesObj
)))
option
.
series
=
series
option
.
tooltip
.
formatter
=
(
params
)
=>
{
let
s
=
params
.
seriesName
+
' '
+
params
.
name
+
'</br>'
this
.
localValues
.
forEach
(({
key
},
index
)
=>
{
s
+=
key
+
' : '
+
params
.
value
[
index
+
1
]
+
'<br>'
})
return
s
}
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
.
legend
.
data
=
this
.
calcData
.
legendData
option
.
xAxis
.
data
=
this
.
calcData
.
xAxisData
option
=
JSON
.
parse
(
JSON
.
stringify
(
option
))
const
series
=
JSON
.
parse
(
JSON
.
stringify
(
Object
.
values
(
this
.
calcData
.
seriesObj
)))
option
.
series
=
series
option
.
tooltip
.
formatter
=
(
params
)
=>
{
let
s
=
params
.
seriesName
+
' '
+
params
.
name
+
'</br>'
this
.
localValues
.
forEach
(({
key
},
index
)
=>
{
s
+=
key
+
' : '
+
params
.
value
[
index
+
1
]
+
'<br>'
})
return
s
}
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
.
legend
.
data
=
this
.
calcData
.
legendData
option
.
xAxis
.
data
=
this
.
calcData
.
xAxisData
option
=
JSON
.
parse
(
JSON
.
stringify
(
option
))
const
series
=
JSON
.
parse
(
JSON
.
stringify
(
Object
.
values
(
this
.
calcData
.
seriesObj
)))
option
.
series
=
series
option
.
tooltip
.
formatter
=
(
params
)
=>
{
let
s
=
params
.
seriesName
+
' '
+
params
.
name
+
'</br>'
this
.
localValues
.
forEach
(({
key
},
index
)
=>
{
s
+=
key
+
' : '
+
params
.
value
[
index
+
1
]
+
'<br>'
})
return
s
}
this
.
chart
.
clear
()
this
.
chart
.
setOption
(
option
,
true
)
}
},
_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
>
</
script
>
...
...
datax-ui/src/views/visual/datachart/components/widgets/ChartWordCloud.vue
View file @
b8f29b48
...
@@ -36,7 +36,8 @@ export default {
...
@@ -36,7 +36,8 @@ export default {
},
},
chartTheme
:
{
chartTheme
:
{
type
:
String
,
type
:
String
,
require
:
true
require
:
true
,
default
:
'default'
},
},
chartOption
:
{
chartOption
:
{
type
:
Object
,
type
:
Object
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment