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
ddca17e6
Commit
ddca17e6
authored
Nov 17, 2020
by
yuwei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
项目初始化
parent
ea4049f4
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
522 additions
and
55 deletions
+522
-55
index.vue
datax-ui/src/components/PivotTable/index.vue
+444
-0
constants.js
datax-ui/src/components/PivotTable/utils/constants.js
+3
-0
convert_path_to_map.js
...ui/src/components/PivotTable/utils/convert_path_to_map.js
+17
-0
get_height_by_count.js
...ui/src/components/PivotTable/utils/get_height_by_count.js
+3
-0
index.js
datax-ui/src/components/PivotTable/utils/index.js
+9
-0
merge_base_info.js
datax-ui/src/components/PivotTable/utils/merge_base_info.js
+11
-0
DataChartBuild.vue
datax-ui/src/views/visual/datachart/DataChartBuild.vue
+1
-1
ChartTable.vue
.../views/visual/datachart/components/widgets/ChartTable.vue
+34
-54
No files found.
datax-ui/src/components/PivotTable/index.vue
0 → 100644
View file @
ddca17e6
<
template
>
<div
class=
"table-responsive"
>
<table>
<thead>
<tr
v-for=
"(tr, index) in combineHeads"
:key=
"index"
>
<th
v-for=
"cell in tr"
:key=
"cell.__index"
:rowspan=
"cell.rowspan"
:colspan=
"cell.colspan"
>
<div
:class=
"
{ 'col-corner-bg': cell.isCorner }"
:style="{ 'min-height': _getMinHeightByRowCount(cell.rowspan) }"
>
{{
cell
.
isCorner
?
(
rowPaths
.
length
+
' x '
+
colPaths
.
length
)
:
cell
.
value
}}
</div>
</th>
</tr>
</thead>
<tbody>
<tr
v-for=
"(tr, index) in combineValues"
:key=
"tr.__index"
>
<td
v-for=
"cell in tr.data"
:key=
"cell.__index"
:rowspan=
"cell.rowspan"
:colspan=
"cell.colspan"
>
<div
:class=
"
{ 'col-corner-bg': cell.isCorner }"
:style="{ 'min-height': _getMinHeightByRowCount(cell.rowspan) }"
>
{{
cell
.
value
}}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</
template
>
<
script
>
import
{
mergeBaseInfo
,
convertPathToMap
,
getHeightByCount
}
from
'./utils'
import
{
SEPARATOR
}
from
'./utils/constants'
export
default
{
name
:
'PivotTable'
,
props
:
{
data
:
{
type
:
Array
,
default
:
()
=>
[]
},
rows
:
{
type
:
Array
,
default
:
()
=>
[]
},
columns
:
{
type
:
Array
,
default
:
()
=>
[]
},
values
:
{
type
:
Array
,
default
:
()
=>
[]
},
summary
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
:
()
=>
({
localRows
:
[],
localColumns
:
[],
localValues
:
[],
localData
:
[],
// 计算列的数据
calcData
:
[],
// Separator
Separator
:
SEPARATOR
,
// 合并后的表头
combineHeads
:
[],
// 合并后的单元格
combineValues
:
[]
}),
computed
:
{
rowPaths
()
{
const
_paths
=
this
.
_combinePaths
(
...
this
.
localRows
.
map
(({
values
})
=>
values
)
)
return
_paths
},
colPaths
()
{
const
keys
=
this
.
localColumns
.
map
(({
values
})
=>
values
)
if
(
this
.
localValues
.
length
)
{
keys
.
push
(
this
.
localValues
.
map
(({
key
})
=>
key
))
}
const
_paths
=
this
.
_combinePaths
(...
keys
)
return
_paths
},
// 列的表头
colHeads
()
{
// 共有多少行
const
_rows
=
this
.
localColumns
.
map
(()
=>
[])
// 有几个值
const
valuesLen
=
this
.
localValues
.
length
if
(
valuesLen
)
{
_rows
.
push
([])
}
// todo: 仅有 values 的时候会有一个空的path
this
.
colPaths
.
forEach
((
path
,
pathIndex
)
=>
{
// 条件值
const
pathValues
=
path
.
split
(
this
.
Separator
)
// 存储路径
const
currPath
=
[]
_rows
.
forEach
((
row
,
rowIndex
)
=>
{
const
cellData
=
{}
const
currVal
=
pathValues
[
rowIndex
]
||
''
// 是否为 values 行
const
isLastRow
=
rowIndex
===
_rows
.
length
-
1
// 存储路径
currPath
.
push
(
currVal
)
const
baseX
=
rowIndex
const
baseY
=
this
.
localRows
.
length
+
pathIndex
row
.
push
(
Object
.
assign
(
cellData
,
mergeBaseInfo
({
__index
:
`
${
baseX
}
-
${
baseY
}
`
,
x
:
baseX
,
y
:
baseY
,
path
:
currPath
.
filter
((
item
)
=>
!!
item
),
// 最后一行是 values,替换显示文本
value
:
valuesLen
&&
isLastRow
&&
currVal
?
this
.
localValues
.
find
(({
key
})
=>
key
===
currVal
).
label
:
currVal
})
)
)
})
})
return
_rows
},
// 行的表头
rowHeads
()
{
// 共有多少列
const
_columns
=
[]
// 左上角特殊处理
_columns
.
push
(
mergeBaseInfo
({
__index
:
`0-0`
,
colspan
:
this
.
localRows
.
length
,
rowspan
:
this
.
localColumns
.
length
,
// 左上角标记
isCorner
:
true
}))
this
.
localRows
.
forEach
(({
label
},
index
)
=>
{
_columns
.
push
(
mergeBaseInfo
({
__index
:
`
${
this
.
localColumns
.
length
}
-
${
index
}
`
,
value
:
label
,
x
:
this
.
localColumns
.
length
,
y
:
index
}))
})
return
_columns
},
// 行对应的值
rowHeadValues
()
{
return
this
.
localRows
.
length
?
this
.
rowPaths
.
map
((
path
,
index
)
=>
{
const
values
=
path
.
split
(
this
.
Separator
)
const
currPath
=
[]
return
this
.
localRows
.
map
((
item
,
rowIndex
)
=>
{
const
_index
=
rowIndex
const
_currVal
=
values
[
_index
]
||
''
const
baseX
=
this
.
localColumns
.
length
+
+
Boolean
(
this
.
localValues
.
length
)
+
index
const
baseY
=
_index
currPath
.
push
(
_currVal
)
return
mergeBaseInfo
({
__index
:
`
${
baseX
}
-
${
baseY
}
`
,
value
:
_currVal
,
x
:
baseX
,
y
:
baseY
,
path
:
currPath
.
filter
((
item
)
=>
!!
item
)
})
})
})
:
[]
},
// 计算所有对应条件的值
dataValues
()
{
// 列对应的条件
const
colConditions
=
convertPathToMap
(
this
.
colPaths
,
this
.
localColumns
.
map
(({
key
})
=>
key
).
concat
(
this
.
localValues
.
length
?
[
'value'
]
:
[])
)
// 行对应的条件
const
rowConditions
=
convertPathToMap
(
this
.
rowPaths
,
this
.
localRows
.
map
(({
key
})
=>
key
)
)
// console.log('colConditions', colConditions)
// console.log('rowConditions', rowConditions)
// 针对没传入行或列的处理
// !colConditions.length && colConditions.push({});
// !rowConditions.length && rowConditions.push({});
// 过滤数据, 遍历行以及遍历行对应的列
return
rowConditions
.
map
((
rowCondition
,
rowConditionIndex
)
=>
{
const
_data
=
colConditions
.
map
((
colCondition
,
colConditionIndex
)
=>
{
// 存储当前单元对应的数据
const
cellData
=
{}
// 当前单元对应的条件
const
conditions
=
Object
.
assign
({},
rowCondition
,
colCondition
)
const
_filterConditions
=
Object
.
fromEntries
(
Object
.
entries
(
conditions
).
filter
(
(
item
)
=>
item
[
0
]
!==
'value'
)
)
// 通过当前单元对应的条件,过滤数据
const
filterData
=
this
.
_filterData
(
_filterConditions
,
this
.
localData
)
// 对应表格的坐标位置
const
baseX
=
this
.
localColumns
.
length
+
+
Boolean
(
this
.
localValues
.
length
)
+
rowConditionIndex
const
baseY
=
this
.
localRows
.
length
+
colConditionIndex
Object
.
assign
(
cellData
,
mergeBaseInfo
({
conditions
,
x
:
baseX
,
y
:
baseY
,
__index
:
`
${
baseX
}
-
${
baseY
}
`
})
)
// 针对为指定值 props.values 的空处理(绘制空表格)
const
isEmptyValues
=
this
.
localColumns
.
length
&&
this
.
localRows
.
length
&&
!
this
.
localValues
.
length
if
(
isEmptyValues
)
{
Object
.
assign
(
cellData
,
{
value
:
''
})
}
else
{
// 从 props.values 中找出对应的值 handle
// 注意:this.localValues 通过 JSON.xxx 序列化后,handle 会被忽略
const
_value
=
this
.
values
.
find
(({
key
})
=>
key
===
conditions
.
value
)
Object
.
assign
(
cellData
,
{
value
:
_value
&&
_value
.
key
?
this
.
_reduceValue
(
filterData
,
_value
.
key
)
:
''
})
}
return
cellData
}
)
return
{
__index
:
_data
[
0
].
x
,
data
:
_data
}
})
}
},
created
:
function
()
{
this
.
init
()
},
methods
:
{
init
()
{
if
(
this
.
rows
.
length
||
this
.
columns
.
length
||
this
.
values
)
{
this
.
handleDataClone
()
this
.
setValuesToColAndRow
()
this
.
handleCalcData
()
this
.
handleCombineHeads
()
this
.
handleCombineValues
()
}
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
]
||
[])
})
},
// 合并表头
handleCombineHeads
()
{
let
combineColHeads
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
colHeads
))
combineColHeads
[
0
]
=
combineColHeads
[
0
]
||
[]
combineColHeads
[
0
].
unshift
(...
this
.
rowHeads
.
filter
((
item
)
=>
item
.
isCorner
))
combineColHeads
[
combineColHeads
.
length
-
1
].
unshift
(...
this
.
rowHeads
.
filter
((
item
)
=>
!
item
.
isCorner
))
combineColHeads
=
combineColHeads
.
filter
((
item
)
=>
item
.
length
)
this
.
combineHeads
=
combineColHeads
},
// 合并值
handleCombineValues
()
{
// values
const
combineValues
=
[]
const
valueRowCount
=
this
.
dataValues
.
length
||
this
.
rowHeadValues
.
length
for
(
let
i
=
0
;
i
<
valueRowCount
;
i
++
)
{
const
_currRowHeadValue
=
this
.
rowHeadValues
[
i
]
||
[]
const
_currValue
=
this
.
dataValues
[
i
]
||
{}
const
_row
=
[...
_currRowHeadValue
,
...(
_currValue
.
data
||
[])]
combineValues
.
push
(
Object
.
assign
({},
_currValue
,
{
data
:
_row
})
)
}
this
.
combineValues
=
combineValues
},
// 初始计算值
handleCalcData
()
{
if
(
!
this
.
localValues
.
length
)
return
const
_rowPaths
=
this
.
_combinePaths
(
...
this
.
localRows
.
map
(({
values
})
=>
values
)
)
const
_rowKeys
=
this
.
localRows
.
map
(({
key
})
=>
key
)
const
_colPaths
=
this
.
_combinePaths
(
...
this
.
localColumns
.
map
(({
values
})
=>
values
)
)
const
_colKeys
=
this
.
localColumns
.
map
(({
key
})
=>
key
)
// conditions of col head
const
colConditions
=
convertPathToMap
(
_colPaths
,
_colKeys
)
// conditions of row-head
const
rowConditions
=
convertPathToMap
(
_rowPaths
,
_rowKeys
)
// Note: if there are no props.rows or props.column, push an empty object
!
colConditions
.
length
&&
colConditions
.
push
({})
!
rowConditions
.
length
&&
rowConditions
.
push
({})
// draw data
this
.
calcData
=
Object
.
freeze
(
rowConditions
.
map
((
rowCondition
,
rowConditionIndex
)
=>
colConditions
.
map
((
colCondition
,
colConditionIndex
)
=>
{
// the condition of current cell
const
conditions
=
Object
.
assign
({},
rowCondition
,
colCondition
)
// filter the data
const
filterData
=
this
.
_filterData
(
conditions
,
this
.
localData
)
// empty cell
const
isEmptyCell
=
this
.
localRows
.
length
&&
this
.
localColumns
.
length
&&
!
this
.
localValues
.
length
const
_values
=
{}
// 多个值,多条数据
this
.
values
.
forEach
(({
key
,
handle
})
=>
{
_values
[
key
]
=
isEmptyCell
?
''
:
this
.
_reduceValue
(
filterData
,
key
)
})
return
Object
.
assign
({},
conditions
,
_values
)
})
.
flat
()
)
.
filter
((
item
)
=>
item
.
length
)
.
flat
()
)
},
_combinePaths
(...
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
''
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
})
},
// get min height by rowspan
_getMinHeightByRowCount
(
count
)
{
return
getHeightByCount
(
count
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
table
{
border-collapse
:
collapse
;
border-spacing
:
0
;
border
:
none
;
thead
th
{
background-color
:
#CCE8EB
;
}
tbody
{
tr
:
nth-child
(
odd
)
{
background
:
#fff
;
}
tr
:nth-child
(
even
)
{
background
:
#F5FAFA
;
}
}
td
,
th
{
border
:
1px
solid
#ccc
;
padding
:
0
;
vertical-align
:
middle
;
box-sizing
:
border-box
;
>
div
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
box-sizing
:
border-box
;
padding
:
5px
;
text-align
:
center
;
white-space
:
nowrap
;
width
:
100%
;
height
:
100%
;
min-height
:
36px
;
cursor
:
default
;
&.col-corner-bg
{
background
:
#f1f7fd
;
}
}
}
}
</
style
>
datax-ui/src/components/PivotTable/utils/constants.js
0 → 100644
View file @
ddca17e6
export
const
CELL_MIN_HEIGHT
=
38
export
const
SEPARATOR
=
':'
datax-ui/src/components/PivotTable/utils/convert_path_to_map.js
0 → 100644
View file @
ddca17e6
import
{
SEPARATOR
}
from
'./constants'
// Convert path to object
export
default
(
paths
,
keys
)
=>
{
return
paths
.
map
(
path
=>
{
const
pathArr
=
path
.
split
(
SEPARATOR
)
const
obj
=
{}
keys
.
forEach
((
key
,
index
)
=>
{
if
(
pathArr
[
index
])
{
obj
[
key
]
=
pathArr
[
index
]
}
})
return
obj
})
}
datax-ui/src/components/PivotTable/utils/get_height_by_count.js
0 → 100644
View file @
ddca17e6
import
{
CELL_MIN_HEIGHT
}
from
'./constants'
export
default
count
=>
count
*
CELL_MIN_HEIGHT
+
'px'
datax-ui/src/components/PivotTable/utils/index.js
0 → 100644
View file @
ddca17e6
import
mergeBaseInfo
from
'./merge_base_info'
import
convertPathToMap
from
'./convert_path_to_map'
import
getHeightByCount
from
'./get_height_by_count'
export
{
mergeBaseInfo
,
convertPathToMap
,
getHeightByCount
}
datax-ui/src/components/PivotTable/utils/merge_base_info.js
0 → 100644
View file @
ddca17e6
// merge base info
export
default
function
mergeBaseInfo
(
info
=
{})
{
const
_baseCellInfo
=
{
value
:
''
,
x
:
0
,
y
:
0
,
colspan
:
1
,
rowspan
:
1
}
return
Object
.
assign
({},
_baseCellInfo
,
info
)
}
datax-ui/src/views/visual/datachart/DataChartBuild.vue
View file @
ddca17e6
...
...
@@ -89,7 +89,7 @@
<el-tabs
type=
"card"
>
<el-tab-pane
label=
"图表预览"
>
<div
class=
"widget-center-pane-chart"
>
<chart-panel
v-if=
"visible"
id=
"chartPanel"
ref=
"chartPanel"
:chart-schema=
"widget"
:chart-data=
"
[]
"
/>
<chart-panel
v-if=
"visible"
id=
"chartPanel"
ref=
"chartPanel"
:chart-schema=
"widget"
:chart-data=
"
chartData.data
"
/>
</div>
</el-tab-pane>
<el-tab-pane
label=
"查询脚本"
>
...
...
datax-ui/src/views/visual/datachart/components/widgets/ChartTable.vue
View file @
ddca17e6
<
template
>
<div
ref=
"chart"
:style=
"chartStyle"
>
<my-chart-table
:col=
"tableCol"
:data=
"tableData"
/>
<div
ref=
"chart"
:style=
"chartStyle"
style=
"overflow: auto;"
>
<pivot-table
ref=
"pivottable"
:data=
"data"
:rows=
"rows"
:columns=
"columns"
:values=
"values"
/>
</div>
</
template
>
<
script
>
import
MyChartTable
from
'./charttable/MyChar
tTable'
import
PivotTable
from
'@/components/Pivo
tTable'
export
default
{
name
:
'ChartTable'
,
components
:
{
MyChar
tTable
Pivo
tTable
},
props
:
{
data
:
{
...
...
@@ -38,60 +44,34 @@ export default {
}
},
computed
:
{
tableCol
()
{
return
[
{
prop
:
'date'
,
label
:
'日期'
},
{
label
:
'配送信息'
,
children
:
[
{
prop
:
'name'
,
label
:
'姓名'
},
{
label
:
'地址'
,
children
:
[
{
prop
:
'province'
,
label
:
'省份'
},
{
prop
:
'city'
,
label
:
'市区'
},
{
prop
:
'address'
,
label
:
'地址'
}
]
}
]
rows
()
{
return
this
.
chartSchema
.
rows
.
map
((
row
,
index
,
arr
)
=>
{
return
{
key
:
`
${
row
.
col
}
`
,
label
:
`
${
row
.
col
}
`
}
})
},
columns
()
{
return
this
.
chartSchema
.
columns
.
map
((
column
,
index
,
arr
)
=>
{
return
{
key
:
`
${
column
.
col
}
`
,
label
:
`
${
column
.
col
}
`
}
]
})
},
tableData
()
{
return
[
{
date
:
'2016-05-03'
,
name
:
'王小虎'
,
province
:
'上海'
,
city
:
'普陀区'
,
address
:
'上海市普陀区金沙江路 1518 弄'
,
zip
:
200333
},
{
date
:
'2016-05-02'
,
name
:
'王小虎'
,
province
:
'上海'
,
city
:
'普陀区'
,
address
:
'上海市普陀区金沙江路 1518 弄'
,
zip
:
200333
values
()
{
return
this
.
chartSchema
.
measures
.
map
((
measure
,
index
,
arr
)
=>
{
return
{
key
:
`
${
measure
.
col
}
`
,
label
:
`
${
measure
.
col
}
`
}
]
})
}
},
created
()
{
console
.
log
(
this
.
data
)
console
.
log
(
this
.
chartSchema
)
}
}
</
script
>
...
...
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