views\chart\components\js\panel
This commit is contained in:
parent
9a8a763cf2
commit
40da16013a
@ -1,45 +1,98 @@
|
||||
<script lang="tsx" setup>
|
||||
import dvUpArrow from '@/assets/svg/dv-up-arrow.svg'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
defineProps({
|
||||
themes: {
|
||||
type: String,
|
||||
default: 'light'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="view-panel-Mask">
|
||||
<Icon class-name="item-icon" name="dv-up-arrow"><dvUpArrow class="svg-icon item-icon" /></Icon>
|
||||
<div>
|
||||
<el-button style="opacity: 1 !important" type="warning" size="mini" round>
|
||||
<span style="font-weight: bold; opacity: 1">{{
|
||||
t('visualization.template_view_tips')
|
||||
}}</span>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="view-panel-mask-left"></div>
|
||||
<div class="view-panel-mask">
|
||||
<el-popover
|
||||
:visible="true"
|
||||
placement="bottom"
|
||||
popper-class="template-popper-tips"
|
||||
:width="256"
|
||||
show-arrow
|
||||
>
|
||||
<div class="template-popper-tips-content">
|
||||
<p class="constant">{{ t('visualization.template_view_tips') }}</p>
|
||||
</div>
|
||||
<template #reference>
|
||||
<div
|
||||
class="view-panel-mask-inner"
|
||||
:class="{ 'view-panel-mask-inner-dark': themes === 'dark' }"
|
||||
></div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.view-panel-Mask {
|
||||
display: flex;
|
||||
height: calc(100vh - 148px);
|
||||
width: 100%;
|
||||
background-color: rgba(92, 94, 97, 0.7);
|
||||
.view-panel-mask-left {
|
||||
height: 100%;
|
||||
width: 240px;
|
||||
position: absolute;
|
||||
top: 85px;
|
||||
left: 0px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: not-allowed;
|
||||
background-color: rgba(31, 35, 41);
|
||||
opacity: 0.4;
|
||||
z-index: 2;
|
||||
}
|
||||
.view-panel-mask {
|
||||
height: 100%;
|
||||
width: 178px;
|
||||
background-color: rgba(31, 35, 41);
|
||||
opacity: 0.4;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 240px;
|
||||
z-index: 2;
|
||||
cursor: not-allowed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.view-panel-mask-inner {
|
||||
top: 51px;
|
||||
left: 6px;
|
||||
height: 34px;
|
||||
width: 170px;
|
||||
background: white;
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 300px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
opacity: 1;
|
||||
color: #ff8800;
|
||||
.view-panel-mask-inner-dark {
|
||||
background: rgba(31, 35, 41);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.template-popper-tips {
|
||||
z-index: 1000 !important;
|
||||
padding: 24px !important;
|
||||
box-shadow: none !important;
|
||||
border: 0 !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
inset: 0 auto auto -5px !important;
|
||||
.ed-popper__arrow::before {
|
||||
border: 1px solid var(--ed-color-primary) !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.template-popper-tips-content {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
.content {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,76 @@
|
||||
<script lang="ts" setup>
|
||||
import dvAi from '@/assets/svg/dv-ai.svg'
|
||||
import { ref } from 'vue'
|
||||
const visible = ref(true)
|
||||
</script>
|
||||
<template>
|
||||
<el-popover
|
||||
:visible="visible"
|
||||
placement="bottom"
|
||||
popper-class="ai-popper-tips"
|
||||
:width="288"
|
||||
show-arrow
|
||||
>
|
||||
<div class="ai-popper-tips-content">
|
||||
<p class="constant">
|
||||
你好,我是 DataEase 智能客服<br />点击一下,开启高效解答模式~<br />
|
||||
</p>
|
||||
</div>
|
||||
<template #reference>
|
||||
<div class="ai-popper-tips-icon">
|
||||
<el-icon style="margin: 2px" class="ai-icon">
|
||||
<Icon name="dv-ai"><dvAi class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.ai-popper-tips {
|
||||
z-index: 10001 !important;
|
||||
padding: 24px !important;
|
||||
box-shadow: none !important;
|
||||
border: 0px !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
.ed-popper__arrow::before {
|
||||
border: 1px solid var(--ed-color-primary) !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.ai-popper-tips-content {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
.title {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
}
|
||||
.content {
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
.bottom {
|
||||
line-height: 22px;
|
||||
text-align: right;
|
||||
button {
|
||||
border: 0px !important;
|
||||
border-color: #ffffff !important;
|
||||
font-weight: 500;
|
||||
color: rgba(51, 112, 255, 1) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-popper-tips-icon {
|
||||
margin: 0 8px;
|
||||
z-index: 10003;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
</style>
|
@ -318,6 +318,32 @@ export const DEFAULT_MISC: ChartMiscAttr = {
|
||||
min: 0,
|
||||
max: 0,
|
||||
fieldId: undefined
|
||||
},
|
||||
bullet: {
|
||||
bar: {
|
||||
ranges: {
|
||||
fill: ['rgba(0,128,255,0.3)'],
|
||||
size: 20,
|
||||
showType: 'dynamic',
|
||||
fixedRangeNumber: 3,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4
|
||||
},
|
||||
measures: {
|
||||
fill: ['rgba(0,128,255,1)'],
|
||||
size: 15,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4
|
||||
},
|
||||
target: {
|
||||
fill: 'rgb(0,0,0)',
|
||||
size: 20,
|
||||
showType: 'dynamic',
|
||||
value: 0,
|
||||
symbol: 'line',
|
||||
symbolSize: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -453,7 +479,8 @@ export const DEFAULT_TABLE_HEADER: ChartTableHeaderAttr = {
|
||||
headerGroupConfig: {
|
||||
columns: [],
|
||||
meta: []
|
||||
}
|
||||
},
|
||||
rowHeaderFreeze: true
|
||||
}
|
||||
export const DEFAULT_TABLE_CELL: ChartTableCellAttr = {
|
||||
tableFontColor: '#000000',
|
||||
@ -552,17 +579,6 @@ export const DEFAULT_TITLE_STYLE_DARK = {
|
||||
remarkBackgroundColor: '#5A5C62'
|
||||
}
|
||||
|
||||
export const DEFAULT_LEGEND_STYLE: ChartLegendStyle = {
|
||||
show: true,
|
||||
hPosition: 'center',
|
||||
vPosition: 'bottom',
|
||||
orient: 'horizontal',
|
||||
icon: 'circle',
|
||||
color: '#333333',
|
||||
fontSize: 12,
|
||||
size: 4
|
||||
}
|
||||
|
||||
export const DEFAULT_LEGEND_STYLE_BASE: ChartLegendStyle = {
|
||||
show: true,
|
||||
hPosition: 'center',
|
||||
@ -571,7 +587,24 @@ export const DEFAULT_LEGEND_STYLE_BASE: ChartLegendStyle = {
|
||||
icon: 'circle',
|
||||
color: '#333333',
|
||||
fontSize: 12,
|
||||
size: 4
|
||||
size: 4,
|
||||
showRange: true,
|
||||
sort: 'none',
|
||||
customSort: []
|
||||
}
|
||||
|
||||
export const DEFAULT_LEGEND_STYLE: ChartLegendStyle = {
|
||||
show: true,
|
||||
hPosition: 'center',
|
||||
vPosition: 'bottom',
|
||||
orient: 'horizontal',
|
||||
icon: 'circle',
|
||||
color: '#333333',
|
||||
fontSize: 12,
|
||||
size: 4,
|
||||
showRange: true,
|
||||
sort: 'none',
|
||||
customSort: []
|
||||
}
|
||||
|
||||
export const DEFAULT_LEGEND_STYLE_LIGHT: ChartLegendStyle = {
|
||||
@ -634,6 +667,7 @@ export const DEFAULT_XAXIS_STYLE: ChartAxisStyle = {
|
||||
},
|
||||
axisLabelFormatter: {
|
||||
type: 'auto',
|
||||
unitLanguage: isEnLocal ? 'en' : 'ch',
|
||||
unit: 1,
|
||||
suffix: '',
|
||||
decimalCount: 2,
|
||||
@ -680,6 +714,7 @@ export const DEFAULT_YAXIS_STYLE: ChartAxisStyle = {
|
||||
},
|
||||
axisLabelFormatter: {
|
||||
type: 'auto',
|
||||
unitLanguage: isEnLocal ? 'en' : 'ch',
|
||||
unit: 1,
|
||||
suffix: '',
|
||||
decimalCount: 2,
|
||||
@ -724,6 +759,7 @@ export const DEFAULT_YAXIS_EXT_STYLE: ChartAxisStyle = {
|
||||
},
|
||||
axisLabelFormatter: {
|
||||
type: 'auto',
|
||||
unitLanguage: isEnLocal ? 'en' : 'ch',
|
||||
unit: 1,
|
||||
suffix: '',
|
||||
decimalCount: 2,
|
||||
@ -1165,7 +1201,7 @@ export const CHART_FONT_FAMILY = [
|
||||
{ name: t('chart.font_family_kai_ti'), value: 'KaiTi' }
|
||||
]
|
||||
|
||||
export const CHART_FONT_FAMILY_MAP:any = {
|
||||
export const CHART_FONT_FAMILY_MAP = {
|
||||
'Microsoft YaHei': 'Microsoft YaHei',
|
||||
SimSun: 'SimSun, "Songti SC", STSong',
|
||||
SimHei: 'SimHei, Helvetica',
|
||||
@ -1395,6 +1431,13 @@ export const CHART_TYPE_CONFIGS = [
|
||||
value: 'stock-line',
|
||||
title: t('chart.chart_stock_line'),
|
||||
icon: 'stock-line'
|
||||
},
|
||||
{
|
||||
render: 'antv',
|
||||
category: 'compare',
|
||||
value: 'bullet-graph',
|
||||
title: t('chart.bullet_chart'),
|
||||
icon: 'bullet-graph'
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -1651,6 +1694,7 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
zoomButtonColor: '#aaa',
|
||||
zoomBackground: '#fff',
|
||||
tableLayoutMode: 'grid',
|
||||
defaultExpandLevel: 1,
|
||||
calcTopN: false,
|
||||
topN: 5,
|
||||
topNLabel: t('datasource.other'),
|
||||
@ -1679,7 +1723,9 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
radarAreaColor: true,
|
||||
circleBorderColor: '#fff',
|
||||
circleBorderWidth: 0,
|
||||
circlePadding: 0
|
||||
circlePadding: 0,
|
||||
quotaPosition: 'col',
|
||||
quotaColLabel: t('dataset.value')
|
||||
}
|
||||
|
||||
export const BASE_VIEW_CONFIG = {
|
||||
|
File diff suppressed because one or more lines are too long
@ -7,7 +7,6 @@ import {
|
||||
import {
|
||||
flow,
|
||||
hexColorToRGBA,
|
||||
hexToRgba,
|
||||
parseJson,
|
||||
setUpGroupSeriesColor,
|
||||
setUpStackSeriesColor
|
||||
@ -21,6 +20,7 @@ import {
|
||||
} from '@/data-visualization/chart/components/js/panel/charts/bar/common'
|
||||
import {
|
||||
configPlotTooltipEvent,
|
||||
configRoundAngle,
|
||||
getLabel,
|
||||
getPadding,
|
||||
getTooltipContainer,
|
||||
@ -43,7 +43,14 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
...BAR_EDITOR_PROPERTY_INNER,
|
||||
'basic-style-selector': [...BAR_EDITOR_PROPERTY_INNER['basic-style-selector'], 'seriesColor'],
|
||||
'label-selector': ['vPosition', 'seriesLabelFormatter', 'showExtremum'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'],
|
||||
'tooltip-selector': [
|
||||
'fontSize',
|
||||
'color',
|
||||
'backgroundColor',
|
||||
'seriesTooltipFormatter',
|
||||
'show',
|
||||
'carousel'
|
||||
],
|
||||
'y-axis-selector': [...BAR_EDITOR_PROPERTY_INNER['y-axis-selector'], 'axisLabelFormatter']
|
||||
}
|
||||
protected baseOptions: ColumnOptions = {
|
||||
@ -69,11 +76,14 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<Column>): Promise<Column> {
|
||||
const { chart, container, action } = drawOptions
|
||||
chart.container = container
|
||||
if (!chart?.data?.data?.length) {
|
||||
chart.container = container
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
const isGroup = 'bar-group' === this.name && chart.xAxisExt?.length > 0
|
||||
const isStack =
|
||||
['bar-stack', 'bar-group-stack'].includes(this.name) && chart.extStack?.length > 0
|
||||
const data = cloneDeep(drawOptions.chart.data?.data)
|
||||
const initOptions: ColumnOptions = {
|
||||
...this.baseOptions,
|
||||
@ -108,7 +118,7 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
const label = {
|
||||
fields: [],
|
||||
...tmpOptions.label,
|
||||
formatter: (data: Datum, _point) => {
|
||||
formatter: (data: Datum) => {
|
||||
if (data.EXTREME) {
|
||||
return ''
|
||||
}
|
||||
@ -174,19 +184,9 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
color
|
||||
}
|
||||
}
|
||||
if (basicStyle.radiusColumnBar === 'roundAngle') {
|
||||
const columnStyle = {
|
||||
radius: [
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius
|
||||
]
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
columnStyle
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
...configRoundAngle(chart, 'columnStyle')
|
||||
}
|
||||
let columnWidthRatio
|
||||
const _v = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio
|
||||
@ -227,7 +227,10 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
tickCount: axisValue.splitCount
|
||||
}
|
||||
}
|
||||
return { ...tmpOptions, ...axis }
|
||||
// 根据axis的最小值,过滤options中的data数据,过滤掉小于最小值的数据
|
||||
const { data } = options
|
||||
const newData = data.filter(item => item.value >= axisValue.min)
|
||||
return { ...tmpOptions, data: newData, ...axis }
|
||||
}
|
||||
return tmpOptions
|
||||
}
|
||||
@ -276,7 +279,14 @@ export class StackBar extends Bar {
|
||||
'totalFormatter',
|
||||
'showStackQuota'
|
||||
],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'tooltipFormatter', 'show']
|
||||
'tooltip-selector': [
|
||||
'fontSize',
|
||||
'color',
|
||||
'backgroundColor',
|
||||
'tooltipFormatter',
|
||||
'show',
|
||||
'carousel'
|
||||
]
|
||||
}
|
||||
protected configLabel(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
let label = getLabel(chart)
|
||||
@ -438,6 +448,74 @@ export class GroupBar extends StackBar {
|
||||
}
|
||||
}
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<Column>): Promise<Column> {
|
||||
const plot = await super.drawChart(drawOptions)
|
||||
if (!plot) {
|
||||
return plot
|
||||
}
|
||||
const { chart } = drawOptions
|
||||
const { xAxis, xAxisExt, yAxis } = chart
|
||||
let innerSort = !!(xAxis.length && xAxisExt.length && yAxis.length)
|
||||
if (innerSort && yAxis[0].sort === 'none') {
|
||||
innerSort = false
|
||||
}
|
||||
if (innerSort && xAxisExt[0].sort !== 'none') {
|
||||
const sortPriority = chart.sortPriority ?? []
|
||||
const yAxisIndex = sortPriority?.findIndex(e => e.id === yAxis[0].id)
|
||||
const xAxisExtIndex = sortPriority?.findIndex(e => e.id === xAxisExt[0].id)
|
||||
if (xAxisExtIndex <= yAxisIndex) {
|
||||
innerSort = false
|
||||
}
|
||||
}
|
||||
if (!innerSort) {
|
||||
return plot
|
||||
}
|
||||
plot.chart.once('beforepaint', () => {
|
||||
const geo = plot.chart.geometries[0]
|
||||
const originMapping = geo.beforeMapping.bind(geo)
|
||||
geo.beforeMapping = originData => {
|
||||
const values = geo.getXScale().values
|
||||
const valueMap = values.reduce((p, n) => {
|
||||
if (!p?.[n]) {
|
||||
p[n] = {
|
||||
fieldArr: [],
|
||||
indexArr: [],
|
||||
dataArr: []
|
||||
}
|
||||
}
|
||||
originData.forEach((arr, arrIndex) => {
|
||||
arr.forEach((item, index) => {
|
||||
if (item._origin.field === n) {
|
||||
p[n].fieldArr.push(item.field)
|
||||
p[n].indexArr.push([arrIndex, index])
|
||||
p[n].dataArr.push(item)
|
||||
}
|
||||
})
|
||||
})
|
||||
return p
|
||||
}, {})
|
||||
values.forEach(v => {
|
||||
const item = valueMap[v]
|
||||
item.dataArr.sort((a, b) => {
|
||||
if (yAxis[0].sort === 'asc') {
|
||||
return a.value - b.value
|
||||
}
|
||||
if (yAxis[0].sort === 'desc') {
|
||||
return b.value - a.value
|
||||
}
|
||||
return 0
|
||||
})
|
||||
item.indexArr.forEach((index, i) => {
|
||||
item.dataArr[i].field = item.fieldArr[i]
|
||||
originData[index[0]][index[1]] = item.dataArr[i]
|
||||
})
|
||||
})
|
||||
return originMapping(originData)
|
||||
}
|
||||
})
|
||||
return plot
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
const tmpLabel = getLabel(chart)
|
||||
if (!tmpLabel) {
|
||||
@ -448,7 +526,7 @@ export class GroupBar extends StackBar {
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum, _point) {
|
||||
formatter: function (param: Datum) {
|
||||
if (param.EXTREME) {
|
||||
return ''
|
||||
}
|
||||
@ -492,6 +570,7 @@ export class GroupBar extends StackBar {
|
||||
super(name)
|
||||
this.baseOptions = {
|
||||
...this.baseOptions,
|
||||
marginRatio: 0,
|
||||
isGroup: true,
|
||||
isStack: false,
|
||||
meta: {
|
||||
@ -606,7 +685,7 @@ export class PercentageStackBar extends GroupStackBar {
|
||||
propertyInner = {
|
||||
...this['propertyInner'],
|
||||
'label-selector': ['color', 'fontSize', 'vPosition', 'reserveDecimalCount'],
|
||||
'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'show']
|
||||
'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'show', 'carousel']
|
||||
}
|
||||
protected configLabel(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
const baseOptions = super.configLabel(chart, options)
|
||||
|
@ -6,14 +6,14 @@ import { cloneDeep, defaultTo, isEmpty, map } from 'lodash-es'
|
||||
import {
|
||||
configAxisLabelLengthLimit,
|
||||
configPlotTooltipEvent,
|
||||
configRoundAngle,
|
||||
getPadding,
|
||||
getTooltipContainer,
|
||||
getTooltipItemConditionColor,
|
||||
getYAxis,
|
||||
getYAxisExt,
|
||||
setGradientColor,
|
||||
TOOLTIP_TPL,
|
||||
addConditionsStyleColorToData
|
||||
TOOLTIP_TPL
|
||||
} from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import type {
|
||||
BidirectionalBar as G2BidirectionalBar,
|
||||
@ -213,19 +213,9 @@ export class BidirectionalHorizontalBar extends G2PlotChartView<
|
||||
...options,
|
||||
layout: basicStyle.layout
|
||||
}
|
||||
if (basicStyle.radiusColumnBar === 'roundAngle') {
|
||||
const barStyle = {
|
||||
radius: [
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius
|
||||
]
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
barStyle
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
...configRoundAngle(chart, 'barStyle')
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
@ -0,0 +1,507 @@
|
||||
import type {
|
||||
Bullet as G2Bullet,
|
||||
BulletOptions as G2BulletOptions
|
||||
} from '@antv/g2plot/esm/plots/bullet'
|
||||
import {
|
||||
G2PlotChartView,
|
||||
G2PlotDrawOptions
|
||||
} from '@/data-visualization/chart/components/js/panel/types/impl/g2plot'
|
||||
import {
|
||||
BAR_AXIS_TYPE,
|
||||
BAR_EDITOR_PROPERTY,
|
||||
BAR_EDITOR_PROPERTY_INNER
|
||||
} from '@/data-visualization/chart/components/js/panel/charts/bar/common'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { flow, parseJson } from '@/data-visualization/chart/components/js/util'
|
||||
import { BulletOptions } from '@antv/g2plot'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import {
|
||||
configAxisLabelLengthLimit,
|
||||
configPlotTooltipEvent,
|
||||
getPadding,
|
||||
getTooltipContainer,
|
||||
TOOLTIP_TPL
|
||||
} from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import { valueFormatter } from '@/data-visualization/chart/components/js/formatter'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
/**
|
||||
* 子弹图
|
||||
*/
|
||||
export class BulletGraph extends G2PlotChartView<G2BulletOptions, G2Bullet> {
|
||||
constructor() {
|
||||
super('bullet-graph', [])
|
||||
}
|
||||
|
||||
axis: AxisType[] = [...BAR_AXIS_TYPE, 'yAxisExt', 'extBubble']
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: { name: `${t('chart.form_type')} / ${t('chart.dimension')}`, type: 'd', limit: 1 },
|
||||
yAxis: { name: `${t('chart.progress_current')} / ${t('chart.quota')}`, type: 'q', limit: 1 },
|
||||
yAxisExt: { name: `${t('chart.progress_target')} / ${t('chart.quota')}`, type: 'q', limit: 1 },
|
||||
extBubble: {
|
||||
name: `${t('chart.range_bg')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
allowEmpty: true,
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
properties: EditorProperty[] = [
|
||||
...BAR_EDITOR_PROPERTY.filter(
|
||||
item => !['function-cfg', 'assist-line', 'threshold'].includes(item)
|
||||
),
|
||||
'bullet-graph-selector'
|
||||
]
|
||||
propertyInner = {
|
||||
'basic-style-selector': ['radiusColumnBar', 'layout'],
|
||||
'label-selector': ['hPosition', 'fontSize', 'color', 'labelFormatter'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'],
|
||||
'x-axis-selector': [
|
||||
...BAR_EDITOR_PROPERTY_INNER['x-axis-selector'].filter(item => item != 'position'),
|
||||
'showLengthLimit'
|
||||
],
|
||||
'y-axis-selector': [
|
||||
...BAR_EDITOR_PROPERTY_INNER['y-axis-selector'].filter(
|
||||
item => item !== 'axisValue' && item !== 'position'
|
||||
),
|
||||
'axisLabelFormatter'
|
||||
],
|
||||
'legend-selector': ['showRange', 'orient', 'fontSize', 'color', 'hPosition', 'vPosition']
|
||||
}
|
||||
|
||||
async drawChart(drawOption: G2PlotDrawOptions<G2Bullet>): Promise<G2Bullet> {
|
||||
const { chart, container, action } = drawOption
|
||||
if (!chart.data?.data?.length) return
|
||||
const result = mergeBulletData(chart)
|
||||
// 处理自定义区间
|
||||
const { bullet } = parseJson(chart.customAttr).misc
|
||||
if (bullet.bar.ranges.showType === 'fixed') {
|
||||
const customRange = bullet.bar.ranges.fixedRange?.map(item => item.fixedRangeValue) || [0]
|
||||
result.forEach(item => (item.ranges = customRange))
|
||||
} else {
|
||||
result.forEach(item => (item.ranges = item.originalRanges))
|
||||
}
|
||||
// 处理自定义目标值
|
||||
if (bullet.bar.target.showType === 'fixed') {
|
||||
const customTarget = bullet.bar.target.value || 0
|
||||
result.forEach(item => (item.target = customTarget))
|
||||
} else {
|
||||
result.forEach(item => (item.target = item.originalTarget))
|
||||
}
|
||||
const initialOptions: BulletOptions = {
|
||||
appendPadding: getPadding(chart),
|
||||
data: result.reverse(),
|
||||
measureField: 'measures',
|
||||
rangeField: 'ranges',
|
||||
targetField: 'target',
|
||||
xField: 'title',
|
||||
meta: {
|
||||
title: {
|
||||
type: 'cat'
|
||||
}
|
||||
},
|
||||
interactions: [
|
||||
{
|
||||
type: 'active-region',
|
||||
cfg: {
|
||||
start: [{ trigger: 'element:mousemove', action: 'active-region:show' }],
|
||||
end: [{ trigger: 'element:mouseleave', action: 'active-region:hide' }]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
const options = this.setupOptions(chart, initialOptions)
|
||||
let newChart = null
|
||||
const { Bullet: BulletClass } = await import('@antv/g2plot/esm/plots/bullet')
|
||||
newChart = new BulletClass(container, options)
|
||||
newChart.on('element:click', ev => {
|
||||
const pointData = ev?.data?.data
|
||||
const dimensionList = options.data.find(item => item.title === pointData.title)?.dimensionList
|
||||
const actionParams = {
|
||||
x: ev.x,
|
||||
y: ev.y,
|
||||
data: {
|
||||
data: {
|
||||
...pointData,
|
||||
dimensionList
|
||||
}
|
||||
}
|
||||
}
|
||||
action(actionParams)
|
||||
})
|
||||
configPlotTooltipEvent(chart, newChart)
|
||||
configAxisLabelLengthLimit(chart, newChart, null)
|
||||
return newChart
|
||||
}
|
||||
|
||||
protected configBasicStyle(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const basicStyle = parseJson(chart.customAttr).basicStyle
|
||||
const { radiusColumnBar, columnBarRightAngleRadius, layout } = basicStyle
|
||||
let radiusValue = 0
|
||||
let rangeLength = 1
|
||||
if (radiusColumnBar === 'roundAngle' || radiusColumnBar === 'topRoundAngle') {
|
||||
radiusValue = columnBarRightAngleRadius
|
||||
rangeLength = options.data[0]?.ranges?.length
|
||||
}
|
||||
const barRadiusStyle = { radius: Array(2).fill(radiusValue) }
|
||||
const baseRadius = [...barRadiusStyle.radius, ...barRadiusStyle.radius]
|
||||
options = {
|
||||
...options,
|
||||
bulletStyle: {
|
||||
range: datum => {
|
||||
if (!datum.rKey) return { fill: 'rgba(0, 0, 0, 0)' }
|
||||
if (rangeLength === 1) {
|
||||
return {
|
||||
radius:
|
||||
radiusColumnBar === 'topRoundAngle' ? [...barRadiusStyle.radius, 0, 0] : baseRadius
|
||||
}
|
||||
}
|
||||
if (rangeLength > 1 && datum.rKey === 'ranges_0') {
|
||||
return {
|
||||
radius: radiusColumnBar === 'topRoundAngle' ? [] : [0, 0, ...barRadiusStyle.radius]
|
||||
}
|
||||
}
|
||||
if (rangeLength > 1 && datum.rKey === 'ranges_' + (rangeLength - 1)) {
|
||||
return { radius: [...barRadiusStyle.radius, 0, 0] }
|
||||
}
|
||||
},
|
||||
measure: datum => {
|
||||
if (datum.measures) {
|
||||
return {
|
||||
radius:
|
||||
radiusColumnBar === 'topRoundAngle' ? [...barRadiusStyle.radius, 0, 0] : baseRadius
|
||||
}
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
target: datum => (datum.tKey === 'target' ? { lineWidth: 2 } : undefined)
|
||||
}
|
||||
}
|
||||
if (layout === 'vertical') options = { ...options, layout: 'vertical' }
|
||||
return options
|
||||
}
|
||||
|
||||
protected configMisc(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const { bullet } = parseJson(chart.customAttr).misc
|
||||
const isDynamic = bullet.bar.ranges.showType === 'dynamic'
|
||||
// 动态背景按大小升序
|
||||
const rangeColor = isDynamic
|
||||
? bullet.bar.ranges.fill
|
||||
: bullet.bar.ranges.fixedRange
|
||||
?.sort((a, b) => (a.fixedRangeValue ?? 0) - (b.fixedRangeValue ?? 0))
|
||||
.map(item => item.fill) || []
|
||||
return {
|
||||
...options,
|
||||
color: {
|
||||
measure: [].concat(bullet.bar.measures.fill),
|
||||
range: [].concat(rangeColor),
|
||||
target: [].concat(bullet.bar.target.fill)
|
||||
},
|
||||
size: {
|
||||
measure: bullet.bar.measures.size,
|
||||
range: bullet.bar.ranges.size,
|
||||
target: bullet.bar.target.size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected configXAxis(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const tmpOptions = super.configXAxis(chart, options)
|
||||
if (!tmpOptions.xAxis || !tmpOptions.xAxis.label) return tmpOptions
|
||||
|
||||
const { layout, xAxis } = tmpOptions
|
||||
const position = xAxis.position
|
||||
const style: any = { ...xAxis.label.style }
|
||||
|
||||
if (layout === 'vertical') {
|
||||
style.textAlign = 'center'
|
||||
style.textBaseline = position === 'bottom' ? 'top' : 'bottom'
|
||||
} else {
|
||||
style.textAlign = position === 'bottom' ? 'end' : 'start'
|
||||
style.textBaseline = 'middle'
|
||||
}
|
||||
|
||||
xAxis.label.style = style
|
||||
return tmpOptions
|
||||
}
|
||||
|
||||
protected configYAxis(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const tmpOptions = super.configYAxis(chart, options)
|
||||
if (!tmpOptions.yAxis || !tmpOptions.yAxis.label) return tmpOptions
|
||||
|
||||
const yAxis = parseJson(chart.customStyle).yAxis
|
||||
tmpOptions.yAxis.label.formatter = value => valueFormatter(value, yAxis.axisLabelFormatter)
|
||||
|
||||
const { layout, yAxis: yAxisConfig } = tmpOptions
|
||||
const position = yAxisConfig.position
|
||||
const style: any = { ...yAxisConfig.label.style }
|
||||
|
||||
if (layout === 'vertical') {
|
||||
style.textAlign = position === 'left' ? 'end' : 'start'
|
||||
style.textBaseline = 'middle'
|
||||
} else {
|
||||
style.textAlign = 'center'
|
||||
style.textBaseline = position === 'left' ? 'top' : 'bottom'
|
||||
}
|
||||
|
||||
yAxisConfig.label.style = style
|
||||
return tmpOptions
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const tmpOptions = super.configLabel(chart, options)
|
||||
if (!tmpOptions.label) return tmpOptions
|
||||
|
||||
const labelAttr = parseJson(chart.customAttr).label
|
||||
const label: any = {
|
||||
...tmpOptions.label,
|
||||
formatter: param =>
|
||||
param.mKey === 'measures'
|
||||
? valueFormatter(param.measures, labelAttr.labelFormatter)
|
||||
: undefined
|
||||
}
|
||||
return { ...tmpOptions, label: { measure: label } }
|
||||
}
|
||||
|
||||
protected configLegend(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const baseLegend = super.configLegend(chart, options).legend
|
||||
if (!baseLegend) return options
|
||||
|
||||
const { bullet } = parseJson(chart.customAttr).misc
|
||||
const customStyleLegend = parseJson(chart.customStyle).legend
|
||||
const items = []
|
||||
|
||||
const createLegendItem = (value, name, symbol, fill, size = 4) => ({
|
||||
value,
|
||||
name,
|
||||
marker: { symbol, style: { fill, stroke: value === 'measure' ? '' : fill, r: size } }
|
||||
})
|
||||
|
||||
if (customStyleLegend.showRange) {
|
||||
if (bullet.bar.ranges.showType === 'dynamic') {
|
||||
if (chart.extBubble.length) {
|
||||
const rangeName = chart.extBubble[0]?.chartShowName || bullet.bar.ranges.name
|
||||
items.push(
|
||||
createLegendItem(
|
||||
'dynamic',
|
||||
rangeName || chart.extBubble[0]?.name,
|
||||
bullet.bar.ranges.symbol,
|
||||
[].concat(bullet.bar.ranges.fill)[0],
|
||||
bullet.bar.ranges.symbolSize
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
bullet.bar.ranges.fixedRange?.forEach(item => {
|
||||
items.push(
|
||||
createLegendItem(
|
||||
item.name,
|
||||
item.name,
|
||||
bullet.bar.ranges.symbol,
|
||||
item.fill,
|
||||
bullet.bar.ranges.symbolSize
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const targetName = chart.yAxisExt[0]?.chartShowName || bullet.bar.target.name
|
||||
items.push(
|
||||
createLegendItem(
|
||||
'target',
|
||||
targetName || chart.yAxisExt[0]?.name,
|
||||
'line',
|
||||
[].concat(bullet.bar.target.fill)[0],
|
||||
bullet.bar.ranges.symbolSize
|
||||
)
|
||||
)
|
||||
|
||||
const measureName = chart.yAxis[0]?.chartShowName || bullet.bar.measures.name
|
||||
items.push(
|
||||
createLegendItem(
|
||||
'measure',
|
||||
measureName || chart.yAxis[0]?.name,
|
||||
'square',
|
||||
[].concat(bullet.bar.measures.fill)[0],
|
||||
bullet.bar.ranges.symbolSize
|
||||
)
|
||||
)
|
||||
|
||||
return {
|
||||
...options,
|
||||
legend: { custom: true, position: baseLegend.position, layout: baseLegend.layout, items }
|
||||
}
|
||||
}
|
||||
|
||||
protected configTooltip(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
const customAttr: DeepPartial<ChartAttr> = parseJson(chart.customAttr)
|
||||
const tooltipAttr = customAttr.tooltip
|
||||
const { bullet } = parseJson(chart.customAttr).misc
|
||||
if (!tooltipAttr.show) return { ...options, tooltip: false }
|
||||
|
||||
const formatterMap = tooltipAttr.seriesTooltipFormatter
|
||||
?.filter(i => i.show)
|
||||
.reduce((pre, next, index) => {
|
||||
const keys = ['measures', 'target', 'ranges']
|
||||
if (keys[index]) pre[keys[index]] = next
|
||||
return pre
|
||||
}, {}) as Record<string, SeriesFormatter>
|
||||
|
||||
const tooltip = {
|
||||
shared: true,
|
||||
showMarkers: true,
|
||||
customItems(originalItems) {
|
||||
if (!tooltipAttr.seriesTooltipFormatter?.length) return originalItems
|
||||
|
||||
const result = []
|
||||
const data = options.data.find(item => item.title === originalItems[0].title)
|
||||
Object.keys(formatterMap).forEach(key => {
|
||||
if (key === '记录数*') return
|
||||
const formatter = formatterMap[key]
|
||||
if (formatter) {
|
||||
if (key !== 'ranges') {
|
||||
let value = 0
|
||||
if (chart.yAxis[0].id === chart.yAxisExt[0].id) {
|
||||
value = valueFormatter(parseFloat(data['target'] as string), formatter.formatterCfg)
|
||||
} else {
|
||||
value = valueFormatter(parseFloat(data[key] as string), formatter.formatterCfg)
|
||||
}
|
||||
const name = isEmpty(formatter.chartShowName)
|
||||
? formatter.name
|
||||
: formatter.chartShowName
|
||||
result.push({ ...originalItems[0], color: bullet.bar[key].fill, name, value })
|
||||
} else {
|
||||
const ranges = data.ranges
|
||||
const isDynamic = bullet.bar.ranges.showType === 'dynamic'
|
||||
ranges.forEach((range, index) => {
|
||||
const value = valueFormatter(
|
||||
parseFloat(isDynamic ? data.minRanges[0] : (range as string)),
|
||||
formatter.formatterCfg
|
||||
)
|
||||
let name = ''
|
||||
let color: string | string[]
|
||||
if (bullet.bar.ranges.showType === 'dynamic') {
|
||||
name = isEmpty(formatter.chartShowName) ? formatter.name : formatter.chartShowName
|
||||
color = bullet.bar[key].fill
|
||||
} else {
|
||||
const customRange = bullet.bar.ranges.fixedRange[index].name
|
||||
name = customRange
|
||||
? customRange
|
||||
: isEmpty(formatter.chartShowName)
|
||||
? formatter.name
|
||||
: formatter.chartShowName
|
||||
color = bullet.bar[key].fixedRange[index].fill
|
||||
}
|
||||
result.push({ ...originalItems[0], color, name, value })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
const dynamicTooltipValue = chart.data.data.find(
|
||||
d => d.field === originalItems[0]['title']
|
||||
)?.dynamicTooltipValue
|
||||
if (dynamicTooltipValue.length > 0) {
|
||||
dynamicTooltipValue.forEach(dy => {
|
||||
const q = tooltipAttr.seriesTooltipFormatter.filter(i => i.id === dy.fieldId)
|
||||
if (q && q.length > 0) {
|
||||
const value = valueFormatter(parseFloat(dy.value as string), q[0].formatterCfg)
|
||||
const name = isEmpty(q[0].chartShowName) ? q[0].name : q[0].chartShowName
|
||||
result.push({ color: 'grey', name, value })
|
||||
}
|
||||
})
|
||||
}
|
||||
return result
|
||||
},
|
||||
container: getTooltipContainer(`tooltip-${chart.id}`),
|
||||
itemTpl: TOOLTIP_TPL,
|
||||
enterable: true
|
||||
}
|
||||
return { ...options, tooltip }
|
||||
}
|
||||
|
||||
setupDefaultOptions(chart: ChartObj): ChartObj {
|
||||
chart.customAttr.label.position = 'middle'
|
||||
chart.customStyle.yAxis.splitLine.show = false
|
||||
return super.setupDefaultOptions(chart)
|
||||
}
|
||||
|
||||
protected setupOptions(chart: Chart, options: BulletOptions): BulletOptions {
|
||||
return flow(
|
||||
this.configTheme,
|
||||
this.configBasicStyle,
|
||||
this.configMisc,
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configLabel,
|
||||
this.configLegend,
|
||||
this.configTooltip
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装子弹图数据
|
||||
* @param chart
|
||||
*/
|
||||
function mergeBulletData(chart): any[] {
|
||||
// 先根据维度分组,再根据指标字段组装成子弹图的格式
|
||||
const groupedData = chart.data.data.reduce((acc, item) => {
|
||||
const field = item.field
|
||||
if (!acc[field]) {
|
||||
acc[field] = []
|
||||
}
|
||||
acc[field].push(item)
|
||||
return acc
|
||||
}, {})
|
||||
const result = []
|
||||
// 组装子弹图数据,每个维度对应一个子弹图
|
||||
Object.keys(groupedData).forEach(field => {
|
||||
const items = groupedData[field]
|
||||
// 初始化子弹图条目结构
|
||||
const entry = {
|
||||
title: field,
|
||||
ranges: [],
|
||||
measures: [],
|
||||
target: [],
|
||||
dimensionList: items[0].dimensionList,
|
||||
quotaList: []
|
||||
}
|
||||
|
||||
// 防止指标相同时无数据有可能会导致数据不一致
|
||||
items.forEach(item => {
|
||||
const quotaId = item.quotaList[0]?.id
|
||||
const v = item.value || 0
|
||||
if (quotaId === chart.yAxis[0]?.id) {
|
||||
entry.measures.push(v)
|
||||
}
|
||||
if (quotaId === chart.yAxisExt[0]?.id) {
|
||||
entry.target.push(v)
|
||||
}
|
||||
if (quotaId === chart.extBubble[0]?.id) {
|
||||
entry.ranges.push(v)
|
||||
}
|
||||
entry.quotaList.push(item.quotaList[0])
|
||||
})
|
||||
// 对数据进行累加
|
||||
const ranges = chart.extBubble[0]?.id
|
||||
? [].concat(entry.ranges?.reduce((acc, curr) => acc + curr, 0))
|
||||
: []
|
||||
const target = [].concat(entry.target?.reduce((acc, curr) => acc + curr, 0))
|
||||
const measures = [].concat(entry.measures?.reduce((acc, curr) => acc + curr, 0))
|
||||
const bulletData = {
|
||||
...entry,
|
||||
measures: measures,
|
||||
target: target,
|
||||
ranges: ranges,
|
||||
quotaList: [...entry.quotaList],
|
||||
minRanges: ranges,
|
||||
originalRanges: ranges,
|
||||
originalTarget: target
|
||||
}
|
||||
result.push(bulletData)
|
||||
})
|
||||
return result
|
||||
}
|
@ -6,6 +6,7 @@ import type { Bar, BarOptions } from '@antv/g2plot/esm/plots/bar'
|
||||
import {
|
||||
configAxisLabelLengthLimit,
|
||||
configPlotTooltipEvent,
|
||||
configRoundAngle,
|
||||
getPadding,
|
||||
getTooltipContainer,
|
||||
setGradientColor,
|
||||
@ -101,6 +102,17 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
const newChart = new Bar(container, options)
|
||||
|
||||
newChart.on('interval:click', action)
|
||||
if (options.label) {
|
||||
newChart.on('label:click', e => {
|
||||
action({
|
||||
x: e.x,
|
||||
y: e.y,
|
||||
data: {
|
||||
data: e.target.attrs.data
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
configPlotTooltipEvent(chart, newChart)
|
||||
configAxisLabelLengthLimit(chart, newChart)
|
||||
return newChart
|
||||
@ -135,7 +147,10 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
tickCount: axisValue.splitCount
|
||||
}
|
||||
}
|
||||
return { ...tmpOptions, ...axis }
|
||||
// 根据axis的最小值,过滤options中的data数据,过滤掉小于最小值的数据
|
||||
const { data } = options
|
||||
const newData = data.filter(item => item.value >= axisValue.min)
|
||||
return { ...tmpOptions, data: newData, ...axis }
|
||||
}
|
||||
return tmpOptions
|
||||
}
|
||||
@ -157,19 +172,9 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
color
|
||||
}
|
||||
}
|
||||
if (basicStyle.radiusColumnBar === 'roundAngle') {
|
||||
const barStyle = {
|
||||
radius: [
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius
|
||||
]
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
barStyle
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
...configRoundAngle(chart, 'barStyle')
|
||||
}
|
||||
|
||||
let barWidthRatio
|
||||
@ -234,6 +239,7 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
attrs: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
data,
|
||||
text: value,
|
||||
textAlign: 'start',
|
||||
textBaseline: 'top',
|
||||
@ -316,8 +322,24 @@ export class HorizontalStackBar extends HorizontalBar {
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum) {
|
||||
return valueFormatter(param.value, labelAttr.labelFormatter)
|
||||
formatter: function (data: Datum) {
|
||||
const value = valueFormatter(data.value, labelAttr.labelFormatter)
|
||||
const group = new Group({})
|
||||
group.addShape({
|
||||
type: 'text',
|
||||
attrs: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
data,
|
||||
text: value,
|
||||
textAlign: 'start',
|
||||
textBaseline: 'top',
|
||||
fontSize: labelAttr.fontSize,
|
||||
fontFamily: chart.fontFamily,
|
||||
fill: labelAttr.color
|
||||
}
|
||||
})
|
||||
return group
|
||||
}
|
||||
}
|
||||
return {
|
||||
@ -435,11 +457,29 @@ export class HorizontalPercentageStackBar extends HorizontalStackBar {
|
||||
const l = parseJson(customAttr).label
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum) {
|
||||
if (!param.value) {
|
||||
return '0%'
|
||||
formatter: function (data: Datum) {
|
||||
let value = data.value
|
||||
if (value) {
|
||||
value = (Math.round(value * 10000) / 100).toFixed(l.reserveDecimalCount) + '%'
|
||||
} else {
|
||||
value = '0%'
|
||||
}
|
||||
return (Math.round(param.value * 10000) / 100).toFixed(l.reserveDecimalCount) + '%'
|
||||
const group = new Group({})
|
||||
group.addShape({
|
||||
type: 'text',
|
||||
attrs: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
data,
|
||||
text: value,
|
||||
textAlign: 'start',
|
||||
textBaseline: 'top',
|
||||
fontSize: l.fontSize,
|
||||
fontFamily: chart.fontFamily,
|
||||
fill: l.color
|
||||
}
|
||||
})
|
||||
return group
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
@ -3,8 +3,8 @@ import { flow, hexColorToRGBA, parseJson } from '../../../util'
|
||||
import {
|
||||
configAxisLabelLengthLimit,
|
||||
configPlotTooltipEvent,
|
||||
configRoundAngle,
|
||||
getTooltipContainer,
|
||||
getTooltipItemConditionColor,
|
||||
setGradientColor,
|
||||
TOOLTIP_TPL
|
||||
} from '../../common/common_antv'
|
||||
@ -66,7 +66,7 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
'fontSize',
|
||||
'axisForm',
|
||||
'axisLabel',
|
||||
'position',
|
||||
// 'position',
|
||||
'showLengthLimit'
|
||||
],
|
||||
'function-cfg': ['emptyDataStrategy'],
|
||||
@ -166,6 +166,7 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
}
|
||||
})
|
||||
if (basicStyle.gradient) {
|
||||
// eslint-disable-next-line
|
||||
color1 = color1.map((ele, _index) => {
|
||||
return setGradientColor(ele, true, 0)
|
||||
})
|
||||
@ -184,19 +185,9 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (basicStyle.radiusColumnBar === 'roundAngle') {
|
||||
const barStyle = {
|
||||
radius: [
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius
|
||||
]
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
barStyle
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
...configRoundAngle(chart, 'barStyle')
|
||||
}
|
||||
|
||||
let barWidthRatio
|
||||
@ -297,12 +288,31 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
if (!baseOption.yAxis) {
|
||||
return baseOption
|
||||
}
|
||||
if (baseOption.yAxis.position === 'left') {
|
||||
baseOption.yAxis.position = 'bottom'
|
||||
const yAxis = parseJson(chart.customStyle).yAxis
|
||||
if (yAxis.axisLabel.show) {
|
||||
const rotate = yAxis.axisLabel.rotate
|
||||
let textAlign = 'end'
|
||||
let textBaseline = 'middle'
|
||||
if (Math.abs(rotate) > 75) {
|
||||
textAlign = 'center'
|
||||
}
|
||||
if (rotate > 75) {
|
||||
textBaseline = 'top'
|
||||
}
|
||||
if (rotate < -75) {
|
||||
textBaseline = 'bottom'
|
||||
}
|
||||
baseOption.yAxis.label.style.textBaseline = textBaseline
|
||||
baseOption.yAxis.label.style.textAlign = textAlign
|
||||
}
|
||||
|
||||
/*if (baseOption.yAxis.position === 'left') {
|
||||
baseOption.yAxis.position = 'bottom'
|
||||
}
|
||||
if (baseOption.yAxis.position === 'right') {
|
||||
baseOption.yAxis.position = 'top'
|
||||
}
|
||||
}*/
|
||||
return baseOption
|
||||
}
|
||||
setupDefaultOptions(chart: ChartObj): ChartObj {
|
||||
|
@ -6,6 +6,7 @@ import type { Bar, BarOptions } from '@antv/g2plot/esm/plots/bar'
|
||||
import {
|
||||
configAxisLabelLengthLimit,
|
||||
configPlotTooltipEvent,
|
||||
configRoundAngle,
|
||||
getPadding,
|
||||
getTooltipContainer,
|
||||
setGradientColor,
|
||||
@ -22,6 +23,7 @@ import {
|
||||
import { Datum } from '@antv/g2plot/esm/types/common'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { DEFAULT_BASIC_STYLE } from '@/data-visualization/chart/components/editor/util/chart'
|
||||
import { Group } from '@antv/g-canvas'
|
||||
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA = []
|
||||
@ -170,6 +172,17 @@ export class RangeBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
const newChart = new BarClass(container, options)
|
||||
|
||||
newChart.on('interval:click', action)
|
||||
if (options.label) {
|
||||
newChart.on('label:click', e => {
|
||||
action({
|
||||
x: e.x,
|
||||
y: e.y,
|
||||
data: {
|
||||
data: e.target.attrs.data
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
configPlotTooltipEvent(chart, newChart)
|
||||
configAxisLabelLengthLimit(chart, newChart)
|
||||
return newChart
|
||||
@ -309,19 +322,10 @@ export class RangeBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (basicStyle.radiusColumnBar === 'roundAngle') {
|
||||
const barStyle = {
|
||||
radius: [
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius,
|
||||
basicStyle.columnBarRightAngleRadius
|
||||
]
|
||||
}
|
||||
options = {
|
||||
...options,
|
||||
barStyle
|
||||
}
|
||||
|
||||
options = {
|
||||
...options,
|
||||
...configRoundAngle(chart, 'barStyle')
|
||||
}
|
||||
let barWidthRatio
|
||||
const _v = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio
|
||||
@ -391,7 +395,22 @@ export class RangeBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
valueFormatter(param.values[1], labelAttr.labelFormatter)
|
||||
}
|
||||
}
|
||||
return res
|
||||
const group = new Group({})
|
||||
group.addShape({
|
||||
type: 'text',
|
||||
attrs: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
data: param,
|
||||
text: res,
|
||||
textAlign: 'start',
|
||||
textBaseline: 'top',
|
||||
fontSize: labelAttr.fontSize,
|
||||
fontFamily: chart.fontFamily,
|
||||
fill: labelAttr.color
|
||||
}
|
||||
})
|
||||
return group
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
@ -72,7 +72,8 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
'axisForm',
|
||||
'axisLabel',
|
||||
'axisLabelFormatter',
|
||||
'showLengthLimit'
|
||||
'showLengthLimit',
|
||||
'axisLine'
|
||||
],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
|
||||
'label-selector': ['seriesLabelVPosition', 'seriesLabelFormatter', 'showExtremum'],
|
||||
'tooltip-selector': [
|
||||
...LINE_EDITOR_PROPERTY_INNER['tooltip-selector'],
|
||||
'seriesTooltipFormatter'
|
||||
'seriesTooltipFormatter',
|
||||
'carousel'
|
||||
]
|
||||
}
|
||||
axis: AxisType[] = [...LINE_AXIS_TYPE]
|
||||
@ -103,8 +104,8 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Area>): Promise<G2Area> {
|
||||
const { chart, container, action } = drawOptions
|
||||
chart.container = container
|
||||
if (!chart.data?.data?.length) {
|
||||
chart.container = container
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
@ -147,7 +148,7 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
|
||||
fields: [],
|
||||
...tmpOptions.label,
|
||||
layout: labelAttr.fullDisplay ? [{ type: 'limit-in-plot' }] : tmpOptions.label.layout,
|
||||
formatter: (data: Datum, _point) => {
|
||||
formatter: (data: Datum) => {
|
||||
if (data.EXTREME) {
|
||||
return ''
|
||||
}
|
||||
@ -305,7 +306,7 @@ export class StackArea extends Area {
|
||||
propertyInner = {
|
||||
...this['propertyInner'],
|
||||
'label-selector': ['vPosition', 'fontSize', 'color', 'labelFormatter'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'tooltipFormatter', 'show']
|
||||
'tooltip-selector': ['fontSize', 'color', 'tooltipFormatter', 'show', 'carousel']
|
||||
}
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
|
673
frontend/src/data-visualization/chart/components/js/panel/charts/line/dist/stock-line.js
vendored
Normal file
673
frontend/src/data-visualization/chart/components/js/panel/charts/line/dist/stock-line.js
vendored
Normal file
@ -0,0 +1,673 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.StockLine = void 0;
|
||||
var g2plot_1 = require("@/views/chart/components/js/panel/types/impl/g2plot");
|
||||
var util_1 = require("@/views/chart/components/js/util");
|
||||
var common_1 = require("@/views/chart/components/js/panel/charts/line/common");
|
||||
var useI18n_1 = require("@/hooks/web/useI18n");
|
||||
var formatter_1 = require("@/views/chart/components/js/formatter");
|
||||
var t = useI18n_1.useI18n().t;
|
||||
var DEFAULT_DATA = [];
|
||||
/**
|
||||
* K线图
|
||||
*/
|
||||
var StockLine = /** @class */ (function (_super) {
|
||||
__extends(StockLine, _super);
|
||||
function StockLine(name) {
|
||||
if (name === void 0) { name = 'stock-line'; }
|
||||
var _this = _super.call(this, name, DEFAULT_DATA) || this;
|
||||
_this.properties = [
|
||||
'background-overall-component',
|
||||
'border-style',
|
||||
'basic-style-selector',
|
||||
'legend-selector',
|
||||
'x-axis-selector',
|
||||
'y-axis-selector',
|
||||
'title-selector',
|
||||
'tooltip-selector',
|
||||
'function-cfg',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
];
|
||||
_this.propertyInner = __assign(__assign({}, common_1.LINE_EDITOR_PROPERTY_INNER), { 'function-cfg': ['emptyDataStrategy'], 'y-axis-selector': [
|
||||
'name',
|
||||
'color',
|
||||
'fontSize',
|
||||
'position',
|
||||
'axisLabel',
|
||||
'axisLine',
|
||||
'splitLine',
|
||||
'axisLabelFormatter'
|
||||
], 'legend-selector': ['fontSize', 'color', 'show'] });
|
||||
_this.axis = ['xAxis', 'yAxis', 'filter', 'extLabel', 'extTooltip'];
|
||||
_this.axisConfig = {
|
||||
xAxis: {
|
||||
name: t('common.component.date') + " / " + t('chart.dimension'),
|
||||
limit: 1,
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: t('chart.k_line_yaxis_tip') + " / " + t('chart.quota'),
|
||||
limit: 4,
|
||||
type: 'q'
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 计算收盘价平均值
|
||||
* @param data
|
||||
* @param dayCount
|
||||
* @param chart
|
||||
*/
|
||||
_this.calculateMovingAverage = function (data, dayCount, chart) {
|
||||
var _a, _b;
|
||||
var xAxis = chart.xAxis;
|
||||
var yAxis = chart.yAxis;
|
||||
// 时间字段
|
||||
var xAxisgisbiName = xAxis[0].gisbiName;
|
||||
// 收盘价字段
|
||||
var yAxisgisbiName = yAxis[1].gisbiName;
|
||||
var result = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (i < dayCount) {
|
||||
result.push((_a = {},
|
||||
_a[xAxisgisbiName] = data[i][xAxisgisbiName],
|
||||
_a.value = null,
|
||||
_a));
|
||||
}
|
||||
else {
|
||||
var sum = data
|
||||
.slice(i - dayCount + 1, i + 1)
|
||||
.reduce(function (sum, item) { return sum + item[yAxisgisbiName]; }, 0);
|
||||
result.push((_b = {},
|
||||
_b[xAxisgisbiName] = data[i][xAxisgisbiName],
|
||||
_b.value = parseFloat((sum / dayCount).toFixed(3)),
|
||||
_b));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* 获取数据集合中对象属性值的最大最小值
|
||||
* @param data
|
||||
*/
|
||||
_this.calculateMinMax = function (data) {
|
||||
return data.reduce(function (acc, current) {
|
||||
// 获取 current 对象的所有属性值
|
||||
var values = Object.values(current);
|
||||
// 过滤出数字值
|
||||
var numericValues = values.filter(function (value) { return typeof value === 'number'; });
|
||||
// 找到 current 对象的数字属性值中的最大值和最小值
|
||||
// 如果存在数字值,则计算当前对象的最大值和最小值
|
||||
if (numericValues.length > 0) {
|
||||
var currentMax = Math.max.apply(Math, numericValues);
|
||||
var currentMin = Math.min.apply(Math, numericValues);
|
||||
// 更新全局最大值和最小值
|
||||
acc.maxValue = Math.max(acc.maxValue, currentMax);
|
||||
acc.minValue = Math.min(acc.minValue, currentMin);
|
||||
}
|
||||
return acc;
|
||||
}, { maxValue: Number.NEGATIVE_INFINITY, minValue: Number.POSITIVE_INFINITY });
|
||||
};
|
||||
/**
|
||||
* 注册图表事件
|
||||
* @param data
|
||||
* @param plot
|
||||
* @param averagesLineData
|
||||
*/
|
||||
_this.registerEvent = function (data, plot, averagesLineData) {
|
||||
// 监听图例点击事件,显示隐藏
|
||||
var risingVisible = true;
|
||||
plot.on('legend-item:click', function (evt) {
|
||||
var value = evt.target.get('delegateObject').item.value;
|
||||
if (value === 'k') {
|
||||
risingVisible = !risingVisible;
|
||||
plot.chart.geometries.forEach(function (geom) {
|
||||
if (geom.type === 'schema') {
|
||||
geom.changeVisible(risingVisible);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
var lines = plot.chart.geometries.filter(function (item) { return item.type === 'line'; });
|
||||
var points = plot.chart.geometries.filter(function (item) { return item.type === 'point'; });
|
||||
var lineIndex = 0;
|
||||
for (var _i = 0, _a = averagesLineData.keys(); _i < _a.length; _i++) {
|
||||
var key = _a[_i];
|
||||
lineIndex++;
|
||||
if (key === value) {
|
||||
lines[lineIndex - 1].changeVisible(!lines[lineIndex - 1].visible);
|
||||
points[lineIndex - 1].changeVisible(!points[lineIndex - 1].visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 监听图表渲染事件
|
||||
plot.on('afterrender', function (e) {
|
||||
var _a, _b;
|
||||
var first = false;
|
||||
if (plot.chart.options.slider.start === 0.5 && plot.chart.options.slider.end === 1) {
|
||||
first = true;
|
||||
}
|
||||
if ((_b = (_a = e.view) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.scales) {
|
||||
var startIndex = Math.floor(0.5 * data.length);
|
||||
var endIndex = Math.ceil(1 * data.length);
|
||||
var filteredData = data.slice(startIndex, endIndex);
|
||||
var _c = _this.calculateMinMax(first ? filteredData : e.view.filteredData), maxValue_1 = _c.maxValue, minValue_1 = _c.minValue;
|
||||
var a_1 = e.view.options.scales;
|
||||
Object.keys(a_1).forEach(function (item) {
|
||||
if (a_1[item].max) {
|
||||
a_1[item].max = maxValue_1;
|
||||
}
|
||||
if (a_1[item].min) {
|
||||
a_1[item].min = minValue_1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听图例组点击事件,设置缩放
|
||||
plot.on('legend-item-group:click', function (e) {
|
||||
var _a, _b;
|
||||
if ((_b = (_a = e.view) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.scales) {
|
||||
var _c = _this.calculateMinMax(e.view.filteredData), maxValue_2 = _c.maxValue, minValue_2 = _c.minValue;
|
||||
var a_2 = e.view.options.scales;
|
||||
Object.keys(a_2).forEach(function (item) {
|
||||
if (a_2[item].max) {
|
||||
a_2[item].max = maxValue_2;
|
||||
}
|
||||
if (a_2[item].min) {
|
||||
a_2[item].min = minValue_2;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听滑块事件,设置缩放
|
||||
plot.on('slider:valuechanged', function (e) {
|
||||
var start = e.gEvent.currentTarget.cfg.component.cfg.start;
|
||||
var end = e.gEvent.currentTarget.cfg.component.cfg.end;
|
||||
plot.chart.options.slider.start = start;
|
||||
plot.chart.options.slider.end = end;
|
||||
var startIndex = Math.floor(start * data.length);
|
||||
var endIndex = Math.ceil(end * data.length);
|
||||
var filteredData = data.slice(startIndex, endIndex);
|
||||
var _a = _this.calculateMinMax(filteredData), maxValue = _a.maxValue, minValue = _a.minValue;
|
||||
var a = e.view.options.scales;
|
||||
Object.keys(a).forEach(function (item) {
|
||||
if (a[item].max) {
|
||||
a[item].max = maxValue;
|
||||
}
|
||||
if (a[item].min) {
|
||||
a[item].min = minValue;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
StockLine.prototype.drawChart = function (drawOptions) {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
return __awaiter(this, void 0, Promise, function () {
|
||||
var chart, action, container, xAxis, yAxis, basicStyle, colors, alpha, data, xAxisgisbiName, averages, legendItems, averagesLineData, averageLines, index, start, end, startIndex, endIndex, filteredData, _g, maxValue, minValue, _i, _h, key, axis, dateFormat, dateSplit, option, MixClass, plot;
|
||||
var _j;
|
||||
var _this = this;
|
||||
return __generator(this, function (_k) {
|
||||
switch (_k.label) {
|
||||
case 0:
|
||||
chart = drawOptions.chart, action = drawOptions.action, container = drawOptions.container;
|
||||
if (!((_b = (_a = chart.data) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.length)) {
|
||||
return [2 /*return*/];
|
||||
}
|
||||
xAxis = chart.xAxis;
|
||||
yAxis = chart.yAxis;
|
||||
if (yAxis.length != 4) {
|
||||
return [2 /*return*/];
|
||||
}
|
||||
basicStyle = util_1.parseJson(chart.customAttr).basicStyle;
|
||||
colors = [];
|
||||
alpha = basicStyle.alpha;
|
||||
basicStyle.colors.forEach(function (ele) {
|
||||
colors.push(util_1.hexColorToRGBA(ele, alpha));
|
||||
});
|
||||
data = util_1.parseJson((_c = chart.data) === null || _c === void 0 ? void 0 : _c.tableRow);
|
||||
xAxisgisbiName = xAxis[0].gisbiName;
|
||||
averages = [5, 10, 20, 60, 120, 180];
|
||||
legendItems = [
|
||||
{
|
||||
name: '日K',
|
||||
value: 'k',
|
||||
marker: {
|
||||
symbol: function (x, y, r) {
|
||||
var width = r * 1;
|
||||
var height = r;
|
||||
return [
|
||||
// 矩形框
|
||||
['M', x - width - 1 / 2, y - height / 2],
|
||||
['L', x + width + 1 / 2, y - height / 2],
|
||||
['L', x + width + 1 / 2, y + height / 2],
|
||||
['L', x - width - 1 / 2, y + height / 2],
|
||||
['Z'],
|
||||
// 中线
|
||||
['M', x, y + 10 / 2],
|
||||
['L', x, y - 10 / 2]
|
||||
];
|
||||
},
|
||||
style: { fill: 'red', stroke: 'red', lineWidth: 2 }
|
||||
}
|
||||
}
|
||||
];
|
||||
averagesLineData = new Map();
|
||||
averages.forEach(function (item) {
|
||||
averagesLineData.set('ma' + item, _this.calculateMovingAverage(data, item, chart));
|
||||
});
|
||||
// 将均线数据设置到主数据中
|
||||
data.forEach(function (item) {
|
||||
var _a;
|
||||
var date = item[xAxisgisbiName];
|
||||
for (var _i = 0, averagesLineData_1 = averagesLineData; _i < averagesLineData_1.length; _i++) {
|
||||
var _b = averagesLineData_1[_i], key = _b[0], value = _b[1];
|
||||
item[key] = (_a = value.find(function (m) { return m[xAxisgisbiName] === date; })) === null || _a === void 0 ? void 0 : _a.value;
|
||||
}
|
||||
});
|
||||
averageLines = [];
|
||||
index = 0;
|
||||
start = 0.5;
|
||||
end = 1;
|
||||
startIndex = Math.floor(start * data.length);
|
||||
endIndex = Math.ceil(end * data.length);
|
||||
filteredData = data.slice(startIndex, endIndex);
|
||||
_g = this.calculateMinMax(filteredData), maxValue = _g.maxValue, minValue = _g.minValue;
|
||||
for (_i = 0, _h = averagesLineData.keys(); _i < _h.length; _i++) {
|
||||
key = _h[_i];
|
||||
index++;
|
||||
averageLines.push({
|
||||
type: 'line',
|
||||
top: true,
|
||||
options: {
|
||||
smooth: false,
|
||||
xField: xAxisgisbiName,
|
||||
yField: key,
|
||||
color: colors[index - 1],
|
||||
xAxis: null,
|
||||
yAxis: {
|
||||
label: false,
|
||||
min: minValue,
|
||||
max: maxValue,
|
||||
grid: null,
|
||||
line: null
|
||||
},
|
||||
lineStyle: {
|
||||
lineWidth: 2
|
||||
}
|
||||
}
|
||||
});
|
||||
legendItems.push({
|
||||
name: key.toUpperCase(),
|
||||
value: key,
|
||||
marker: { symbol: 'hyphen', style: { stroke: colors[index - 1], lineWidth: 2 } }
|
||||
});
|
||||
}
|
||||
axis = (_d = chart.xAxis) !== null && _d !== void 0 ? _d : [];
|
||||
dateSplit = ((_e = axis[0]) === null || _e === void 0 ? void 0 : _e.datePattern) === 'date_split' ? '/' : '-';
|
||||
switch ((_f = axis[0]) === null || _f === void 0 ? void 0 : _f.dateStyle) {
|
||||
case 'y':
|
||||
dateFormat = 'YYYY';
|
||||
break;
|
||||
case 'y_M':
|
||||
dateFormat = 'YYYY' + dateSplit + 'MM';
|
||||
break;
|
||||
case 'y_M_d':
|
||||
dateFormat = 'YYYY' + dateSplit + 'MM' + dateSplit + 'DD';
|
||||
break;
|
||||
// case 'H_m_s':
|
||||
// dateFormat = 'HH:mm:ss'
|
||||
// break
|
||||
case 'y_M_d_H':
|
||||
dateFormat = 'YYYY' + dateSplit + 'MM' + dateSplit + 'DD' + ' HH';
|
||||
break;
|
||||
case 'y_M_d_H_m':
|
||||
dateFormat = 'YYYY' + dateSplit + 'MM' + dateSplit + 'DD' + ' HH:mm';
|
||||
break;
|
||||
case 'y_M_d_H_m_s':
|
||||
dateFormat = 'YYYY' + dateSplit + 'MM' + dateSplit + 'DD' + ' HH:mm:ss';
|
||||
break;
|
||||
default:
|
||||
dateFormat = 'YYYY-MM-dd HH:mm:ss';
|
||||
}
|
||||
option = this.setupOptions(chart, {
|
||||
data: data,
|
||||
slider: {
|
||||
start: 0.5,
|
||||
end: 1,
|
||||
textStyle: {
|
||||
fontFamily: chart.fontFamily
|
||||
}
|
||||
},
|
||||
plots: __spreadArrays([
|
||||
{
|
||||
type: 'stock',
|
||||
top: true,
|
||||
options: {
|
||||
meta: (_j = {},
|
||||
_j[xAxisgisbiName] = {
|
||||
mask: dateFormat
|
||||
},
|
||||
_j),
|
||||
stockStyle: {
|
||||
stroke: 'black',
|
||||
lineWidth: 0.5
|
||||
},
|
||||
yAxis: {
|
||||
label: {},
|
||||
position: 'left',
|
||||
min: minValue,
|
||||
max: maxValue
|
||||
},
|
||||
xField: xAxisgisbiName,
|
||||
yField: [
|
||||
yAxis[0].gisbiName,
|
||||
yAxis[1].gisbiName,
|
||||
yAxis[2].gisbiName,
|
||||
yAxis[3].gisbiName
|
||||
],
|
||||
legend: {
|
||||
position: 'top',
|
||||
custom: true,
|
||||
items: legendItems
|
||||
}
|
||||
}
|
||||
}
|
||||
], averageLines)
|
||||
});
|
||||
return [4 /*yield*/, Promise.resolve().then(function () { return require('@antv/g2plot/esm/plots/mix'); })];
|
||||
case 1:
|
||||
MixClass = (_k.sent()).Mix;
|
||||
plot = new MixClass(container, option);
|
||||
this.registerEvent(data, plot, averagesLineData);
|
||||
plot.on('schema:click', function (evt) {
|
||||
var _a;
|
||||
var selectSchema = evt.data.data[xAxisgisbiName];
|
||||
var paramData = util_1.parseJson((_a = chart.data) === null || _a === void 0 ? void 0 : _a.data);
|
||||
var selectData = paramData.filter(function (item) { return item.field === selectSchema; });
|
||||
var quotaList = [];
|
||||
selectData.forEach(function (item) {
|
||||
quotaList.push(__assign(__assign({}, item.quotaList[0]), { value: item.value }));
|
||||
});
|
||||
if (selectData.length) {
|
||||
var param = {
|
||||
x: evt.x,
|
||||
y: evt.y,
|
||||
data: {
|
||||
data: __assign(__assign({}, evt.data.data), { value: quotaList[0].value, name: selectSchema, dimensionList: selectData[0].dimensionList, quotaList: quotaList })
|
||||
}
|
||||
};
|
||||
action(param);
|
||||
}
|
||||
});
|
||||
return [2 /*return*/, plot];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
StockLine.prototype.configBasicStyle = function (chart, options) {
|
||||
// size
|
||||
var customAttr = util_1.parseJson(chart.customAttr);
|
||||
var s = JSON.parse(JSON.stringify(customAttr.basicStyle));
|
||||
var smooth = s.lineSmooth;
|
||||
var point = {
|
||||
size: s.lineSymbolSize,
|
||||
shape: s.lineSymbol
|
||||
};
|
||||
var lineStyle = {
|
||||
lineWidth: s.lineWidth
|
||||
};
|
||||
var plots = [];
|
||||
options.plots.forEach(function (item) {
|
||||
if (item.type === 'stock') {
|
||||
plots.push(__assign({}, item));
|
||||
}
|
||||
if (item.type === 'line') {
|
||||
plots.push(__assign(__assign({}, item), { options: __assign(__assign({}, item.options), { smooth: smooth, point: point, lineStyle: lineStyle }) }));
|
||||
}
|
||||
});
|
||||
return __assign(__assign({}, options), { plots: plots });
|
||||
};
|
||||
StockLine.prototype.configTooltip = function (chart, options) {
|
||||
var tooltipAttr = util_1.parseJson(chart.customAttr).tooltip;
|
||||
var newPlots = [];
|
||||
var linePlotList = options.plots.filter(function (item) { return item.type === 'line'; });
|
||||
linePlotList.forEach(function (item) {
|
||||
newPlots.push(item);
|
||||
});
|
||||
var stockPlot = options.plots.filter(function (item) { return item.type === 'stock'; })[0];
|
||||
if (!tooltipAttr.show) {
|
||||
var stockOption_1 = __assign(__assign({}, stockPlot.options), { tooltip: {
|
||||
showContent: false
|
||||
} });
|
||||
newPlots.push(__assign(__assign({}, stockPlot), { options: stockOption_1 }));
|
||||
return __assign(__assign({}, options), { plots: newPlots });
|
||||
}
|
||||
var showFiled = chart.data.fields;
|
||||
var customTooltipItems = function (originalItems) {
|
||||
var _a;
|
||||
var formattedItems = originalItems.map(function (item) {
|
||||
var fieldObj = showFiled.find(function (q) { return q.gisbiName === item.name; });
|
||||
var displayName = (fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.chartShowName) || (fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.name) || item.name;
|
||||
var formattedName = displayName.startsWith('ma') ? displayName.toUpperCase() : displayName;
|
||||
tooltipAttr.tooltipFormatter.decimalCount = 3;
|
||||
var formattedValue = formatter_1.valueFormatter(item.value, tooltipAttr.tooltipFormatter);
|
||||
return __assign(__assign({}, item), { name: formattedName, value: formattedValue, color: item.color });
|
||||
});
|
||||
var hasKLine = formattedItems.some(function (item) { return !item.name.startsWith('MA'); });
|
||||
var kLines = formattedItems.filter(function (item) { return !item.name.startsWith('MA'); });
|
||||
return hasKLine
|
||||
? __spreadArrays([
|
||||
{ name: '日K', value: '', marker: true, color: (_a = kLines[0]) === null || _a === void 0 ? void 0 : _a.color }
|
||||
], kLines, formattedItems.filter(function (item) { return item.name.startsWith('MA'); })) : formattedItems;
|
||||
};
|
||||
var formatTooltipItem = function (item) {
|
||||
var size = item.name.startsWith('MA') || !item.value ? 10 : 5;
|
||||
var markerMarginRight = item.name.startsWith('MA') || !item.value ? 5 : 9;
|
||||
var markerMarginLeft = item.name.startsWith('MA') || !item.value ? 0 : 2;
|
||||
return "\n <li style=\"display: flex; align-items: center; margin-bottom: 10px;\">\n <div>\n <span\n style=\"\n background-color: " + item.color + ";\n width: " + size + "px;\n height: " + size + "px;\n border-radius: 50%;\n display: inline-block;\n margin-right: " + markerMarginRight + "px;\n margin-left: " + markerMarginLeft + "px;\n \"></span>\n </div>\n <div style=\"display: flex; justify-content: space-between; width: 100%;\">\n <span style=\"margin-right: 15px;\">" + item.name + "</span>\n <span>" + (item.name.startsWith('MA') && item.value === '0' ? '-' : item.value) + "</span>\n </div>\n </li>\n ";
|
||||
};
|
||||
var generateCustomTooltipContent = function (title, items) {
|
||||
return "\n <div style=\"padding: 10px 0;\">\n <div style=\"margin-bottom: 10px;\">" + title + "</div>\n <ul style=\"list-style: none; padding: 0;\">\n " + items.map(formatTooltipItem).join('') + "\n </ul>\n </div>\n ";
|
||||
};
|
||||
var stockOption = __assign(__assign({}, stockPlot.options), { tooltip: {
|
||||
showMarkers: true,
|
||||
showCrosshairs: true,
|
||||
showNil: true,
|
||||
crosshairs: {
|
||||
follow: true,
|
||||
text: function (axisType, value, data) {
|
||||
if (axisType === 'y') {
|
||||
return { content: value ? value.toFixed(0) : value };
|
||||
}
|
||||
return { content: data[0].title, position: 'end' };
|
||||
}
|
||||
},
|
||||
showContent: true,
|
||||
customItems: customTooltipItems,
|
||||
customContent: generateCustomTooltipContent
|
||||
} });
|
||||
newPlots.push(__assign(__assign({}, stockPlot), { options: stockOption }));
|
||||
return __assign(__assign({}, options), { plots: newPlots });
|
||||
};
|
||||
StockLine.prototype.configXAxis = function (chart, options) {
|
||||
var xAxisOptions = _super.prototype.configXAxis.call(this, chart, options);
|
||||
if (!xAxisOptions) {
|
||||
return options;
|
||||
}
|
||||
var newPlots = [];
|
||||
var linePlotList = options.plots.filter(function (item) { return item.type === 'line'; });
|
||||
var stockPlot = options.plots.filter(function (item) { return item.type === 'stock'; })[0];
|
||||
var newStockPlot = __assign(__assign({}, stockPlot), { options: __assign(__assign({}, stockPlot.options), { xAxis: xAxisOptions['xAxis']
|
||||
? __assign(__assign({}, stockPlot.options['xAxis']), xAxisOptions['xAxis']) : {
|
||||
label: false,
|
||||
line: null
|
||||
} }) });
|
||||
newPlots.push(newStockPlot);
|
||||
linePlotList.forEach(function (item) {
|
||||
newPlots.push(item);
|
||||
});
|
||||
return __assign(__assign({}, options), { plots: newPlots });
|
||||
};
|
||||
StockLine.prototype.configYAxis = function (chart, options) {
|
||||
var yAxisOptions = _super.prototype.configYAxis.call(this, chart, options);
|
||||
if (!yAxisOptions) {
|
||||
return options;
|
||||
}
|
||||
var yAxis = util_1.parseJson(chart.customStyle).yAxis;
|
||||
var newPlots = [];
|
||||
var linePlotList = options.plots.filter(function (item) { return item.type === 'line'; });
|
||||
var stockPlot = options.plots.filter(function (item) { return item.type === 'stock'; })[0];
|
||||
var label = false;
|
||||
if (yAxisOptions['yAxis'].label) {
|
||||
label = __assign(__assign({}, yAxisOptions['yAxis'].label), { formatter: function (value) {
|
||||
return formatter_1.valueFormatter(value, yAxis.axisLabelFormatter);
|
||||
} });
|
||||
}
|
||||
var newStockPlot = __assign(__assign({}, stockPlot), { options: __assign(__assign({}, stockPlot.options), { yAxis: label
|
||||
? __assign(__assign(__assign({}, stockPlot.options['yAxis']), yAxisOptions['yAxis']), { label: label }) : __assign(__assign({}, yAxisOptions['yAxis']), { label: label, grid: null, line: null }) }) });
|
||||
newPlots.push(newStockPlot);
|
||||
linePlotList.forEach(function (item) {
|
||||
newPlots.push(item);
|
||||
});
|
||||
return __assign(__assign({}, options), { plots: newPlots });
|
||||
};
|
||||
StockLine.prototype.customConfigEmptyDataStrategy = function (chart, options) {
|
||||
var data = options.data;
|
||||
if (!(data === null || data === void 0 ? void 0 : data.length)) {
|
||||
return options;
|
||||
}
|
||||
var strategy = util_1.parseJson(chart.senior).functionCfg.emptyDataStrategy;
|
||||
if (strategy === 'ignoreData') {
|
||||
var _loop_1 = function (i) {
|
||||
var item = data[i];
|
||||
Object.keys(item).forEach(function (key) {
|
||||
if (key.startsWith('f_') && item[key] === null) {
|
||||
data.splice(i, 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
_loop_1(i);
|
||||
}
|
||||
}
|
||||
var updateValues = function (strategy, data) {
|
||||
data.forEach(function (obj) {
|
||||
Object.keys(obj).forEach(function (key) {
|
||||
if (key.startsWith('f_') && obj[key] === null) {
|
||||
obj[key] = strategy === 'breakLine' ? null : 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
if (strategy === 'breakLine' || strategy === 'setZero') {
|
||||
updateValues(strategy, data);
|
||||
}
|
||||
return options;
|
||||
};
|
||||
StockLine.prototype.configLegend = function (chart, options) {
|
||||
var legend = {};
|
||||
var customStyle;
|
||||
var stockPlot = options.plots.filter(function (item) { return item.type === 'stock'; })[0];
|
||||
if (chart.customStyle) {
|
||||
customStyle = util_1.parseJson(chart.customStyle);
|
||||
// legend
|
||||
if (customStyle.legend) {
|
||||
var l = JSON.parse(JSON.stringify(customStyle.legend));
|
||||
if (l.show) {
|
||||
legend = __assign(__assign({}, stockPlot.options.legend), { itemName: {
|
||||
style: {
|
||||
fill: l.color,
|
||||
fontSize: l.fontSize
|
||||
}
|
||||
} });
|
||||
}
|
||||
else {
|
||||
legend = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
var newPlots = [];
|
||||
var stockOption = __assign(__assign({}, stockPlot.options), { legend: legend });
|
||||
var linePlotList = options.plots.filter(function (item) { return item.type === 'line'; });
|
||||
linePlotList.forEach(function (item) {
|
||||
newPlots.push(item);
|
||||
});
|
||||
newPlots.push(__assign(__assign({}, stockPlot), { options: stockOption }));
|
||||
return __assign(__assign({}, options), { plots: newPlots });
|
||||
};
|
||||
StockLine.prototype.setupOptions = function (chart, options) {
|
||||
return util_1.flow(this.configTheme, this.configBasicStyle, this.configXAxis, this.configYAxis, this.configTooltip, this.configLegend, this.customConfigEmptyDataStrategy)(chart, options);
|
||||
};
|
||||
return StockLine;
|
||||
}(g2plot_1.G2PlotChartView));
|
||||
exports.StockLine = StockLine;
|
@ -10,10 +10,12 @@ import {
|
||||
TOOLTIP_TPL
|
||||
} from '../../common/common_antv'
|
||||
import {
|
||||
convertToAlphaColor,
|
||||
flow,
|
||||
getLineConditions,
|
||||
getLineLabelColorByCondition,
|
||||
hexColorToRGBA,
|
||||
isAlphaColor,
|
||||
parseJson,
|
||||
setUpGroupSeriesColor
|
||||
} from '@/data-visualization/chart/components/js/util'
|
||||
@ -43,8 +45,10 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
'label-selector': ['seriesLabelVPosition', 'seriesLabelFormatter', 'showExtremum'],
|
||||
'tooltip-selector': [
|
||||
...LINE_EDITOR_PROPERTY_INNER['tooltip-selector'],
|
||||
'seriesTooltipFormatter'
|
||||
]
|
||||
'seriesTooltipFormatter',
|
||||
'carousel'
|
||||
],
|
||||
'legend-selector': [...LINE_EDITOR_PROPERTY_INNER['legend-selector'], 'legendSort']
|
||||
}
|
||||
axis: AxisType[] = [...LINE_AXIS_TYPE, 'xAxisExt']
|
||||
axisConfig = {
|
||||
@ -66,8 +70,8 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
}
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Line>): Promise<G2Line> {
|
||||
const { chart, action, container } = drawOptions
|
||||
chart.container = container
|
||||
if (!chart.data?.data?.length) {
|
||||
chart.container = container
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
@ -146,7 +150,7 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
fields: [],
|
||||
...tmpOptions.label,
|
||||
layout: labelAttr.fullDisplay ? [{ type: 'limit-in-plot' }] : tmpOptions.label.layout,
|
||||
formatter: (data: Datum, _point) => {
|
||||
formatter: (data: Datum) => {
|
||||
if (data.EXTREME) {
|
||||
return ''
|
||||
}
|
||||
@ -321,17 +325,30 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
if (sort?.length) {
|
||||
// 用值域限定排序,有可能出现新数据但是未出现在图表上,所以这边要遍历一下子维度,加到后面,让新数据显示出来
|
||||
const data = optionTmp.data
|
||||
data?.forEach(d => {
|
||||
const cat = d['category']
|
||||
if (cat && !sort.includes(cat)) {
|
||||
sort.push(cat)
|
||||
const cats =
|
||||
data?.reduce((p, n) => {
|
||||
const cat = n['category']
|
||||
if (cat && !p.includes(cat)) {
|
||||
p.push(cat)
|
||||
}
|
||||
return p
|
||||
}, []) || []
|
||||
const values = sort.reduce((p, n) => {
|
||||
if (cats.includes(n)) {
|
||||
const index = cats.indexOf(n)
|
||||
if (index !== -1) {
|
||||
cats.splice(index, 1)
|
||||
}
|
||||
p.push(n)
|
||||
}
|
||||
})
|
||||
return p
|
||||
}, [])
|
||||
cats.length > 0 && values.push(...cats)
|
||||
optionTmp.meta = {
|
||||
...optionTmp.meta,
|
||||
category: {
|
||||
type: 'cat',
|
||||
values: sort
|
||||
values
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,6 +368,56 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
fill: style.stroke
|
||||
}
|
||||
}
|
||||
const { sort, customSort, icon } = customStyle.legend
|
||||
if (sort && sort !== 'none' && chart.xAxisExt.length) {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const { basicStyle } = customAttr
|
||||
const seriesMap =
|
||||
basicStyle.seriesColor?.reduce((p, n) => {
|
||||
p[n.id] = n
|
||||
return p
|
||||
}, {}) || {}
|
||||
const dupCheck = new Set()
|
||||
const items = optionTmp.data?.reduce((arr, item) => {
|
||||
if (!dupCheck.has(item.category)) {
|
||||
const fill =
|
||||
seriesMap[item.category]?.color ??
|
||||
optionTmp.color[dupCheck.size % optionTmp.color.length]
|
||||
dupCheck.add(item.category)
|
||||
arr.push({
|
||||
name: item.category,
|
||||
value: item.category,
|
||||
marker: {
|
||||
symbol: icon,
|
||||
style: {
|
||||
r: size,
|
||||
fill: isAlphaColor(fill) ? fill : convertToAlphaColor(fill, basicStyle.alpha)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr
|
||||
}, [])
|
||||
if (sort !== 'custom') {
|
||||
items.sort((a, b) => {
|
||||
return sort !== 'desc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name)
|
||||
})
|
||||
} else {
|
||||
const tmp = []
|
||||
;(customSort || []).forEach(item => {
|
||||
const index = items.findIndex(i => i.name === item)
|
||||
if (index !== -1) {
|
||||
tmp.push(items[index])
|
||||
items.splice(index, 1)
|
||||
}
|
||||
})
|
||||
items.unshift(...tmp)
|
||||
}
|
||||
optionTmp.legend.items = items
|
||||
if (xAxisExt?.customSort?.length > 0) {
|
||||
delete optionTmp.meta?.category.values
|
||||
}
|
||||
}
|
||||
return optionTmp
|
||||
}
|
||||
protected setupOptions(chart: Chart, options: LineOptions): LineOptions {
|
||||
|
@ -68,22 +68,22 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
const xAxis = chart.xAxis
|
||||
const yAxis = chart.yAxis
|
||||
// 时间字段
|
||||
const xAxisDataeaseName = xAxis[0].dataeaseName
|
||||
const xAxisgisbiName = xAxis[0].gisbiName
|
||||
// 收盘价字段
|
||||
const yAxisDataeaseName = yAxis[1].dataeaseName
|
||||
const yAxisgisbiName = yAxis[1].gisbiName
|
||||
const result = []
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (i < dayCount) {
|
||||
result.push({
|
||||
[xAxisDataeaseName]: data[i][xAxisDataeaseName],
|
||||
[xAxisgisbiName]: data[i][xAxisgisbiName],
|
||||
value: null
|
||||
})
|
||||
} else {
|
||||
const sum = data
|
||||
.slice(i - dayCount + 1, i + 1)
|
||||
.reduce((sum, item) => sum + item[yAxisDataeaseName], 0)
|
||||
.reduce((sum, item) => sum + item[yAxisgisbiName], 0)
|
||||
result.push({
|
||||
[xAxisDataeaseName]: data[i][xAxisDataeaseName],
|
||||
[xAxisgisbiName]: data[i][xAxisgisbiName],
|
||||
value: parseFloat((sum / dayCount).toFixed(3))
|
||||
})
|
||||
}
|
||||
@ -228,7 +228,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
const data = parseJson(chart.data?.tableRow)
|
||||
|
||||
// 时间字段
|
||||
const xAxisDataeaseName = xAxis[0].dataeaseName
|
||||
const xAxisgisbiName = xAxis[0].gisbiName
|
||||
const averages = [5, 10, 20, 60, 120, 180]
|
||||
const legendItems: any[] = [
|
||||
{
|
||||
@ -262,9 +262,9 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
|
||||
// 将均线数据设置到主数据中
|
||||
data.forEach((item: any) => {
|
||||
const date = item[xAxisDataeaseName]
|
||||
const date = item[xAxisgisbiName]
|
||||
for (const [key, value] of averagesLineData) {
|
||||
item[key] = value.find(m => m[xAxisDataeaseName] === date)?.value
|
||||
item[key] = value.find(m => m[xAxisgisbiName] === date)?.value
|
||||
}
|
||||
})
|
||||
|
||||
@ -283,7 +283,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
top: true,
|
||||
options: {
|
||||
smooth: false,
|
||||
xField: xAxisDataeaseName,
|
||||
xField: xAxisgisbiName,
|
||||
yField: key,
|
||||
color: colors[index - 1],
|
||||
xAxis: null,
|
||||
@ -349,7 +349,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
|
||||
options: {
|
||||
meta: {
|
||||
[xAxisDataeaseName]: {
|
||||
[xAxisgisbiName]: {
|
||||
mask: dateFormat
|
||||
}
|
||||
},
|
||||
@ -363,12 +363,12 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
min: minValue,
|
||||
max: maxValue
|
||||
},
|
||||
xField: xAxisDataeaseName,
|
||||
xField: xAxisgisbiName,
|
||||
yField: [
|
||||
yAxis[0].dataeaseName,
|
||||
yAxis[1].dataeaseName,
|
||||
yAxis[2].dataeaseName,
|
||||
yAxis[3].dataeaseName
|
||||
yAxis[0].gisbiName,
|
||||
yAxis[1].gisbiName,
|
||||
yAxis[2].gisbiName,
|
||||
yAxis[3].gisbiName
|
||||
],
|
||||
legend: {
|
||||
position: 'top',
|
||||
@ -384,7 +384,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
const plot = new MixClass(container, option)
|
||||
this.registerEvent(data, plot, averagesLineData)
|
||||
plot.on('schema:click', evt => {
|
||||
const selectSchema = evt.data.data[xAxisDataeaseName]
|
||||
const selectSchema = evt.data.data[xAxisgisbiName]
|
||||
const paramData = parseJson(chart.data?.data)
|
||||
const selectData = paramData.filter(item => item.field === selectSchema)
|
||||
const quotaList = []
|
||||
@ -440,7 +440,6 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
|
||||
protected configTooltip(chart: Chart, options: MixOptions): MixOptions {
|
||||
const tooltipAttr = parseJson(chart.customAttr).tooltip
|
||||
const xAxis = chart.xAxis
|
||||
const newPlots = []
|
||||
const linePlotList = options.plots.filter(item => item.type === 'line')
|
||||
linePlotList.forEach(item => {
|
||||
@ -464,7 +463,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
const showFiled = chart.data.fields
|
||||
const customTooltipItems = originalItems => {
|
||||
const formattedItems = originalItems.map(item => {
|
||||
const fieldObj = showFiled.find(q => q.dataeaseName === item.name)
|
||||
const fieldObj = showFiled.find(q => q.gisbiName === item.name)
|
||||
const displayName = fieldObj?.chartShowName || fieldObj?.name || item.name
|
||||
const formattedName = displayName.startsWith('ma') ? displayName.toUpperCase() : displayName
|
||||
tooltipAttr.tooltipFormatter.decimalCount = 3
|
||||
|
@ -74,7 +74,7 @@ export class Liquid extends G2PlotChartView<LiquidOptions, G2Liquid> {
|
||||
})
|
||||
// 处理空数据, 只要有一个指标是空数据,就不显示图表
|
||||
const hasNoneData = chart.data?.series.some(s => !s.data?.[0])
|
||||
this.configEmptyDataStyle(newChart, hasNoneData ? [] : [1], container)
|
||||
this.configEmptyDataStyle(hasNoneData ? [] : [1], container, newChart)
|
||||
if (hasNoneData) {
|
||||
return
|
||||
}
|
||||
|
@ -402,7 +402,8 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
content.push(name)
|
||||
}
|
||||
if (label.showQuota) {
|
||||
areaMap[name] && content.push(valueFormatter(areaMap[name], label.quotaLabelFormatter))
|
||||
;(areaMap[name] || areaMap[name] === 0) &&
|
||||
content.push(valueFormatter(areaMap[name], label.quotaLabelFormatter))
|
||||
}
|
||||
item.properties['_DE_LABEL_'] = content.join('\n\n')
|
||||
}
|
||||
|
@ -51,6 +51,29 @@ export const MAP_AXIS_TYPE: AxisType[] = [
|
||||
'extTooltip'
|
||||
]
|
||||
|
||||
export const gaodeMapStyleOptions = [
|
||||
{ name: t('chart.map_style_normal'), value: 'normal' },
|
||||
{ name: t('chart.map_style_darkblue'), value: 'darkblue' },
|
||||
{ name: t('chart.map_style_light'), value: 'light' },
|
||||
{ name: t('chart.map_style_dark'), value: 'dark' },
|
||||
{ name: t('chart.map_style_fresh'), value: 'fresh' },
|
||||
{ name: t('chart.map_style_grey'), value: 'grey' },
|
||||
{ name: t('chart.map_style_blue'), value: 'blue' },
|
||||
{ name: t('chart.map_style_translate'), value: 'Satellite' },
|
||||
{ name: t('commons.custom'), value: 'custom' }
|
||||
]
|
||||
|
||||
export const tdtMapStyleOptions = [
|
||||
{ name: t('chart.map_style_normal'), value: 'normal' },
|
||||
{ name: t('chart.map_style_dark'), value: 'black' },
|
||||
{ name: t('chart.map_style_darkblue'), value: 'indigo' }
|
||||
]
|
||||
|
||||
export const qqMapStyleOptions = [
|
||||
{ name: t('chart.map_style_normal'), value: 'normal' },
|
||||
{ name: t('commons.custom'), value: 'custom' }
|
||||
]
|
||||
|
||||
export declare type MapMouseEvent = MouseEvent & {
|
||||
feature: GeoJSON.Feature
|
||||
}
|
||||
|
391
frontend/src/data-visualization/chart/components/js/panel/charts/map/dist/flow-map.js
vendored
Normal file
391
frontend/src/data-visualization/chart/components/js/panel/charts/map/dist/flow-map.js
vendored
Normal file
@ -0,0 +1,391 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.FlowMap = void 0;
|
||||
var useI18n_1 = require("@/hooks/web/useI18n");
|
||||
var l7_1 = require("@/views/chart/components/js/panel/types/impl/l7");
|
||||
var common_1 = require("@/views/chart/components/js/panel/charts/map/common");
|
||||
var util_1 = require("@/views/chart/components/js/util");
|
||||
var utils_1 = require("@/utils/utils");
|
||||
var l7_layers_1 = require("@antv/l7-layers");
|
||||
var l7_layers_2 = require("@antv/l7-layers");
|
||||
var common_antv_1 = require("@/views/chart/components/js/panel/common/common_antv");
|
||||
var t = useI18n_1.useI18n().t;
|
||||
/**
|
||||
* 流向地图
|
||||
*/
|
||||
var FlowMap = /** @class */ (function (_super) {
|
||||
__extends(FlowMap, _super);
|
||||
function FlowMap() {
|
||||
var _this = _super.call(this, 'flow-map', []) || this;
|
||||
_this.properties = [
|
||||
'background-overall-component',
|
||||
'border-style',
|
||||
'basic-style-selector',
|
||||
'title-selector',
|
||||
'flow-map-line-selector',
|
||||
'flow-map-point-selector',
|
||||
'bubble-animate'
|
||||
];
|
||||
_this.propertyInner = __assign(__assign({}, common_1.MAP_EDITOR_PROPERTY_INNER), { 'basic-style-selector': [
|
||||
'mapBaseStyle',
|
||||
'mapLineStyle',
|
||||
'zoom',
|
||||
'showLabel',
|
||||
'autoFit',
|
||||
'mapCenter',
|
||||
'zoomLevel'
|
||||
] });
|
||||
_this.axis = ['xAxis', 'xAxisExt', 'filter', 'flowMapStartName', 'flowMapEndName', 'yAxis'];
|
||||
_this.axisConfig = {
|
||||
xAxis: {
|
||||
name: t('chart.start_coordinates') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 2
|
||||
},
|
||||
xAxisExt: {
|
||||
name: t('chart.end_coordinates') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 2
|
||||
},
|
||||
flowMapStartName: {
|
||||
name: t('chart.start_name') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
flowMapEndName: {
|
||||
name: t('chart.end_name') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
yAxis: {
|
||||
name: t('chart.flow_map_line_width') + " / " + t('chart.quota'),
|
||||
type: 'q',
|
||||
limit: 1,
|
||||
tooltip: t('chart.flow_map_line_width_tip'),
|
||||
allowEmpty: true
|
||||
}
|
||||
};
|
||||
_this.lineConfig = function (chart, xAxis, xAxisExt, basicStyle, misc) {
|
||||
var _a;
|
||||
var flowLineStyle = {
|
||||
type: misc.flowMapConfig.lineConfig.mapLineType,
|
||||
size: misc.flowMapConfig.lineConfig.mapLineType === 'line'
|
||||
? misc.flowMapConfig.lineConfig.mapLineWidth / 2
|
||||
: misc.flowMapConfig.lineConfig.mapLineWidth,
|
||||
animate: misc.flowMapConfig.lineConfig.mapLineAnimate,
|
||||
animateDuration: misc.flowMapConfig.lineConfig.mapLineAnimateDuration,
|
||||
gradient: misc.flowMapConfig.lineConfig.mapLineGradient,
|
||||
sourceColor: misc.flowMapConfig.lineConfig.mapLineSourceColor,
|
||||
targetColor: misc.flowMapConfig.lineConfig.mapLineTargetColor,
|
||||
alpha: misc.flowMapConfig.lineConfig.alpha
|
||||
};
|
||||
var colorsWithAlpha = basicStyle.colors.map(function (color) {
|
||||
return util_1.hexColorToRGBA(color, misc.flowMapConfig.lineConfig.alpha);
|
||||
});
|
||||
flowLineStyle.sourceColor = colorsWithAlpha[0];
|
||||
flowLineStyle.targetColor = colorsWithAlpha[1];
|
||||
// 线条粗细
|
||||
var lineWidthField = null;
|
||||
var yAxis = utils_1.deepCopy(chart.yAxis);
|
||||
if (yAxis.length > 0) {
|
||||
lineWidthField = yAxis[0].gisbiName;
|
||||
}
|
||||
// 线条颜色
|
||||
var lineColorField = null;
|
||||
var yAxisExt = utils_1.deepCopy(chart.yAxisExt);
|
||||
if (yAxisExt.length > 0) {
|
||||
lineColorField = yAxisExt[0].gisbiName;
|
||||
}
|
||||
var asteriskField = '*';
|
||||
var data = [];
|
||||
(_a = chart.data) === null || _a === void 0 ? void 0 : _a.tableRow.forEach(function (item) {
|
||||
var newKey = 'f_record';
|
||||
var newObj = Object.keys(item).reduce(function (acc, key) {
|
||||
if (key === asteriskField) {
|
||||
acc[newKey] = item[key];
|
||||
}
|
||||
else {
|
||||
acc[key] = item[key];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
data.push(newObj);
|
||||
});
|
||||
var config = new l7_layers_1.LineLayer({
|
||||
name: 'line',
|
||||
blend: 'normal',
|
||||
autoFit: !(basicStyle.autoFit === false)
|
||||
})
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName,
|
||||
x1: xAxisExt[0].gisbiName,
|
||||
y1: xAxisExt[1].gisbiName
|
||||
}
|
||||
})
|
||||
.size(flowLineStyle.size)
|
||||
.shape(flowLineStyle.type)
|
||||
.animate({
|
||||
enable: flowLineStyle.animate,
|
||||
duration: flowLineStyle.animateDuration,
|
||||
interval: 1,
|
||||
trailLength: 1
|
||||
});
|
||||
if (lineWidthField) {
|
||||
config.size(lineWidthField === asteriskField ? 'f_record' : lineWidthField, [1, 10]);
|
||||
}
|
||||
if (lineColorField) {
|
||||
config.style({
|
||||
opacity: flowLineStyle.alpha / 100
|
||||
});
|
||||
config.color(lineColorField);
|
||||
}
|
||||
else {
|
||||
if (flowLineStyle.gradient) {
|
||||
config.style({
|
||||
sourceColor: flowLineStyle.sourceColor,
|
||||
targetColor: flowLineStyle.targetColor,
|
||||
opacity: flowLineStyle.alpha / 100
|
||||
});
|
||||
}
|
||||
else {
|
||||
config
|
||||
.style({
|
||||
opacity: flowLineStyle.alpha / 100
|
||||
})
|
||||
.color(flowLineStyle.sourceColor);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
};
|
||||
_this.startAndEndNameConfig = function (chart, xAxis, xAxisExt, misc, configList) {
|
||||
var _a, _b;
|
||||
var flowMapStartName = utils_1.deepCopy(chart.flowMapStartName);
|
||||
var flowMapEndName = utils_1.deepCopy(chart.flowMapEndName);
|
||||
var textColor = misc.flowMapConfig.pointConfig.text.color;
|
||||
var textFontSize = misc.flowMapConfig.pointConfig.text.fontSize;
|
||||
var has = new Map();
|
||||
if ((flowMapStartName === null || flowMapStartName === void 0 ? void 0 : flowMapStartName.length) > 0) {
|
||||
var startTextLayer = new l7_layers_2.PointLayer()
|
||||
.source((_a = chart.data) === null || _a === void 0 ? void 0 : _a.tableRow, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName
|
||||
}
|
||||
})
|
||||
.shape(flowMapStartName[0].gisbiName, function (args) {
|
||||
if (has.has('from-' + args)) {
|
||||
return '';
|
||||
}
|
||||
has.set('from-' + args, args);
|
||||
return args;
|
||||
})
|
||||
.size(textFontSize)
|
||||
.color(textColor)
|
||||
.style({
|
||||
textAnchor: 'top',
|
||||
textOffset: [0, 0],
|
||||
spacing: 2,
|
||||
padding: [1, 1],
|
||||
textAllowOverlap: true,
|
||||
fontFamily: chart.fontFamily ? chart.fontFamily : undefined
|
||||
});
|
||||
configList.push(startTextLayer);
|
||||
}
|
||||
if ((flowMapEndName === null || flowMapEndName === void 0 ? void 0 : flowMapEndName.length) > 0) {
|
||||
var endTextLayer = new l7_layers_2.PointLayer()
|
||||
.source((_b = chart.data) === null || _b === void 0 ? void 0 : _b.tableRow, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxisExt[0].gisbiName,
|
||||
y: xAxisExt[1].gisbiName
|
||||
}
|
||||
})
|
||||
.shape(flowMapEndName[0].gisbiName, function (args) {
|
||||
if (has.has('from-' + args) || has.has('to-' + args)) {
|
||||
return '';
|
||||
}
|
||||
has.set('to-' + args, args);
|
||||
return args;
|
||||
})
|
||||
.size(textFontSize)
|
||||
.color(textColor)
|
||||
.style({
|
||||
textAnchor: 'top',
|
||||
textOffset: [0, 0],
|
||||
spacing: 2,
|
||||
padding: [1, 1],
|
||||
textAllowOverlap: true,
|
||||
fontFamily: chart.fontFamily ? chart.fontFamily : undefined
|
||||
});
|
||||
configList.push(endTextLayer);
|
||||
}
|
||||
};
|
||||
_this.pointConfig = function (chart, xAxis, xAxisExt, misc, configList) {
|
||||
var _a, _b;
|
||||
var color = misc.flowMapConfig.pointConfig.point.color;
|
||||
var size = misc.flowMapConfig.pointConfig.point.size;
|
||||
var bubbleCfg = util_1.parseJson(chart.senior).bubbleCfg;
|
||||
var fromDefaultPointLayer = new l7_layers_2.PointLayer({ zIndex: -1 })
|
||||
.source((_a = chart.data) === null || _a === void 0 ? void 0 : _a.tableRow, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName
|
||||
}
|
||||
})
|
||||
.shape('circle')
|
||||
.size(size)
|
||||
.color(color)
|
||||
.style({
|
||||
blur: 0.6
|
||||
});
|
||||
var toDefaultPointLayer = new l7_layers_2.PointLayer({ zIndex: -1 })
|
||||
.source((_b = chart.data) === null || _b === void 0 ? void 0 : _b.tableRow, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxisExt[0].gisbiName,
|
||||
y: xAxisExt[1].gisbiName
|
||||
}
|
||||
})
|
||||
.shape('circle')
|
||||
.size(size)
|
||||
.color(color)
|
||||
.style({
|
||||
blur: 0.6
|
||||
});
|
||||
if (bubbleCfg && bubbleCfg.enable) {
|
||||
var animate = {
|
||||
enable: true,
|
||||
speed: bubbleCfg.speed,
|
||||
rings: bubbleCfg.rings
|
||||
};
|
||||
fromDefaultPointLayer.size(size * 2);
|
||||
fromDefaultPointLayer.animate(animate);
|
||||
toDefaultPointLayer.size(size * 2);
|
||||
toDefaultPointLayer.animate(animate);
|
||||
}
|
||||
configList.push(fromDefaultPointLayer);
|
||||
configList.push(toDefaultPointLayer);
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
FlowMap.prototype.drawChart = function (drawOption) {
|
||||
var _a;
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var chart, container, containerDom, rect, xAxis, xAxisExt, _b, basicStyle, misc, mapKey, mapStyle, chartObj, scene, center, configList, i;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
chart = drawOption.chart, container = drawOption.container;
|
||||
containerDom = document.getElementById(container);
|
||||
rect = containerDom === null || containerDom === void 0 ? void 0 : containerDom.getBoundingClientRect();
|
||||
if ((rect === null || rect === void 0 ? void 0 : rect.height) <= 0) {
|
||||
return [2 /*return*/, new l7_1.L7Wrapper((_a = drawOption.chartObj) === null || _a === void 0 ? void 0 : _a.getScene(), [])];
|
||||
}
|
||||
xAxis = utils_1.deepCopy(chart.xAxis);
|
||||
xAxisExt = utils_1.deepCopy(chart.xAxisExt);
|
||||
_b = utils_1.deepCopy(util_1.parseJson(chart.customAttr)), basicStyle = _b.basicStyle, misc = _b.misc;
|
||||
return [4 /*yield*/, this.getMapKey()];
|
||||
case 1:
|
||||
mapKey = _c.sent();
|
||||
mapStyle = common_antv_1.getMapStyle(mapKey, basicStyle);
|
||||
chartObj = drawOption.chartObj;
|
||||
scene = chartObj === null || chartObj === void 0 ? void 0 : chartObj.getScene();
|
||||
center = common_antv_1.getMapCenter(basicStyle);
|
||||
return [4 /*yield*/, common_antv_1.getMapScene(chart, scene, container, mapKey, basicStyle, misc, mapStyle, center)];
|
||||
case 2:
|
||||
scene = _c.sent();
|
||||
this.configZoomButton(chart, scene, mapKey);
|
||||
if ((xAxis === null || xAxis === void 0 ? void 0 : xAxis.length) < 2 || (xAxisExt === null || xAxisExt === void 0 ? void 0 : xAxisExt.length) < 2) {
|
||||
return [2 /*return*/, new l7_1.L7Wrapper(scene, undefined)];
|
||||
}
|
||||
configList = [];
|
||||
configList.push(this.lineConfig(chart, xAxis, xAxisExt, basicStyle, misc));
|
||||
this.startAndEndNameConfig(chart, xAxis, xAxisExt, misc, configList);
|
||||
this.pointConfig(chart, xAxis, xAxisExt, misc, configList);
|
||||
configList[0].once('inited', function () {
|
||||
common_antv_1.mapRendered(container);
|
||||
});
|
||||
for (i = 0; i < configList.length; i++) {
|
||||
configList[i].on('inited', function () {
|
||||
common_antv_1.qqMapRendered(scene);
|
||||
});
|
||||
}
|
||||
return [2 /*return*/, new l7_1.L7Wrapper(scene, configList)];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
FlowMap.prototype.setupDefaultOptions = function (chart) {
|
||||
chart.customAttr.misc.flowMapConfig.lineConfig.mapLineAnimate = true;
|
||||
return chart;
|
||||
};
|
||||
return FlowMap;
|
||||
}(l7_1.L7ChartView));
|
||||
exports.FlowMap = FlowMap;
|
632
frontend/src/data-visualization/chart/components/js/panel/charts/map/dist/symbolic-map.js
vendored
Normal file
632
frontend/src/data-visualization/chart/components/js/panel/charts/map/dist/symbolic-map.js
vendored
Normal file
@ -0,0 +1,632 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.SymbolicMap = void 0;
|
||||
var useI18n_1 = require("@/hooks/web/useI18n");
|
||||
var l7_1 = require("@/views/chart/components/js/panel/types/impl/l7");
|
||||
var common_1 = require("@/views/chart/components/js/panel/charts/map/common");
|
||||
var util_1 = require("@/views/chart/components/js/util");
|
||||
var utils_1 = require("@/utils/utils");
|
||||
var l7_layers_1 = require("@antv/l7-layers");
|
||||
var l7_2 = require("@antv/l7");
|
||||
var common_antv_1 = require("@/views/chart/components/js/panel/common/common_antv");
|
||||
var tooltip_carousel_1 = require("@/views/chart/components/js/panel/charts/map/tooltip-carousel");
|
||||
var lodash_es_1 = require("lodash-es");
|
||||
var t = useI18n_1.useI18n().t;
|
||||
/**
|
||||
* 符号地图
|
||||
*/
|
||||
var SymbolicMap = /** @class */ (function (_super) {
|
||||
__extends(SymbolicMap, _super);
|
||||
function SymbolicMap() {
|
||||
var _this = _super.call(this, 'symbolic-map', []) || this;
|
||||
_this.properties = [
|
||||
'background-overall-component',
|
||||
'border-style',
|
||||
'basic-style-selector',
|
||||
'symbolic-style-selector',
|
||||
'title-selector',
|
||||
'label-selector',
|
||||
'tooltip-selector',
|
||||
'threshold'
|
||||
];
|
||||
_this.propertyInner = __assign(__assign({}, common_1.MAP_EDITOR_PROPERTY_INNER), { 'basic-style-selector': [
|
||||
'colors',
|
||||
'alpha',
|
||||
'mapBaseStyle',
|
||||
'zoom',
|
||||
'showLabel',
|
||||
'autoFit',
|
||||
'mapCenter',
|
||||
'zoomLevel'
|
||||
], 'symbolic-style-selector': ['symbolicMapStyle'], 'label-selector': ['color', 'fontSize', 'showFields', 'customContent'], 'tooltip-selector': [
|
||||
'color',
|
||||
'fontSize',
|
||||
'showFields',
|
||||
'customContent',
|
||||
'show',
|
||||
'backgroundColor',
|
||||
'carousel'
|
||||
], threshold: ['lineThreshold'] });
|
||||
_this.axis = ['xAxis', 'xAxisExt', 'extBubble', 'filter', 'extLabel', 'extTooltip'];
|
||||
_this.axisConfig = {
|
||||
xAxis: {
|
||||
name: t('chart.symbolic_map_coordinates') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 2
|
||||
},
|
||||
xAxisExt: {
|
||||
name: t('chart.color') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
extBubble: {
|
||||
name: t('chart.bubble_size') + " / " + t('chart.quota'),
|
||||
type: 'q',
|
||||
limit: 1,
|
||||
tooltip: t('chart.symbolic_map_bubble_size_tip'),
|
||||
allowEmpty: true
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 构建符号图层
|
||||
* @param chart
|
||||
*/
|
||||
_this.buildSymbolicLayer = function (chart, scene) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var basicStyle, xAxis, xAxisExt, extBubble, _a, mapSymbolOpacity, mapSymbolSize, mapSymbol, mapSymbolStrokeWidth, colors, alpha, mapSymbolSizeMin, mapSymbolSizeMax, colorsWithAlpha, colorIndex, colorAssignments, sizeKey, threshold, conditions, extBubbleIds, baseColor, baseColorList, data, pointLayer, parser, index, color, fillRegex, svgStr, doc, svgEle, parser, color, fillRegex, svgStr, doc, svgEle;
|
||||
var _b, _c, _d;
|
||||
return __generator(this, function (_e) {
|
||||
switch (_e.label) {
|
||||
case 0:
|
||||
basicStyle = util_1.parseJson(chart.customAttr).basicStyle;
|
||||
xAxis = utils_1.deepCopy(chart.xAxis);
|
||||
xAxisExt = utils_1.deepCopy(chart.xAxisExt);
|
||||
extBubble = utils_1.deepCopy(chart.extBubble);
|
||||
_a = utils_1.deepCopy(basicStyle), mapSymbolOpacity = _a.mapSymbolOpacity, mapSymbolSize = _a.mapSymbolSize, mapSymbol = _a.mapSymbol, mapSymbolStrokeWidth = _a.mapSymbolStrokeWidth, colors = _a.colors, alpha = _a.alpha, mapSymbolSizeMin = _a.mapSymbolSizeMin, mapSymbolSizeMax = _a.mapSymbolSizeMax;
|
||||
colorsWithAlpha = colors.map(function (color) { return util_1.hexColorToRGBA(color, alpha); });
|
||||
colorIndex = 0;
|
||||
colorAssignments = new Map();
|
||||
sizeKey = extBubble.length > 0 ? extBubble[0].gisbiName : '';
|
||||
threshold = util_1.parseJson(chart.senior).threshold;
|
||||
conditions = [];
|
||||
if (threshold.enable) {
|
||||
conditions = (_b = threshold.lineThreshold) !== null && _b !== void 0 ? _b : [];
|
||||
}
|
||||
extBubbleIds = chart.extBubble.map(function (i) { return i.id; });
|
||||
conditions = lodash_es_1.filter(conditions, function (c) { return extBubbleIds.includes(c.fieldId); });
|
||||
baseColor = colorsWithAlpha[0];
|
||||
baseColorList = [];
|
||||
data = ((_c = chart.data) === null || _c === void 0 ? void 0 : _c.tableRow) ? chart.data.tableRow.map(function (item, index) {
|
||||
var _a, _b;
|
||||
item['_index'] = '_index' + index;
|
||||
// 颜色标识
|
||||
var identifier = item[(_a = xAxisExt[0]) === null || _a === void 0 ? void 0 : _a.gisbiName];
|
||||
// 检查该标识是否已有颜色分配,如果没有则分配
|
||||
var color = colorAssignments.get(identifier);
|
||||
if (!color) {
|
||||
color = colorsWithAlpha[colorIndex++ % colorsWithAlpha.length];
|
||||
// 记录分配的颜色
|
||||
colorAssignments.set(identifier, color);
|
||||
}
|
||||
baseColorList[index] = color;
|
||||
if (conditions.length > 0) {
|
||||
for (var i = 0; i < conditions.length; i++) {
|
||||
var c = conditions[i];
|
||||
var value = item[c.field.gisbiName];
|
||||
for (var _i = 0, _c = c.conditions; _i < _c.length; _i++) {
|
||||
var t_1 = _c[_i];
|
||||
var v = t_1.value;
|
||||
//保存一下颜色到map
|
||||
var _color = util_1.getColorFormAlphaColor(t_1.color);
|
||||
if (t_1.term === 'between') {
|
||||
var start = parseFloat(t_1.min);
|
||||
var end = parseFloat(t_1.max);
|
||||
if (start <= value && value <= end) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
else if ('lt' === t_1.term) {
|
||||
if (value < v) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
else if ('le' === t_1.term) {
|
||||
if (value <= v) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
else if ('gt' === t_1.term) {
|
||||
if (value > v) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
else if ('ge' === t_1.term) {
|
||||
if (value >= v) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
else if ('eq' === t_1.term) {
|
||||
if (value === v) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
else if ('not_eq' === t_1.term) {
|
||||
if (value !== v) {
|
||||
color = util_1.hexColorToRGBA(_color, alpha);
|
||||
baseColorList[index] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return __assign(__assign({}, item), { color: color, size: (_b = parseInt(item[sizeKey])) !== null && _b !== void 0 ? _b : mapSymbolSize, name: identifier });
|
||||
})
|
||||
: [];
|
||||
pointLayer = new l7_layers_1.PointLayer({ autoFit: !(basicStyle.autoFit === false) })
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName
|
||||
}
|
||||
})
|
||||
.active(true);
|
||||
if (!((_d = xAxisExt[0]) === null || _d === void 0 ? void 0 : _d.gisbiName)) return [3 /*break*/, 10];
|
||||
if (!(basicStyle.mapSymbol === 'custom' && basicStyle.customIcon)) return [3 /*break*/, 8];
|
||||
if (!basicStyle.customIcon.startsWith('data')) return [3 /*break*/, 2];
|
||||
scene.removeImage('customIcon');
|
||||
return [4 /*yield*/, scene.addImage('customIcon', basicStyle.customIcon)];
|
||||
case 1:
|
||||
_e.sent();
|
||||
pointLayer.shape('customIcon');
|
||||
return [3 /*break*/, 7];
|
||||
case 2:
|
||||
parser = new DOMParser();
|
||||
index = 0;
|
||||
_e.label = 3;
|
||||
case 3:
|
||||
if (!(index < Math.min(baseColorList.length, colorIndex + 1))) return [3 /*break*/, 6];
|
||||
color = baseColorList[index];
|
||||
fillRegex = /(fill="[^"]*")/g;
|
||||
svgStr = basicStyle.customIcon.replace(fillRegex, '');
|
||||
doc = parser.parseFromString(svgStr, 'image/svg+xml');
|
||||
svgEle = doc.documentElement;
|
||||
svgEle.setAttribute('fill', color);
|
||||
scene.removeImage("icon-" + color);
|
||||
return [4 /*yield*/, scene.addImage("icon-" + color, util_1.svgStrToUrl(svgEle.outerHTML))];
|
||||
case 4:
|
||||
_e.sent();
|
||||
_e.label = 5;
|
||||
case 5:
|
||||
index++;
|
||||
return [3 /*break*/, 3];
|
||||
case 6:
|
||||
pointLayer.shape('color', function (c) {
|
||||
return "icon-" + c;
|
||||
});
|
||||
_e.label = 7;
|
||||
case 7: return [3 /*break*/, 9];
|
||||
case 8:
|
||||
pointLayer.shape(mapSymbol).color('_index', baseColorList);
|
||||
pointLayer.style({
|
||||
stroke: {
|
||||
field: 'color'
|
||||
},
|
||||
strokeWidth: mapSymbolStrokeWidth,
|
||||
opacity: mapSymbolOpacity / 10
|
||||
});
|
||||
_e.label = 9;
|
||||
case 9: return [3 /*break*/, 16];
|
||||
case 10:
|
||||
if (!(basicStyle.mapSymbol === 'custom' && basicStyle.customIcon)) return [3 /*break*/, 15];
|
||||
scene.removeImage('customIcon');
|
||||
if (!basicStyle.customIcon.startsWith('data')) return [3 /*break*/, 12];
|
||||
return [4 /*yield*/, scene.addImage('customIcon', basicStyle.customIcon)];
|
||||
case 11:
|
||||
_e.sent();
|
||||
pointLayer.shape('customIcon');
|
||||
return [3 /*break*/, 14];
|
||||
case 12:
|
||||
parser = new DOMParser();
|
||||
color = baseColor;
|
||||
fillRegex = /(fill="[^"]*")/g;
|
||||
svgStr = basicStyle.customIcon.replace(fillRegex, '');
|
||||
doc = parser.parseFromString(svgStr, 'image/svg+xml');
|
||||
svgEle = doc.documentElement;
|
||||
svgEle.setAttribute('fill', color);
|
||||
return [4 /*yield*/, scene.addImage("customIcon", util_1.svgStrToUrl(svgEle.outerHTML))];
|
||||
case 13:
|
||||
_e.sent();
|
||||
pointLayer.shape('customIcon');
|
||||
_e.label = 14;
|
||||
case 14: return [3 /*break*/, 16];
|
||||
case 15:
|
||||
pointLayer
|
||||
.shape(mapSymbol)
|
||||
.color('_index', baseColorList)
|
||||
.style({
|
||||
stroke: {
|
||||
field: 'color'
|
||||
},
|
||||
strokeWidth: mapSymbolStrokeWidth,
|
||||
opacity: mapSymbolOpacity / 10
|
||||
});
|
||||
_e.label = 16;
|
||||
case 16:
|
||||
if (sizeKey) {
|
||||
pointLayer.size('size', [mapSymbolSizeMin, mapSymbolSizeMax]);
|
||||
}
|
||||
else {
|
||||
pointLayer.size(mapSymbolSize);
|
||||
}
|
||||
return [2 /*return*/, pointLayer];
|
||||
}
|
||||
});
|
||||
}); };
|
||||
/**
|
||||
* 合并详情到 map
|
||||
* @param details
|
||||
* @returns {Map<string, any>}
|
||||
*/
|
||||
_this.mergeDetailsToMap = function (details) {
|
||||
var resultMap = new Map();
|
||||
details.forEach(function (item) {
|
||||
Object.entries(item).forEach(function (_a) {
|
||||
var key = _a[0], value = _a[1];
|
||||
if (resultMap.has(key)) {
|
||||
var existingValue = resultMap.get(key);
|
||||
if (existingValue !== value) {
|
||||
resultMap.set(key, existingValue + ", " + value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
resultMap.set(key, value);
|
||||
}
|
||||
});
|
||||
});
|
||||
return resultMap;
|
||||
};
|
||||
/**
|
||||
* 清除 popup
|
||||
* @param container
|
||||
*/
|
||||
_this.clearPopup = function (container) {
|
||||
var containerElement = document.getElementById(container);
|
||||
containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelectorAll('.l7-popup').forEach(function (element) { return element.remove(); });
|
||||
};
|
||||
/**
|
||||
* 构建 tooltip
|
||||
* @param chart
|
||||
* @param pointLayer
|
||||
*/
|
||||
_this.buildTooltip = function (chart, container, pointLayer, scene) {
|
||||
var _a, _b;
|
||||
var customAttr = chart.customAttr ? util_1.parseJson(chart.customAttr) : null;
|
||||
_this.clearPopup(container);
|
||||
if ((_a = customAttr === null || customAttr === void 0 ? void 0 : customAttr.tooltip) === null || _a === void 0 ? void 0 : _a.show) {
|
||||
var tooltip_1 = utils_1.deepCopy(customAttr).tooltip;
|
||||
var showFields_1 = tooltip_1.showFields || [];
|
||||
if (!tooltip_1.showFields || tooltip_1.showFields.length === 0) {
|
||||
showFields_1 = __spreadArrays(chart.xAxisExt.map(function (i) { return i.gisbiName + "@" + i.name; }), chart.xAxis.map(function (i) { return i.gisbiName + "@" + i.name; }));
|
||||
}
|
||||
// 修改背景色
|
||||
var styleId = 'tooltip-' + container;
|
||||
var styleElement = document.getElementById(styleId);
|
||||
if (styleElement) {
|
||||
styleElement.remove();
|
||||
(_b = styleElement.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(styleElement);
|
||||
}
|
||||
var style = document.createElement('style');
|
||||
style.id = styleId;
|
||||
style.innerHTML = "\n #" + container + " .l7-popup-content {\n background-color: " + tooltip_1.backgroundColor + " !important;\n padding: 6px 10px 6px;\n line-height: 1.6;\n border-top-left-radius: 3px;\n }\n #" + container + " .l7-popup-tip {\n border-top-color: " + tooltip_1.backgroundColor + " !important;\n }\n ";
|
||||
document.head.appendChild(style);
|
||||
var htmlPrefix_1 = "<div style='font-size:" + tooltip_1.fontSize + "px;color:" + tooltip_1.color + ";font-family: " + chart.fontFamily + "'>";
|
||||
var htmlSuffix_1 = '</div>';
|
||||
var containerElement_1 = document.getElementById(container);
|
||||
if (containerElement_1) {
|
||||
containerElement_1.addEventListener('mousemove', function (event) {
|
||||
var rect = containerElement_1.getBoundingClientRect();
|
||||
var mouseX = event.clientX - rect.left;
|
||||
var mouseY = event.clientY - rect.top;
|
||||
var tooltipElement = containerElement_1.getElementsByClassName('l7-popup');
|
||||
for (var i = 0; i < (tooltipElement === null || tooltipElement === void 0 ? void 0 : tooltipElement.length); i++) {
|
||||
var element = tooltipElement[i];
|
||||
element.firstElementChild.style.display = 'none';
|
||||
element.style.transform = 'translate(15px, 12px)';
|
||||
var isNearRightEdge = containerElement_1.clientWidth - mouseX <= element.clientWidth + 10;
|
||||
var isNearBottomEdge = containerElement_1.clientHeight - mouseY <= element.clientHeight;
|
||||
var transform = '';
|
||||
if (isNearRightEdge) {
|
||||
transform += 'translateX(-120%) translateY(15%) ';
|
||||
}
|
||||
if (isNearBottomEdge) {
|
||||
transform += 'translateX(15%) translateY(-80%) ';
|
||||
}
|
||||
if (transform) {
|
||||
element.style.transform = transform.trim();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
pointLayer.on('touchend', function (e) {
|
||||
var _a;
|
||||
if (e.lngLat) {
|
||||
var fieldData = __assign(__assign({}, e.feature), Object.fromEntries(_this.mergeDetailsToMap((_a = e.feature.details) !== null && _a !== void 0 ? _a : [])));
|
||||
var content = _this.buildTooltipContent(tooltip_1, fieldData, showFields_1);
|
||||
var popup = new l7_2.Popup({
|
||||
lngLat: e.lngLat,
|
||||
title: '',
|
||||
closeButton: false,
|
||||
closeOnClick: true,
|
||||
html: "" + htmlPrefix_1 + content + htmlSuffix_1
|
||||
});
|
||||
scene.addPopup(popup);
|
||||
}
|
||||
});
|
||||
return new l7_2.LayerPopup({
|
||||
anchor: 'top-left',
|
||||
className: 'l7-popup-' + container,
|
||||
items: [
|
||||
{
|
||||
layer: pointLayer,
|
||||
customContent: function (item) {
|
||||
var fieldData = __assign(__assign({}, item), Object.fromEntries(_this.mergeDetailsToMap(item.details)));
|
||||
var content = _this.buildTooltipContent(tooltip_1, fieldData, showFields_1);
|
||||
return "" + htmlPrefix_1 + content + htmlSuffix_1;
|
||||
}
|
||||
}
|
||||
],
|
||||
trigger: 'hover'
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
/**
|
||||
* 构建 tooltip 内容
|
||||
* @param tooltip
|
||||
* @param fieldData
|
||||
* @param showFields
|
||||
* @returns {string}
|
||||
*/
|
||||
_this.buildTooltipContent = function (tooltip, fieldData, showFields) {
|
||||
var content = "";
|
||||
if (tooltip.customContent) {
|
||||
content = tooltip.customContent;
|
||||
showFields.forEach(function (field) {
|
||||
content = content.replace("${" + field.split('@')[1] + "}", fieldData[field.split('@')[0]]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
showFields.forEach(function (field) {
|
||||
content += "<span style=\"margin-bottom: 4px\">" + field.split('@')[1] + ": " + fieldData[field.split('@')[0]] + "</span><br>";
|
||||
});
|
||||
}
|
||||
return content.replace(/\n/g, '<br>');
|
||||
};
|
||||
/**
|
||||
* 构建 label
|
||||
* @param chart
|
||||
* @param configList
|
||||
*/
|
||||
_this.buildLabel = function (chart, configList) {
|
||||
var _a, _b;
|
||||
var xAxis = utils_1.deepCopy(chart.xAxis);
|
||||
var customAttr = chart.customAttr ? util_1.parseJson(chart.customAttr) : null;
|
||||
if ((_a = customAttr === null || customAttr === void 0 ? void 0 : customAttr.label) === null || _a === void 0 ? void 0 : _a.show) {
|
||||
var label_1 = customAttr.label;
|
||||
var data = ((_b = chart.data) === null || _b === void 0 ? void 0 : _b.tableRow) || [];
|
||||
var showFields_2 = label_1.showFields || [];
|
||||
if (!label_1.showFields || label_1.showFields.length === 0) {
|
||||
showFields_2 = __spreadArrays(chart.xAxisExt.map(function (i) { return i.gisbiName + "@" + i.name; }), chart.xAxis.map(function (i) { return i.gisbiName + "@" + i.name; }));
|
||||
}
|
||||
data.forEach(function (item) {
|
||||
var fieldData = __assign(__assign({}, item), Object.fromEntries(_this.mergeDetailsToMap(item.details)));
|
||||
var content = label_1.customContent || '';
|
||||
if (content) {
|
||||
showFields_2.forEach(function (field) {
|
||||
var _a = field.split('@'), fieldKey = _a[0], fieldName = _a[1];
|
||||
content = content.replace("${" + fieldName + "}", fieldData[fieldKey]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
content = showFields_2.map(function (field) { return fieldData[field.split('@')[0]]; }).join(',');
|
||||
}
|
||||
content = content.replace(/\n/g, '');
|
||||
item.textLayerContent = content;
|
||||
});
|
||||
configList.push(new l7_layers_1.PointLayer()
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName
|
||||
}
|
||||
})
|
||||
.shape('textLayerContent', 'text')
|
||||
.color(label_1.color)
|
||||
.size(label_1.fontSize)
|
||||
.style({
|
||||
textAllowOverlap: label_1.fullDisplay,
|
||||
textAnchor: 'center',
|
||||
textOffset: [0, 0],
|
||||
fontFamily: chart.fontFamily ? chart.fontFamily : undefined
|
||||
}));
|
||||
}
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
SymbolicMap.prototype.drawChart = function (drawOption) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var chart, container, action, containerDom, rect, xAxis, basicStyle, miscStyle, mapKey, mapStyle, center, lng, lat, chartObj, scene, configList, symbolicLayer, tooltipLayer;
|
||||
return __generator(this, function (_j) {
|
||||
switch (_j.label) {
|
||||
case 0:
|
||||
chart = drawOption.chart, container = drawOption.container, action = drawOption.action;
|
||||
containerDom = document.getElementById(container);
|
||||
rect = containerDom === null || containerDom === void 0 ? void 0 : containerDom.getBoundingClientRect();
|
||||
if ((rect === null || rect === void 0 ? void 0 : rect.height) <= 0) {
|
||||
return [2 /*return*/, new l7_1.L7Wrapper((_a = drawOption.chartObj) === null || _a === void 0 ? void 0 : _a.getScene(), [])];
|
||||
}
|
||||
xAxis = utils_1.deepCopy(chart.xAxis);
|
||||
if (chart.customAttr) {
|
||||
basicStyle = util_1.parseJson(chart.customAttr).basicStyle;
|
||||
miscStyle = util_1.parseJson(chart.customAttr).misc;
|
||||
}
|
||||
return [4 /*yield*/, this.getMapKey()];
|
||||
case 1:
|
||||
mapKey = _j.sent();
|
||||
mapStyle = common_antv_1.getMapStyle(mapKey, basicStyle);
|
||||
center = common_antv_1.getMapCenter(basicStyle);
|
||||
// 联动时,聚焦到数据点,多个取第一个
|
||||
if (((_c = (_b = chart.chartExtRequest) === null || _b === void 0 ? void 0 : _b.linkageFilters) === null || _c === void 0 ? void 0 : _c.length) &&
|
||||
(xAxis === null || xAxis === void 0 ? void 0 : xAxis.length) === 2 && ((_d = chart.data) === null || _d === void 0 ? void 0 : _d.tableRow.length)) {
|
||||
lng = (_f = (_e = chart.data) === null || _e === void 0 ? void 0 : _e.tableRow) === null || _f === void 0 ? void 0 : _f[0][chart.xAxis[0].gisbiName];
|
||||
lat = (_h = (_g = chart.data) === null || _g === void 0 ? void 0 : _g.tableRow) === null || _h === void 0 ? void 0 : _h[0][chart.xAxis[1].gisbiName];
|
||||
center = [lng, lat];
|
||||
}
|
||||
chartObj = drawOption.chartObj;
|
||||
scene = chartObj === null || chartObj === void 0 ? void 0 : chartObj.getScene();
|
||||
return [4 /*yield*/, common_antv_1.getMapScene(chart, scene, container, mapKey, basicStyle, miscStyle, mapStyle, center)];
|
||||
case 2:
|
||||
scene = _j.sent();
|
||||
this.configZoomButton(chart, scene, mapKey);
|
||||
if ((xAxis === null || xAxis === void 0 ? void 0 : xAxis.length) < 2) {
|
||||
return [2 /*return*/, new l7_1.L7Wrapper(scene, undefined)];
|
||||
}
|
||||
configList = [];
|
||||
return [4 /*yield*/, this.buildSymbolicLayer(chart, scene)];
|
||||
case 3:
|
||||
symbolicLayer = _j.sent();
|
||||
configList.push(symbolicLayer);
|
||||
tooltipLayer = this.buildTooltip(chart, container, symbolicLayer, scene);
|
||||
if (tooltipLayer) {
|
||||
scene.addPopup(tooltipLayer);
|
||||
}
|
||||
this.buildLabel(chart, configList);
|
||||
symbolicLayer.once('inited', function () {
|
||||
common_antv_1.mapRendered(container);
|
||||
});
|
||||
symbolicLayer.on('inited', function () {
|
||||
chart.container = container;
|
||||
tooltip_carousel_1.configCarouselTooltip(chart, symbolicLayer, symbolicLayer.sourceOption.data, scene);
|
||||
common_antv_1.qqMapRendered(scene);
|
||||
});
|
||||
symbolicLayer.on('click', function (ev) {
|
||||
var data = ev.feature;
|
||||
var dimensionList = [];
|
||||
var quotaList = [];
|
||||
chart.data.fields.forEach(function (item, index) {
|
||||
Object.keys(data).forEach(function (key) {
|
||||
if (key.startsWith('f_') && item.gisbiName === key) {
|
||||
if (index === 0) {
|
||||
dimensionList.push({
|
||||
id: item.id,
|
||||
gisbiName: item.gisbiName,
|
||||
value: data[key]
|
||||
});
|
||||
}
|
||||
else {
|
||||
quotaList.push({
|
||||
id: item.id,
|
||||
gisbiName: item.gisbiName,
|
||||
value: data[key]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
action({
|
||||
x: ev.x,
|
||||
y: ev.y,
|
||||
data: {
|
||||
data: __assign(__assign({}, data), { value: quotaList[0].value, name: dimensionList[0].id, dimensionList: dimensionList, quotaList: quotaList })
|
||||
}
|
||||
});
|
||||
});
|
||||
return [2 /*return*/, new l7_1.L7Wrapper(scene, configList)];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
SymbolicMap.prototype.setupDefaultOptions = function (chart) {
|
||||
chart.customAttr.label = __assign(__assign({}, chart.customAttr.label), { show: false });
|
||||
chart.customAttr.basicStyle = __assign(__assign({}, chart.customAttr.basicStyle), { mapSymbolOpacity: 5, mapStyle: 'normal' });
|
||||
return chart;
|
||||
};
|
||||
return SymbolicMap;
|
||||
}(l7_1.L7ChartView));
|
||||
exports.SymbolicMap = SymbolicMap;
|
558
frontend/src/data-visualization/chart/components/js/panel/charts/map/dist/tooltip-carousel.js
vendored
Normal file
558
frontend/src/data-visualization/chart/components/js/panel/charts/map/dist/tooltip-carousel.js
vendored
Normal file
@ -0,0 +1,558 @@
|
||||
"use strict";
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.CarouselManager = exports.carouselManagerInstances = exports.configCarouselTooltip = void 0;
|
||||
var l7_1 = require("@antv/l7");
|
||||
var isEmpty_1 = require("lodash-es/isEmpty");
|
||||
var formatter_1 = require("@/views/chart/components/js/formatter");
|
||||
var util_1 = require("@/views/chart/components/js/util");
|
||||
var utils_1 = require("@/utils/utils");
|
||||
exports.configCarouselTooltip = function (chart, view, data, scene, customSubArea, drawOption) {
|
||||
var _a;
|
||||
if (['bubble-map', 'map'].includes(chart.type)) {
|
||||
data = (_a = view.source.data.dataArray) === null || _a === void 0 ? void 0 : _a.filter(function (i) { var _a; return ((_a = i.dimensionList) === null || _a === void 0 ? void 0 : _a.length) > 0; }).reduce(function (acc, current) {
|
||||
var existingItem = acc.find(function (obj) {
|
||||
var _a;
|
||||
if ((_a = drawOption === null || drawOption === void 0 ? void 0 : drawOption.areaId) === null || _a === void 0 ? void 0 : _a.startsWith('custom_')) {
|
||||
return obj.areaName === current.areaName;
|
||||
}
|
||||
else {
|
||||
return obj.name === current.name || (obj.adcode && obj.adcode === current.adcode);
|
||||
}
|
||||
});
|
||||
if (!existingItem) {
|
||||
acc.push(current);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
if (exports.carouselManagerInstances[chart.container]) {
|
||||
var instances = exports.carouselManagerInstances[chart.container];
|
||||
instances.update(scene, chart, view, data, customSubArea, drawOption);
|
||||
}
|
||||
else {
|
||||
new CarouselManager(scene, chart, view, data, customSubArea, drawOption);
|
||||
}
|
||||
};
|
||||
exports.carouselManagerInstances = {};
|
||||
/**
|
||||
* 轮播管理类
|
||||
*/
|
||||
var CarouselManager = /** @class */ (function () {
|
||||
function CarouselManager(scene, chart, view, data, customSubArea, drawOption) {
|
||||
var _this = this;
|
||||
/**
|
||||
* 停留时长定时器
|
||||
* @private
|
||||
*/
|
||||
this.popupTimeoutId = null;
|
||||
/**
|
||||
* 轮播间隔定时器
|
||||
* @private
|
||||
*/
|
||||
this.popupIntervalId = null;
|
||||
/**
|
||||
* 是否暂停轮播
|
||||
* @private
|
||||
*/
|
||||
this.isPaused = false;
|
||||
/**
|
||||
* 当前显示的数据索引
|
||||
* @private
|
||||
*/
|
||||
this.currentIndex = 0;
|
||||
this.handleVisibilityChange = function () {
|
||||
if (document.hidden) {
|
||||
_this.clearPreviousInstance(_this.chart.container);
|
||||
}
|
||||
else {
|
||||
_this.startCarouselPopups();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 鼠标移入暂停轮播
|
||||
*/
|
||||
this.pauseCarouselPopups = function () {
|
||||
var _a;
|
||||
if (_this.popup) {
|
||||
(_a = _this.popup) === null || _a === void 0 ? void 0 : _a.remove();
|
||||
}
|
||||
_this.removeStyle();
|
||||
_this.isPaused = true;
|
||||
_this.clearExistingTimers();
|
||||
};
|
||||
/**
|
||||
* 鼠标移出开始轮播
|
||||
*/
|
||||
this.resumeCarouselPopups = function () {
|
||||
if (_this.isPaused) {
|
||||
_this.isPaused = false;
|
||||
_this.startCarouselPopups();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 清除定时器
|
||||
* @private
|
||||
*/
|
||||
this.clearExistingTimers = function () {
|
||||
if (_this.popupTimeoutId !== null) {
|
||||
clearTimeout(_this.popupTimeoutId);
|
||||
_this.popupTimeoutId = 0;
|
||||
}
|
||||
if (_this.popupIntervalId !== null) {
|
||||
clearInterval(_this.popupIntervalId);
|
||||
_this.popupIntervalId = 0;
|
||||
}
|
||||
};
|
||||
// 绑定事件处理函数
|
||||
this.onMouseEnterHandler = this.pauseCarouselPopups.bind(this);
|
||||
this.onMouseLeaveHandler = this.resumeCarouselPopups.bind(this);
|
||||
this.onVisibilityChangeHandler = this.handleVisibilityChange.bind(this);
|
||||
this.clearExistingTimers = this.clearExistingTimers.bind(this);
|
||||
this.init(scene, chart, view, data, customSubArea, drawOption);
|
||||
}
|
||||
/**
|
||||
* 更新轮播弹窗对象内容
|
||||
* @param scene
|
||||
* @param chart
|
||||
* @param view
|
||||
* @param data
|
||||
* @param customSubArea
|
||||
*/
|
||||
CarouselManager.prototype.update = function (scene, chart, view, data, customSubArea, drawOption) {
|
||||
this.init(scene, chart, view, data, customSubArea, drawOption);
|
||||
};
|
||||
/**
|
||||
* 初始化轮播弹窗
|
||||
* @param scene
|
||||
* @param chart
|
||||
* @param view
|
||||
* @param data
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.init = function (scene, chart, view, data, customSubArea, drawOption) {
|
||||
var _this = this;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
||||
this.view = view;
|
||||
this.chart = chart;
|
||||
this.scene = scene;
|
||||
this.data = data;
|
||||
this.popup = null;
|
||||
this.currentIndex = 0;
|
||||
this.customSubArea = customSubArea;
|
||||
this.drawOption = drawOption;
|
||||
this.clearPreviousInstance(this.chart.container);
|
||||
if (((_b = (_a = this.chart.customAttr) === null || _a === void 0 ? void 0 : _a.tooltip) === null || _b === void 0 ? void 0 : _b.show) && ((_e = (_d = (_c = this.chart.customAttr) === null || _c === void 0 ? void 0 : _c.tooltip) === null || _d === void 0 ? void 0 : _d.carousel) === null || _e === void 0 ? void 0 : _e.enable) &&
|
||||
this.data.length > 0) {
|
||||
this.popup = new l7_1.Popup({ closeButton: false, maxWidth: 600 });
|
||||
var carousel = (_g = (_f = this.chart.customAttr) === null || _f === void 0 ? void 0 : _f.tooltip) === null || _g === void 0 ? void 0 : _g.carousel;
|
||||
this.stayTime = carousel.stayTime * 1000;
|
||||
this.intervalTime = carousel.intervalTime * 1000;
|
||||
this.startCarouselPopups();
|
||||
var divElement = document.getElementById(this.chart.container);
|
||||
divElement.addEventListener('mouseenter', this.pauseCarouselPopups);
|
||||
divElement.addEventListener('mouseleave', this.resumeCarouselPopups);
|
||||
// 移动端符号地图不支持mouseenter和mouseleave事件,这里特殊处理一下
|
||||
if (this.chart.type === 'symbolic-map') {
|
||||
// 监听符号触摸事件, 暂停轮播
|
||||
(_j = (_h = scene === null || scene === void 0 ? void 0 : scene.getLayers()) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.addListener('touchend', function () {
|
||||
_this.pauseCarouselPopups();
|
||||
});
|
||||
// 地图空白区域触摸事件, 启动轮播
|
||||
(_k = scene === null || scene === void 0 ? void 0 : scene.getMapCanvasContainer()) === null || _k === void 0 ? void 0 : _k.addEventListener('touchend', function () {
|
||||
_this.resumeCarouselPopups();
|
||||
});
|
||||
}
|
||||
// 监听页面可见性变化
|
||||
document.addEventListener('visibilitychange', this.handleVisibilityChange);
|
||||
exports.carouselManagerInstances[this.chart.container] = this;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 清除之前的实例数据
|
||||
* @param containerId
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.clearPreviousInstance = function (containerId) {
|
||||
var _a;
|
||||
if (exports.carouselManagerInstances[containerId]) {
|
||||
var instance = exports.carouselManagerInstances[containerId];
|
||||
this.clearExistingTimers();
|
||||
(_a = instance.popup) === null || _a === void 0 ? void 0 : _a.remove();
|
||||
instance.removeStyle();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 开始轮播
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.startCarouselPopups = function () {
|
||||
this.clearExistingTimers();
|
||||
this.carouselPopups();
|
||||
};
|
||||
/**
|
||||
* 管理轮播弹窗的显示
|
||||
*
|
||||
* 此方法用于处理轮播弹窗的显示逻辑它会根据当前的索引显示对应的弹窗,
|
||||
* 并在一定时间后自动移除当前弹窗并显示下一个弹窗
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.carouselPopups = function () {
|
||||
var _this = this;
|
||||
var showPopup = function (index) {
|
||||
_this.removeStyle();
|
||||
var containerElement = document.getElementById(_this.chart.container);
|
||||
if (containerElement) {
|
||||
if (_this.chart.type === 'symbolic-map') {
|
||||
// 轮播进行时,隐藏隐藏鼠标悬浮的tooltip
|
||||
var mouseTooltip = containerElement.getElementsByClassName('l7-popup-' + _this.chart.container);
|
||||
for (var _i = 0, _a = Array.from(mouseTooltip); _i < _a.length; _i++) {
|
||||
var tooltip = _a[_i];
|
||||
var tooltipElement = tooltip;
|
||||
tooltipElement.classList.add('l7-popup-hide');
|
||||
}
|
||||
_this.createSymbolicMapPopup(index);
|
||||
}
|
||||
else {
|
||||
if (_this.chart.type === 'map') {
|
||||
// 轮播进行时,隐藏隐藏鼠标悬浮的tooltip
|
||||
var mouseTooltip = containerElement.getElementsByClassName('l7plot-tooltip-container');
|
||||
for (var _b = 0, _c = Array.from(mouseTooltip); _b < _c.length; _b++) {
|
||||
var tooltip = _c[_b];
|
||||
var tooltipElement = tooltip;
|
||||
tooltipElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
_this.createPopup(index);
|
||||
}
|
||||
_this.clearExistingTimers();
|
||||
_this.popupTimeoutId = window.setTimeout(function () {
|
||||
var _a;
|
||||
_this.currentIndex++;
|
||||
(_a = _this.popup) === null || _a === void 0 ? void 0 : _a.remove();
|
||||
_this.cancelHighlightLayer(index);
|
||||
if (_this.currentIndex >= _this.data.length) {
|
||||
_this.currentIndex = 0;
|
||||
}
|
||||
_this.popupIntervalId = window.setTimeout(function () {
|
||||
showPopup(_this.currentIndex);
|
||||
}, _this.intervalTime);
|
||||
}, _this.stayTime);
|
||||
}
|
||||
else {
|
||||
_this.clearExistingTimers();
|
||||
}
|
||||
};
|
||||
showPopup(this.currentIndex);
|
||||
};
|
||||
/**
|
||||
* 移除样式
|
||||
* 每次创建弹窗前移除之前的样式
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.removeStyle = function () {
|
||||
var _a;
|
||||
var styleToRemove = document.getElementById('style-' + this.chart.container);
|
||||
if (styleToRemove) {
|
||||
styleToRemove.remove();
|
||||
(_a = styleToRemove.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(styleToRemove);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 创建弹窗信息
|
||||
* @param index
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.createPopup = function (index) {
|
||||
var _this = this;
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
var tooltipStyle = this.view.tooltip.options.domStyles;
|
||||
var tooltipBackgroundColor = tooltipStyle['l7plot-tooltip']['background-color'];
|
||||
var tooltipFontSize = tooltipStyle['l7plot-tooltip']['font-size'];
|
||||
var style = document.createElement('style');
|
||||
style.id = 'style-' + this.chart.container;
|
||||
style.innerHTML = "\n #" + this.chart.container + " .l7-popup-content {\n background-color: " + tooltipBackgroundColor + " !important;\n font-size: " + tooltipFontSize + ";\n padding: 10px 10px 6px;\n line-height: 1.6;\n }\n #" + this.chart.container + " .l7-popup-tip {\n border-top-color: " + tooltipBackgroundColor + " !important;\n }\n ";
|
||||
document.head.appendChild(style);
|
||||
var popupData = this.getPopupData(index);
|
||||
if (popupData.data) {
|
||||
var tooltipItem_1 = '';
|
||||
this.getTooltipItems(popupData.data).forEach(function (fieldData) {
|
||||
tooltipItem_1 += "\n <li style=\"list-style-type: none; margin-bottom: 4px; white-space: nowrap; display: flex; justify-content: space-between;\">\n <span style=\"" + _this.objectToSemicolonSeparated(tooltipStyle['l7plot-tooltip__name']) + "\">" + fieldData.name + "</span>\n <span style=\"" + _this.objectToSemicolonSeparated(tooltipStyle['l7plot-tooltip__value']) + "\">" + fieldData.value + "</span>\n </li>";
|
||||
});
|
||||
var html = "\n <div>\n <div style=\"" + this.objectToSemicolonSeparated(tooltipStyle['l7plot-tooltip__title']) + "\">" + popupData.data.name + "</div>\n <ul style=\"" + this.objectToSemicolonSeparated(tooltipStyle['l7plot-tooltip__list']) + "\">\n " + tooltipItem_1 + "\n </ul>\n </div>\n ";
|
||||
this.popup.setLngLat({ lng: popupData.centroid[0], lat: popupData.centroid[1] });
|
||||
this.popup.setHTML(html);
|
||||
this.popup.closeButton = false;
|
||||
this.view.addLayer(this.popup);
|
||||
// 地图层高亮
|
||||
(_b = (_a = this.view.scene
|
||||
.getLayers()) === null || _a === void 0 ? void 0 : _a.find(function (i) { return i.name === 'highlightLayer'; })) === null || _b === void 0 ? void 0 : _b.setData(this.getActiveData(index));
|
||||
if (this.chart.type === 'bubble-map') {
|
||||
// 气泡地图高亮
|
||||
var _id = ((_d = (_c = this.view.scene
|
||||
.getLayers()) === null || _c === void 0 ? void 0 : _c.find(function (i) { return i.name === 'bubbleLayer'; })) === null || _d === void 0 ? void 0 : _d.layerSource.data.dataArray.find(function (i) { return i.name === _this.data[index].name; }))._id;
|
||||
(_f = (_e = this.view.scene
|
||||
.getLayers()) === null || _e === void 0 ? void 0 : _e.find(function (i) { return i.name === 'bubbleLayer' && i.coordCenter; })) === null || _f === void 0 ? void 0 : _f.setActive(_id, { color: 'rgba(30,90,255,1)' });
|
||||
}
|
||||
}
|
||||
};
|
||||
CarouselManager.prototype.getActiveData = function (index) {
|
||||
var _this = this;
|
||||
var _a, _b, _c;
|
||||
if ((_b = (_a = this.drawOption) === null || _a === void 0 ? void 0 : _a.areaId) === null || _b === void 0 ? void 0 : _b.startsWith('custom_')) {
|
||||
var result_1 = {
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
};
|
||||
var area = this.customSubArea.find(function (a) { return a.name === _this.data[index].areaName; });
|
||||
var areaMap_1 = this.view.currentDistrictData.features.reduce(function (p, n) {
|
||||
p['156' + n.properties.adcode] = n;
|
||||
return p;
|
||||
}, {});
|
||||
(_c = area === null || area === void 0 ? void 0 : area.scopeArr) === null || _c === void 0 ? void 0 : _c.forEach(function (s) {
|
||||
if (areaMap_1[s]) {
|
||||
result_1.features.push(areaMap_1[s]);
|
||||
}
|
||||
});
|
||||
return result_1;
|
||||
}
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
this.view.currentDistrictData.features.find(function (i) { return i.properties.name === _this.data[index].name; })
|
||||
]
|
||||
};
|
||||
};
|
||||
/**
|
||||
* 获取弹窗信息,包括原始数据及位置信息
|
||||
* @param index
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.getPopupData = function (index) {
|
||||
var _this = this;
|
||||
var _a, _b, _c, _d;
|
||||
if ((_b = (_a = this.drawOption) === null || _a === void 0 ? void 0 : _a.areaId) === null || _b === void 0 ? void 0 : _b.startsWith('custom_')) {
|
||||
var data_1 = this.data[index];
|
||||
var area = (_c = this.customSubArea) === null || _c === void 0 ? void 0 : _c.find(function (a) { return a.name === data_1.areaName; });
|
||||
data_1.name = data_1.areaName;
|
||||
return {
|
||||
data: data_1,
|
||||
centroid: area.centroid
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
data: this.data[index],
|
||||
centroid: (_d = this.view.currentDistrictData.features.find(function (i) { return i.properties.name === _this.data[index].name; })) === null || _d === void 0 ? void 0 : _d.properties.centroid
|
||||
};
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 将对象转换为 CSS 属性
|
||||
* @param obj
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.objectToSemicolonSeparated = function (obj) {
|
||||
var result = '';
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
result += this.convertToSnakeCase(key) + ":" + obj[key] + ";";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
CarouselManager.prototype.cancelHighlightLayer = function (index) {
|
||||
var _this = this;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
||||
(_c = (_b = (_a = this.view.scene) === null || _a === void 0 ? void 0 : _a.getLayers()) === null || _b === void 0 ? void 0 : _b.find(function (i) { return i.name === 'highlightLayer'; })) === null || _c === void 0 ? void 0 : _c.setData({ type: 'FeatureCollection', features: [] });
|
||||
if (this.chart.type === 'bubble-map') {
|
||||
var _id = ((_f = (_e = (_d = this.view.scene) === null || _d === void 0 ? void 0 : _d.getLayers()) === null || _e === void 0 ? void 0 : _e.find(function (i) { return i.name === 'bubbleLayer'; })) === null || _f === void 0 ? void 0 : _f.layerSource.data.dataArray.find(function (i) { return i.name === _this.data[index].name; }))._id;
|
||||
(_h = (_g = this.view.scene
|
||||
.getLayers()) === null || _g === void 0 ? void 0 : _g.find(function (i) { return i.name === 'bubbleLayer' && i.coordCenter; })) === null || _h === void 0 ? void 0 : _h.setActive(_id, {
|
||||
color: this.view.scene
|
||||
.getLayers()
|
||||
.find(function (i) { return i.name === 'bubbleLayer'; })
|
||||
.styleAttributeService.getLayerStyleAttribute('color').scale.field
|
||||
});
|
||||
}
|
||||
if (this.chart.type === 'symbolic-map') {
|
||||
var lngField_1 = this.chart.xAxis[0].gisbiName;
|
||||
var latField_1 = this.chart.xAxis[1].gisbiName;
|
||||
var _id = ((_l = (_k = (_j = this.scene) === null || _j === void 0 ? void 0 : _j.getLayers()) === null || _k === void 0 ? void 0 : _k.find(function (i) { return i.type === 'PointLayer'; })) === null || _l === void 0 ? void 0 : _l.layerSource.data.dataArray.find(function (i) {
|
||||
var targetLng = _this.data[index][lngField_1];
|
||||
var targetLat = _this.data[index][latField_1];
|
||||
return i[lngField_1] === targetLng && i[latField_1] === targetLat;
|
||||
}))._id;
|
||||
(_o = (_m = this.scene
|
||||
.getLayers()) === null || _m === void 0 ? void 0 : _m.find(function (i) { return i.type === 'PointLayer' && i.coordCenter; })) === null || _o === void 0 ? void 0 : _o.setActive(_id, {
|
||||
color: this.scene
|
||||
.getLayers()
|
||||
.find(function (i) { return i.type === 'PointLayer'; })
|
||||
.styleAttributeService.getLayerStyleAttribute('color').scale.field
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 将驼峰式命名转换为蛇形命名
|
||||
* @param str
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.convertToSnakeCase = function (str) {
|
||||
return str.replace(/([A-Z])/g, function (match) { return '-' + match.toLowerCase(); });
|
||||
};
|
||||
/**
|
||||
* 获取弹窗字段信息
|
||||
* 与tooltip要显示的内容一致
|
||||
* @param data
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.getTooltipItems = function (data) {
|
||||
var _a, _b, _c, _d;
|
||||
var result = [];
|
||||
var customAttr = util_1.parseJson(this.chart.customAttr);
|
||||
var tooltip = customAttr.tooltip;
|
||||
var formatterMap = (_a = tooltip.seriesTooltipFormatter) === null || _a === void 0 ? void 0 : _a.filter(function (i) { return i.show; }).reduce(function (pre, next) {
|
||||
pre[next.id] = next;
|
||||
return pre;
|
||||
}, {});
|
||||
if (isEmpty_1["default"](formatterMap)) {
|
||||
return result;
|
||||
}
|
||||
var head = data;
|
||||
var formatter = formatterMap[(_c = (_b = head.quotaList) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.id];
|
||||
if (!isEmpty_1["default"](formatter)) {
|
||||
var originValue = parseFloat(head.value);
|
||||
var value = formatter_1.valueFormatter(originValue, formatter.formatterCfg);
|
||||
var name = isEmpty_1["default"](formatter.chartShowName) ? formatter.name : formatter.chartShowName;
|
||||
result.push(__assign(__assign({}, head), { name: name, value: "" + (value !== null && value !== void 0 ? value : '') }));
|
||||
}
|
||||
(_d = head.dynamicTooltipValue) === null || _d === void 0 ? void 0 : _d.forEach(function (item) {
|
||||
var formatter = formatterMap[item.fieldId];
|
||||
if (formatter) {
|
||||
var value = formatter_1.valueFormatter(parseFloat(item.value), formatter.formatterCfg);
|
||||
var name = isEmpty_1["default"](formatter.chartShowName) ? formatter.name : formatter.chartShowName;
|
||||
result.push({ color: 'grey', name: name, value: "" + (value !== null && value !== void 0 ? value : '') });
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* 符号地图特殊处理,tooltip的配置可自定义显示内容
|
||||
* @param index
|
||||
* @private
|
||||
*/
|
||||
CarouselManager.prototype.createSymbolicMapPopup = function (index) {
|
||||
var _this = this;
|
||||
var buildTooltip = function () {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
var customAttr = _this.chart.customAttr ? util_1.parseJson(_this.chart.customAttr) : null;
|
||||
if ((_a = customAttr === null || customAttr === void 0 ? void 0 : customAttr.tooltip) === null || _a === void 0 ? void 0 : _a.show) {
|
||||
if (!_this.popup) {
|
||||
return undefined;
|
||||
}
|
||||
var tooltip = utils_1.deepCopy(customAttr).tooltip;
|
||||
var showFields = tooltip.showFields || [];
|
||||
if (!tooltip.showFields || tooltip.showFields.length === 0) {
|
||||
showFields = __spreadArrays(_this.chart.xAxisExt.map(function (i) { return i.gisbiName + "@" + i.name; }), _this.chart.xAxis.map(function (i) { return i.gisbiName + "@" + i.name; }));
|
||||
}
|
||||
var style = document.createElement('style');
|
||||
style.id = 'style-' + _this.chart.container;
|
||||
style.innerHTML = "\n #" + _this.chart.container + " .l7-popup-content {\n background-color: " + tooltip.backgroundColor + " !important;\n padding: 6px 10px 6px;\n line-height: 1.6;\n }\n #" + _this.chart.container + " .l7-popup-tip {\n border-top-color: " + tooltip.backgroundColor + " !important;\n }\n ";
|
||||
document.head.appendChild(style);
|
||||
var lngField_2 = _this.chart.xAxis[0].gisbiName;
|
||||
var latField_2 = _this.chart.xAxis[1].gisbiName;
|
||||
var htmlPrefix = "<div style='font-size:" + tooltip.fontSize + "px;color:" + tooltip.color + ";'>";
|
||||
var htmlSuffix = '</div>';
|
||||
var data = _this.view.sourceOption.data[index];
|
||||
if (data && ((_b = data.details) === null || _b === void 0 ? void 0 : _b.length)) {
|
||||
var fieldData = __assign(__assign({}, data), Object.fromEntries(mergeDetailsToMap(data.details)));
|
||||
var content = buildTooltipContent(tooltip, fieldData, showFields);
|
||||
var html = "" + htmlPrefix + content + htmlSuffix;
|
||||
_this.popup.setLngLat({
|
||||
lng: data[lngField_2],
|
||||
lat: data[latField_2]
|
||||
});
|
||||
_this.popup.setHTML(html);
|
||||
_this.popup.closeButton = false;
|
||||
_this.scene.addPopup(_this.popup);
|
||||
_this.popup.addTo(_this.scene);
|
||||
var _id = ((_d = (_c = _this.scene
|
||||
.getLayers()) === null || _c === void 0 ? void 0 : _c.find(function (i) { return i.type === 'PointLayer'; })) === null || _d === void 0 ? void 0 : _d.layerSource.data.dataArray.find(function (i) {
|
||||
var targetLng = _this.data[index][lngField_2];
|
||||
var targetLat = _this.data[index][latField_2];
|
||||
return i[lngField_2] === targetLng && i[latField_2] === targetLat;
|
||||
}))._id;
|
||||
(_f = (_e = _this.scene
|
||||
.getLayers()) === null || _e === void 0 ? void 0 : _e.find(function (i) { return i.type === 'PointLayer' && i.coordCenter; })) === null || _f === void 0 ? void 0 : _f.setActive(_id, { color: 'rgba(30,90,255,1)' });
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
/**
|
||||
* 构建 tooltip 内容
|
||||
* @param tooltip
|
||||
* @param fieldData
|
||||
* @param showFields
|
||||
* @returns {string}
|
||||
*/
|
||||
var buildTooltipContent = function (tooltip, fieldData, showFields) {
|
||||
var content = '';
|
||||
if (tooltip.customContent) {
|
||||
content = tooltip.customContent;
|
||||
showFields.forEach(function (field) {
|
||||
content = content.replace("${" + field.split('@')[1] + "}", fieldData[field.split('@')[0]]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
showFields.forEach(function (field) {
|
||||
content += "<span style=\"margin-bottom: 4px\">" + field.split('@')[1] + ": " + fieldData[field.split('@')[0]] + "</span><br>";
|
||||
});
|
||||
}
|
||||
return content.replace(/\n/g, '<br>');
|
||||
};
|
||||
/**
|
||||
* 合并详情到 map
|
||||
* @param details
|
||||
* @returns {Map<string, any>}
|
||||
*/
|
||||
var mergeDetailsToMap = function (details) {
|
||||
var resultMap = new Map();
|
||||
details.forEach(function (item) {
|
||||
Object.entries(item).forEach(function (_a) {
|
||||
var key = _a[0], value = _a[1];
|
||||
if (resultMap.has(key)) {
|
||||
var existingValue = resultMap.get(key);
|
||||
if (existingValue !== value) {
|
||||
resultMap.set(key, existingValue + ", " + value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
resultMap.set(key, value);
|
||||
}
|
||||
});
|
||||
});
|
||||
return resultMap;
|
||||
};
|
||||
buildTooltip();
|
||||
};
|
||||
return CarouselManager;
|
||||
}());
|
||||
exports.CarouselManager = CarouselManager;
|
@ -1,18 +1,18 @@
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import {
|
||||
L7ChartView,
|
||||
L7Config,
|
||||
L7DrawConfig,
|
||||
L7Wrapper
|
||||
} from '@/data-visualization/chart/components/js/panel/types/impl/l7'
|
||||
import { MAP_EDITOR_PROPERTY_INNER } from '@/data-visualization/chart/components/js/panel/charts/map/common'
|
||||
import { flow, parseJson } from '@/data-visualization/chart/components/js/util'
|
||||
import { deepCopy } from '@/data-visualization/utils/utils'
|
||||
} from '@/views/chart/components/js/panel/types/impl/l7'
|
||||
import { MAP_EDITOR_PROPERTY_INNER } from '@/views/chart/components/js/panel/charts/map/common'
|
||||
import { flow, parseJson } from '@/views/chart/components/js/util'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
import { GaodeMap } from '@antv/l7-maps'
|
||||
import { Scene } from '@antv/l7-scene'
|
||||
import { HeatmapLayer } from '@antv/l7-layers'
|
||||
import { DEFAULT_BASIC_STYLE } from '@/data-visualization/chart/components/editor/util/chart'
|
||||
import { mapRendered, mapRendering } from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart'
|
||||
import { mapRendered, mapRendering } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
const { t } = useI18n()
|
||||
|
||||
/**
|
||||
|
@ -157,6 +157,11 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
})
|
||||
})
|
||||
data = filterChartDataByRange(sourceData, maxValue, minValue)
|
||||
if (chart.drill) {
|
||||
getMaxAndMinValueByData(sourceData, 'value', 0, 0, (max, min) => {
|
||||
data = filterChartDataByRange(sourceData, max, min)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
data = sourceData
|
||||
}
|
||||
@ -301,7 +306,8 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
content.push(name)
|
||||
}
|
||||
if (label.showQuota) {
|
||||
areaMap[name] && content.push(valueFormatter(areaMap[name], label.quotaLabelFormatter))
|
||||
;(areaMap[name] || areaMap[name] === 0) &&
|
||||
content.push(valueFormatter(areaMap[name], label.quotaLabelFormatter))
|
||||
}
|
||||
item.properties['_DE_LABEL_'] = content.join('\n\n')
|
||||
}
|
||||
@ -346,11 +352,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
return listDom
|
||||
}
|
||||
|
||||
private customConfigLegend(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
context: Record<string, any>
|
||||
): ChoroplethOptions {
|
||||
private customConfigLegend(chart: Chart, options: ChoroplethOptions): ChoroplethOptions {
|
||||
const { basicStyle, misc } = parseJson(chart.customAttr)
|
||||
const colors = basicStyle.colors.map(item => hexColorToRGBA(item, basicStyle.alpha))
|
||||
if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
|
||||
@ -420,14 +422,14 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
const isLessThanMin = range[0] < ranges[0][0] && range[1] < ranges[0][0]
|
||||
let rangeColor = colors[colorIndex]
|
||||
if (isLessThanMin) {
|
||||
rangeColor = hexColorToRGBA(basicStyle.areaBaseColor, basicStyle.alpha)
|
||||
rangeColor = basicStyle.areaBaseColor
|
||||
}
|
||||
items.push({
|
||||
value: tmpRange,
|
||||
color: rangeColor
|
||||
})
|
||||
})
|
||||
customLegend['customContent'] = (_: string, _items: CategoryLegendListItem[]) => {
|
||||
customLegend['customContent'] = () => {
|
||||
if (items?.length) {
|
||||
return this.createLegendCustomContent(items)
|
||||
}
|
||||
@ -435,13 +437,16 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
}
|
||||
options.color['value'] = ({ value }) => {
|
||||
const item = items.find(item => value >= item.value[0] && value <= item.value[1])
|
||||
return item ? item.color : hexColorToRGBA(basicStyle.areaBaseColor, basicStyle.alpha)
|
||||
return item ? item.color : basicStyle.areaBaseColor
|
||||
}
|
||||
options.color.scale.domain = [ranges[0][0], ranges[ranges.length - 1][1]]
|
||||
} else {
|
||||
customLegend['customContent'] = (_: string, items: CategoryLegendListItem[]) => {
|
||||
const showItems = items?.length > 30 ? items.slice(0, 30) : items
|
||||
if (showItems?.length) {
|
||||
if (showItems.length === 1) {
|
||||
showItems[0].value = options.color.scale.domain.slice(0, 2)
|
||||
}
|
||||
return this.createLegendCustomContent(showItems)
|
||||
}
|
||||
return ''
|
||||
@ -508,7 +513,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
content.push(area.name)
|
||||
}
|
||||
if (label.showQuota) {
|
||||
areaMap[area.name] &&
|
||||
;(areaMap[area.name] || areaMap[area.name] === 0) &&
|
||||
content.push(valueFormatter(areaMap[area.name].value, label.quotaLabelFormatter))
|
||||
}
|
||||
labelLocation.push({
|
||||
@ -567,6 +572,9 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
return result
|
||||
}
|
||||
const head = originalItem.properties
|
||||
if (!head) {
|
||||
return result
|
||||
}
|
||||
const { adcode } = head
|
||||
const areaName = subAreaMap['156' + adcode]
|
||||
const valItem = areaMap[areaName]
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import {
|
||||
L7ChartView,
|
||||
L7Config,
|
||||
@ -13,13 +13,17 @@ import {
|
||||
svgStrToUrl
|
||||
} from '@/data-visualization/chart/components/js/util'
|
||||
import { deepCopy } from '@/data-visualization/utils/utils'
|
||||
import { GaodeMap } from '@antv/l7-maps'
|
||||
import { Scene } from '@antv/l7-scene'
|
||||
import { PointLayer } from '@antv/l7-layers'
|
||||
import { LayerPopup, Popup } from '@antv/l7'
|
||||
import { mapRendered, mapRendering } from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import {
|
||||
getMapCenter,
|
||||
getMapScene,
|
||||
getMapStyle,
|
||||
mapRendered,
|
||||
qqMapRendered
|
||||
} from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import { configCarouselTooltip } from '@/data-visualization/chart/components/js/panel/charts/map/tooltip-carousel'
|
||||
import { DEFAULT_BASIC_STYLE } from '@/data-visualization/chart/components/editor/util/chart'
|
||||
import { filter } from 'lodash-es'
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -102,18 +106,10 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
miscStyle = parseJson(chart.customAttr).misc
|
||||
}
|
||||
|
||||
let mapStyle = basicStyle.mapStyleUrl
|
||||
if (basicStyle.mapStyle !== 'custom') {
|
||||
mapStyle = `amap://styles/${basicStyle.mapStyle ? basicStyle.mapStyle : 'normal'}`
|
||||
}
|
||||
const mapKey = await this.getMapKey()
|
||||
let center: [number, number] = [
|
||||
DEFAULT_BASIC_STYLE.mapCenter.longitude,
|
||||
DEFAULT_BASIC_STYLE.mapCenter.latitude
|
||||
]
|
||||
if (basicStyle.autoFit === false) {
|
||||
center = [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
}
|
||||
const mapStyle = getMapStyle(mapKey, basicStyle)
|
||||
|
||||
let center = getMapCenter(basicStyle)
|
||||
// 联动时,聚焦到数据点,多个取第一个
|
||||
if (
|
||||
chart.chartExtRequest?.linkageFilters?.length &&
|
||||
@ -121,45 +117,25 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
chart.data?.tableRow.length
|
||||
) {
|
||||
// 经度
|
||||
const lng = chart.data?.tableRow?.[0][chart.xAxis[0].dataeaseName]
|
||||
const lng = chart.data?.tableRow?.[0][chart.xAxis[0].gisbiName]
|
||||
// 纬度
|
||||
const lat = chart.data?.tableRow?.[0][chart.xAxis[1].dataeaseName]
|
||||
const lat = chart.data?.tableRow?.[0][chart.xAxis[1].gisbiName]
|
||||
center = [lng, lat]
|
||||
}
|
||||
const chartObj = drawOption.chartObj as unknown as L7Wrapper<L7Config, Scene>
|
||||
let scene = chartObj?.getScene()
|
||||
if (!scene) {
|
||||
scene = new Scene({
|
||||
id: container,
|
||||
logoVisible: false,
|
||||
map: new GaodeMap({
|
||||
token: mapKey?.key ?? undefined,
|
||||
style: mapStyle,
|
||||
pitch: miscStyle.mapPitch,
|
||||
center,
|
||||
zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : undefined,
|
||||
showLabel: !(basicStyle.showLabel === false),
|
||||
WebGLParams: {
|
||||
preserveDrawingBuffer: true
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
if (scene.getLayers()?.length) {
|
||||
await scene.removeAllLayer()
|
||||
scene.setPitch(miscStyle.mapPitch)
|
||||
scene.setMapStyle(mapStyle)
|
||||
scene.map.showLabel = !(basicStyle.showLabel === false)
|
||||
}
|
||||
if (basicStyle.autoFit === false) {
|
||||
scene.setZoomAndCenter(basicStyle.zoomLevel, center)
|
||||
}
|
||||
}
|
||||
mapRendering(container)
|
||||
scene.once('loaded', () => {
|
||||
mapRendered(container)
|
||||
})
|
||||
this.configZoomButton(chart, scene)
|
||||
scene = await getMapScene(
|
||||
chart,
|
||||
scene,
|
||||
container,
|
||||
mapKey,
|
||||
basicStyle,
|
||||
miscStyle,
|
||||
mapStyle,
|
||||
center
|
||||
)
|
||||
|
||||
this.configZoomButton(chart, scene, mapKey)
|
||||
if (xAxis?.length < 2) {
|
||||
return new L7Wrapper(scene, undefined)
|
||||
}
|
||||
@ -171,9 +147,13 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
scene.addPopup(tooltipLayer)
|
||||
}
|
||||
this.buildLabel(chart, configList)
|
||||
symbolicLayer.once('inited', () => {
|
||||
mapRendered(container)
|
||||
})
|
||||
symbolicLayer.on('inited', () => {
|
||||
chart.container = container
|
||||
configCarouselTooltip(chart, symbolicLayer, symbolicLayer.sourceOption.data, scene)
|
||||
qqMapRendered(scene)
|
||||
})
|
||||
symbolicLayer.on('click', ev => {
|
||||
const data = ev.feature
|
||||
@ -181,17 +161,17 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
const quotaList = []
|
||||
chart.data.fields.forEach((item, index) => {
|
||||
Object.keys(data).forEach(key => {
|
||||
if (key.startsWith('f_') && item.dataeaseName === key) {
|
||||
if (key.startsWith('f_') && item.gisbiName === key) {
|
||||
if (index === 0) {
|
||||
dimensionList.push({
|
||||
id: item.id,
|
||||
dataeaseName: item.dataeaseName,
|
||||
gisbiName: item.gisbiName,
|
||||
value: data[key]
|
||||
})
|
||||
} else {
|
||||
quotaList.push({
|
||||
id: item.id,
|
||||
dataeaseName: item.dataeaseName,
|
||||
gisbiName: item.gisbiName,
|
||||
value: data[key]
|
||||
})
|
||||
}
|
||||
@ -239,7 +219,7 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
let colorIndex = 0
|
||||
// 存储已分配的颜色
|
||||
const colorAssignments = new Map()
|
||||
const sizeKey = extBubble.length > 0 ? extBubble[0].dataeaseName : ''
|
||||
const sizeKey = extBubble.length > 0 ? extBubble[0].gisbiName : ''
|
||||
|
||||
//条件颜色
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
@ -257,7 +237,7 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
? chart.data.tableRow.map((item, index) => {
|
||||
item['_index'] = '_index' + index
|
||||
// 颜色标识
|
||||
const identifier = item[xAxisExt[0]?.dataeaseName]
|
||||
const identifier = item[xAxisExt[0]?.gisbiName]
|
||||
// 检查该标识是否已有颜色分配,如果没有则分配
|
||||
let color = colorAssignments.get(identifier)
|
||||
if (!color) {
|
||||
@ -271,7 +251,7 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
if (conditions.length > 0) {
|
||||
for (let i = 0; i < conditions.length; i++) {
|
||||
const c = conditions[i]
|
||||
const value = item[c.field.dataeaseName]
|
||||
const value = item[c.field.gisbiName]
|
||||
for (const t of c.conditions) {
|
||||
const v = t.value
|
||||
|
||||
@ -332,12 +312,12 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].dataeaseName,
|
||||
y: xAxis[1].dataeaseName
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName
|
||||
}
|
||||
})
|
||||
.active(true)
|
||||
if (xAxisExt[0]?.dataeaseName) {
|
||||
if (xAxisExt[0]?.gisbiName) {
|
||||
if (basicStyle.mapSymbol === 'custom' && basicStyle.customIcon) {
|
||||
// 图片无法改色
|
||||
if (basicStyle.customIcon.startsWith('data')) {
|
||||
@ -452,8 +432,8 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
let showFields = tooltip.showFields || []
|
||||
if (!tooltip.showFields || tooltip.showFields.length === 0) {
|
||||
showFields = [
|
||||
...chart.xAxisExt.map(i => `${i.dataeaseName}@${i.name}`),
|
||||
...chart.xAxis.map(i => `${i.dataeaseName}@${i.name}`)
|
||||
...chart.xAxisExt.map(i => `${i.gisbiName}@${i.name}`),
|
||||
...chart.xAxis.map(i => `${i.gisbiName}@${i.name}`)
|
||||
]
|
||||
}
|
||||
// 修改背景色
|
||||
@ -584,8 +564,8 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
let showFields = label.showFields || []
|
||||
if (!label.showFields || label.showFields.length === 0) {
|
||||
showFields = [
|
||||
...chart.xAxisExt.map(i => `${i.dataeaseName}@${i.name}`),
|
||||
...chart.xAxis.map(i => `${i.dataeaseName}@${i.name}`)
|
||||
...chart.xAxisExt.map(i => `${i.gisbiName}@${i.name}`),
|
||||
...chart.xAxis.map(i => `${i.gisbiName}@${i.name}`)
|
||||
]
|
||||
}
|
||||
data.forEach(item => {
|
||||
@ -613,8 +593,8 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: xAxis[0].dataeaseName,
|
||||
y: xAxis[1].dataeaseName
|
||||
x: xAxis[0].gisbiName,
|
||||
y: xAxis[1].gisbiName
|
||||
}
|
||||
})
|
||||
.shape('textLayerContent', 'text')
|
||||
|
@ -469,8 +469,8 @@ export class CarouselManager {
|
||||
})
|
||||
}
|
||||
if (this.chart.type === 'symbolic-map') {
|
||||
const lngField = this.chart.xAxis[0].dataeaseName
|
||||
const latField = this.chart.xAxis[1].dataeaseName
|
||||
const lngField = this.chart.xAxis[0].gisbiName
|
||||
const latField = this.chart.xAxis[1].gisbiName
|
||||
const { _id } = this.scene
|
||||
?.getLayers()
|
||||
?.find(i => i.type === 'PointLayer')
|
||||
@ -554,8 +554,8 @@ export class CarouselManager {
|
||||
let showFields = tooltip.showFields || []
|
||||
if (!tooltip.showFields || tooltip.showFields.length === 0) {
|
||||
showFields = [
|
||||
...this.chart.xAxisExt.map(i => `${i.dataeaseName}@${i.name}`),
|
||||
...this.chart.xAxis.map(i => `${i.dataeaseName}@${i.name}`)
|
||||
...this.chart.xAxisExt.map(i => `${i.gisbiName}@${i.name}`),
|
||||
...this.chart.xAxis.map(i => `${i.gisbiName}@${i.name}`)
|
||||
]
|
||||
}
|
||||
const style = document.createElement('style')
|
||||
@ -571,8 +571,8 @@ export class CarouselManager {
|
||||
}
|
||||
`
|
||||
document.head.appendChild(style)
|
||||
const lngField = this.chart.xAxis[0].dataeaseName
|
||||
const latField = this.chart.xAxis[1].dataeaseName
|
||||
const lngField = this.chart.xAxis[0].gisbiName
|
||||
const latField = this.chart.xAxis[1].gisbiName
|
||||
const htmlPrefix = `<div style='font-size:${tooltip.fontSize}px;color:${tooltip.color};'>`
|
||||
const htmlSuffix = '</div>'
|
||||
const data = this.view.sourceOption.data[index]
|
||||
|
@ -1,9 +1,10 @@
|
||||
import {
|
||||
G2PlotChartView,
|
||||
G2PlotDrawOptions
|
||||
} from '@/data-visualization/chart/components/js/panel/types/impl/g2plot'
|
||||
} from '@/views/chart/components/js/panel/types/impl/g2plot'
|
||||
import type { DualAxes, DualAxesOptions } from '@antv/g2plot/esm/plots/dual-axes'
|
||||
import {
|
||||
configRoundAngle,
|
||||
configPlotTooltipEvent,
|
||||
getAnalyse,
|
||||
getLabel,
|
||||
@ -14,7 +15,7 @@ import {
|
||||
setGradientColor,
|
||||
TOOLTIP_TPL
|
||||
} from '../../common/common_antv'
|
||||
import { flow, hexColorToRGBA, parseJson } from '@/data-visualization/chart/components/js/util'
|
||||
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
|
||||
import {
|
||||
cloneDeep,
|
||||
isEmpty,
|
||||
@ -25,7 +26,7 @@ import {
|
||||
defaultsDeep,
|
||||
defaults
|
||||
} from 'lodash-es'
|
||||
import { valueFormatter } from '@/data-visualization/chart/components/js/formatter'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import {
|
||||
CHART_MIX_AXIS_TYPE,
|
||||
CHART_MIX_DEFAULT_BASIC_STYLE,
|
||||
@ -34,14 +35,15 @@ import {
|
||||
MixChartBasicStyle
|
||||
} from './chart-mix-common'
|
||||
import type { Datum } from '@antv/g2plot/esm/types/common'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import {
|
||||
DEFAULT_BASIC_STYLE,
|
||||
DEFAULT_LABEL,
|
||||
DEFAULT_LEGEND_STYLE
|
||||
} from '@/data-visualization/chart/components/editor/util/chart'
|
||||
} from '@/views/chart/components/editor/util/chart'
|
||||
import type { Options } from '@antv/g2plot/esm'
|
||||
import { Group } from '@antv/g-canvas'
|
||||
import { extremumEvt } from '@/views/chart/components/js/extremumUitl'
|
||||
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA = []
|
||||
@ -56,7 +58,8 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
'label-selector': ['vPosition', 'seriesLabelFormatter'],
|
||||
'tooltip-selector': [
|
||||
...CHART_MIX_EDITOR_PROPERTY_INNER['tooltip-selector'],
|
||||
'seriesTooltipFormatter'
|
||||
'seriesTooltipFormatter',
|
||||
'carousel'
|
||||
]
|
||||
}
|
||||
axis: AxisType[] = [...CHART_MIX_AXIS_TYPE, 'xAxisExtRight', 'yAxisExt']
|
||||
@ -94,6 +97,7 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<DualAxes>): Promise<DualAxes> {
|
||||
const { chart, action, container } = drawOptions
|
||||
chart.container = container
|
||||
if (!chart.data?.left?.data?.length && !chart.data?.right?.data?.length) {
|
||||
return
|
||||
}
|
||||
@ -117,7 +121,6 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
valueExt: d.value
|
||||
}
|
||||
})
|
||||
|
||||
// options
|
||||
const initOptions: DualAxesOptions = {
|
||||
data: [data1, data2],
|
||||
@ -127,6 +130,7 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
geometryOptions: [
|
||||
{
|
||||
geometry: data1Type,
|
||||
marginRatio: 0,
|
||||
color: [],
|
||||
isGroup: isGroup,
|
||||
isStack: isStack,
|
||||
@ -174,6 +178,7 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
|
||||
newChart.on('point:click', action)
|
||||
newChart.on('interval:click', action)
|
||||
extremumEvt(newChart, chart, options, container)
|
||||
configPlotTooltipEvent(chart, newChart)
|
||||
return newChart
|
||||
}
|
||||
@ -292,18 +297,9 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
tempOption.geometryOptions[1].smooth = smooth
|
||||
tempOption.geometryOptions[1].point = point
|
||||
tempOption.geometryOptions[1].lineStyle = lineStyle
|
||||
|
||||
if (s.radiusColumnBar === 'roundAngle') {
|
||||
const columnStyle = {
|
||||
radius: [
|
||||
s.columnBarRightAngleRadius,
|
||||
s.columnBarRightAngleRadius,
|
||||
s.columnBarRightAngleRadius,
|
||||
s.columnBarRightAngleRadius
|
||||
]
|
||||
}
|
||||
tempOption.geometryOptions[0].columnStyle = columnStyle
|
||||
tempOption.geometryOptions[1].columnStyle = columnStyle
|
||||
tempOption.geometryOptions[0] = {
|
||||
...tempOption.geometryOptions[0],
|
||||
...configRoundAngle(chart, 'columnStyle')
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,7 +324,7 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
}
|
||||
|
||||
setupDefaultOptions(chart: ChartObj): ChartObj {
|
||||
const { customAttr, senior } = chart
|
||||
const { senior } = chart
|
||||
if (
|
||||
senior.functionCfg.emptyDataStrategy == undefined ||
|
||||
senior.functionCfg.emptyDataStrategy === 'ignoreData'
|
||||
@ -670,7 +666,8 @@ export class GroupColumnLineMix extends ColumnLineMix {
|
||||
'label-selector': ['vPosition', 'seriesLabelFormatter'],
|
||||
'tooltip-selector': [
|
||||
...CHART_MIX_EDITOR_PROPERTY_INNER['tooltip-selector'],
|
||||
'seriesTooltipFormatter'
|
||||
'seriesTooltipFormatter',
|
||||
'carousel'
|
||||
]
|
||||
}
|
||||
axisConfig = {
|
||||
@ -782,7 +779,8 @@ export class StackColumnLineMix extends ColumnLineMix {
|
||||
'label-selector': ['vPosition', 'seriesLabelFormatter'],
|
||||
'tooltip-selector': [
|
||||
...CHART_MIX_EDITOR_PROPERTY_INNER['tooltip-selector'],
|
||||
'seriesTooltipFormatter'
|
||||
'seriesTooltipFormatter',
|
||||
'carousel'
|
||||
]
|
||||
}
|
||||
axisConfig = {
|
||||
@ -895,7 +893,8 @@ export class DualLineMix extends ColumnLineMix {
|
||||
'label-selector': ['seriesLabelFormatter'],
|
||||
'tooltip-selector': [
|
||||
...CHART_MIX_EDITOR_PROPERTY_INNER['tooltip-selector'],
|
||||
'seriesTooltipFormatter'
|
||||
'seriesTooltipFormatter',
|
||||
'carousel'
|
||||
]
|
||||
}
|
||||
axisConfig = {
|
||||
|
@ -69,7 +69,7 @@ export class CirclePacking extends G2PlotChartView<CirclePackingOptions, G2Circl
|
||||
if (chart?.data?.data?.length) {
|
||||
// data
|
||||
const data = chart.data.data
|
||||
const { xAxis, yAxis, drillFields } = chart
|
||||
const { yAxis } = chart
|
||||
const ySort = yAxis[0]?.sort ?? 'none'
|
||||
const sort = {
|
||||
sort: (a, b) =>
|
||||
@ -123,7 +123,7 @@ export class CirclePacking extends G2PlotChartView<CirclePackingOptions, G2Circl
|
||||
'@antv/g2plot/esm/plots/circle-packing'
|
||||
)
|
||||
const newChart = new G2CirclePacking(container, options)
|
||||
newChart.on('point:click', param => {
|
||||
newChart.on('element:click', param => {
|
||||
const pointData = param?.data?.data
|
||||
if (pointData?.name === t('commons.all')) {
|
||||
return
|
||||
@ -157,7 +157,7 @@ export class CirclePacking extends G2PlotChartView<CirclePackingOptions, G2Circl
|
||||
...options,
|
||||
hierarchyConfig: {
|
||||
...options.hierarchyConfig,
|
||||
padding: typeof padding === 'number' && !isNaN(padding) ? padding / 100 : 0
|
||||
padding: padding / 100 ?? 0
|
||||
},
|
||||
pointStyle
|
||||
}
|
||||
@ -177,7 +177,7 @@ export class CirclePacking extends G2PlotChartView<CirclePackingOptions, G2Circl
|
||||
textAlign: 'center',
|
||||
offsetY: 5,
|
||||
layout: labelAttr.fullDisplay ? [{ type: 'limit-in-plot' }] : tmpOptions.label.layout,
|
||||
formatter: (d: Datum, _point) => {
|
||||
formatter: (d: Datum) => {
|
||||
return d.children.length === 0 ? d.name : ''
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
// options
|
||||
const initOptions: GaugeOptions = {
|
||||
percent: 0,
|
||||
appendPadding: getPadding(chart),
|
||||
appendPadding: [0, 10, 15, 10],
|
||||
axis: {
|
||||
tickInterval: 0.2,
|
||||
label: {
|
||||
@ -109,8 +109,10 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
}
|
||||
})
|
||||
})
|
||||
const hasNoneData = chart.data?.series.some(s => !s.data?.[0])
|
||||
this.configEmptyDataStyle(newChart, hasNoneData ? [] : [1], container)
|
||||
const hasNoneData = chart.data?.series.some(
|
||||
s => s.data?.[0] === undefined || s.data?.[0] === null
|
||||
)
|
||||
this.configEmptyDataStyle(hasNoneData ? [] : [1], container, newChart)
|
||||
if (hasNoneData) {
|
||||
return
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ export class IndicatorChartView extends AbstractChartView {
|
||||
'indicator-value-selector',
|
||||
'indicator-name-selector',
|
||||
'threshold',
|
||||
'function-cfg'
|
||||
'function-cfg',
|
||||
'linkage'
|
||||
]
|
||||
propertyInner: EditorPropertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
|
@ -13,7 +13,8 @@ import {
|
||||
configPlotTooltipEvent,
|
||||
configYaxisTitleLengthLimit,
|
||||
getTooltipContainer,
|
||||
TOOLTIP_TPL
|
||||
TOOLTIP_TPL,
|
||||
getPadding
|
||||
} from '../../common/common_antv'
|
||||
import { DEFAULT_LEGEND_STYLE } from '@/data-visualization/chart/components/editor/util/chart'
|
||||
|
||||
@ -209,7 +210,7 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
data: data,
|
||||
xField: 'yAxis',
|
||||
yField: 'yAxisExt',
|
||||
appendPadding: 30,
|
||||
appendPadding: getPadding(chart),
|
||||
pointStyle: {
|
||||
fillOpacity: 0.8,
|
||||
stroke: '#bbb'
|
||||
@ -476,7 +477,6 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
this.configLegend,
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configAnalyse,
|
||||
this.configSlider,
|
||||
this.configBasicStyle
|
||||
)(chart, options, {}, this)
|
||||
|
@ -1,20 +1,20 @@
|
||||
import {
|
||||
G2PlotChartView,
|
||||
G2PlotDrawOptions
|
||||
} from '@/data-visualization/chart/components/js/panel/types/impl/g2plot'
|
||||
} from '@/views/chart/components/js/panel/types/impl/g2plot'
|
||||
import type { Sankey, SankeyOptions } from '@antv/g2plot/esm/plots/sankey'
|
||||
import { getPadding, setGradientColor } from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { cloneDeep, get } from 'lodash-es'
|
||||
import { flow, hexColorToRGBA, parseJson } from '@/data-visualization/chart/components/js/util'
|
||||
import { valueFormatter } from '@/data-visualization/chart/components/js/formatter'
|
||||
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
|
||||
import { Datum } from '@antv/g2plot/esm/types/common'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import {
|
||||
SANKEY_AXIS_TYPE,
|
||||
SANKEY_EDITOR_PROPERTY,
|
||||
SANKEY_EDITOR_PROPERTY_INNER
|
||||
} from '@/data-visualization/chart/components/js/panel/charts/others/sankey-common'
|
||||
} from '@/views/chart/components/js/panel/charts/others/sankey-common'
|
||||
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA = []
|
||||
|
@ -14,6 +14,8 @@ import {
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { defaults, isEmpty } from 'lodash-es'
|
||||
import { DEFAULT_LEGEND_STYLE } from '@/data-visualization/chart/components/editor/util/chart'
|
||||
import { type Datum } from '@antv/g2plot/esm'
|
||||
import { Group } from '@antv/g-canvas'
|
||||
|
||||
const { t } = useI18n()
|
||||
/**
|
||||
@ -144,6 +146,17 @@ export class Scatter extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
const { Scatter: G2Scatter } = await import('@antv/g2plot/esm/plots/scatter')
|
||||
const newChart = new G2Scatter(container, options)
|
||||
newChart.on('point:click', action)
|
||||
if (options.label) {
|
||||
newChart.on('label:click', e => {
|
||||
action({
|
||||
x: e.x,
|
||||
y: e.y,
|
||||
data: {
|
||||
data: e.target.attrs.data
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
configPlotTooltipEvent(chart, newChart)
|
||||
return newChart
|
||||
}
|
||||
@ -277,6 +290,41 @@ export class Scatter extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
return optionTmp
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: ScatterOptions): ScatterOptions {
|
||||
const tmpOption = super.configLabel(chart, options)
|
||||
if (!tmpOption.label) {
|
||||
return options
|
||||
}
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
tmpOption.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...tmpOption.label,
|
||||
formatter: function (data: Datum) {
|
||||
const value = valueFormatter(data.value, labelAttr.labelFormatter)
|
||||
const group = new Group({})
|
||||
group.addShape({
|
||||
type: 'text',
|
||||
attrs: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
data,
|
||||
text: value,
|
||||
textAlign: 'start',
|
||||
textBaseline: 'top',
|
||||
fontSize: labelAttr.fontSize,
|
||||
fontFamily: chart.fontFamily,
|
||||
fill: labelAttr.color
|
||||
}
|
||||
})
|
||||
return group
|
||||
}
|
||||
}
|
||||
return {
|
||||
...tmpOption,
|
||||
label
|
||||
}
|
||||
}
|
||||
|
||||
protected setupOptions(chart: Chart, options: ScatterOptions) {
|
||||
return flow(
|
||||
this.configTheme,
|
||||
@ -286,7 +334,6 @@ export class Scatter extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
this.configLegend,
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configAnalyse,
|
||||
this.configSlider,
|
||||
this.configBasicStyle
|
||||
)(chart, options)
|
||||
|
@ -1,19 +1,19 @@
|
||||
import {
|
||||
G2PlotChartView,
|
||||
G2PlotDrawOptions
|
||||
} from '@/data-visualization/chart/components/js/panel/types/impl/g2plot'
|
||||
} from '@/views/chart/components/js/panel/types/impl/g2plot'
|
||||
import type { WordCloud as G2WordCloud, WordCloudOptions } from '@antv/g2plot/esm/plots/word-cloud'
|
||||
import {
|
||||
filterChartDataByRange,
|
||||
flow,
|
||||
getMaxAndMinValueByData,
|
||||
parseJson
|
||||
} from '@/data-visualization/chart/components/js/util'
|
||||
import { getPadding } from '@/data-visualization/chart/components/js/panel/common/common_antv'
|
||||
import { valueFormatter } from '@/data-visualization/chart/components/js/formatter'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
} from '@/views/chart/components/js/util'
|
||||
import { getPadding } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { DEFAULT_MISC } from '@/data-visualization/chart/components/editor/util/chart'
|
||||
import { DEFAULT_MISC } from '@/views/chart/components/editor/util/chart'
|
||||
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA = []
|
||||
|
@ -27,19 +27,23 @@ import type { Datum } from '@antv/g2plot/esm/types/common'
|
||||
import { add } from 'mathjs'
|
||||
import isEmpty from 'lodash-es/isEmpty'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA = []
|
||||
export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
||||
axis: AxisType[] = PIE_AXIS_TYPE
|
||||
properties = PIE_EDITOR_PROPERTY
|
||||
propertyInner: EditorPropertyInner = {
|
||||
...PIE_EDITOR_PROPERTY_INNER,
|
||||
'basic-style-selector': ['colors', 'alpha', 'radius', 'topN', 'seriesColor']
|
||||
'basic-style-selector': ['colors', 'alpha', 'radius', 'topN', 'seriesColor'],
|
||||
'tooltip-selector': [...PIE_EDITOR_PROPERTY_INNER['tooltip-selector'], 'carousel']
|
||||
}
|
||||
axisConfig = PIE_AXIS_CONFIG
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Pie>): Promise<G2Pie> {
|
||||
const { chart, container, action } = drawOptions
|
||||
this.configEmptyDataStyle(chart.data?.data, container, null, t('chart.no_data_or_not_positive'))
|
||||
chart.container = container
|
||||
if (!chart.data?.data?.length) {
|
||||
return
|
||||
}
|
||||
@ -115,12 +119,22 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
||||
field: {
|
||||
type: 'cat'
|
||||
}
|
||||
},
|
||||
state: {
|
||||
active: {
|
||||
style: {
|
||||
lineWidth: 2,
|
||||
fillOpacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const options = this.setupOptions(chart, initOptions)
|
||||
const { Pie: G2Pie } = await import('@antv/g2plot/esm/plots/pie')
|
||||
const newChart = new G2Pie(container, options)
|
||||
newChart.on('interval:click', action)
|
||||
newChart.on('interval:click', d => {
|
||||
d.data?.data?.field !== customAttr.basicStyle.topNLabel && action(d)
|
||||
})
|
||||
configPlotTooltipEvent(chart, newChart)
|
||||
return newChart
|
||||
}
|
||||
@ -244,6 +258,7 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
||||
},
|
||||
container: getTooltipContainer(`tooltip-${chart.id}`),
|
||||
itemTpl: TOOLTIP_TPL,
|
||||
shared: true,
|
||||
enterable: true
|
||||
}
|
||||
return {
|
||||
@ -338,7 +353,8 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
||||
export class PieDonut extends Pie {
|
||||
propertyInner: EditorPropertyInner = {
|
||||
...PIE_EDITOR_PROPERTY_INNER,
|
||||
'basic-style-selector': ['colors', 'alpha', 'radius', 'innerRadius', 'topN', 'seriesColor']
|
||||
'basic-style-selector': ['colors', 'alpha', 'radius', 'innerRadius', 'topN', 'seriesColor'],
|
||||
'tooltip-selector': [...PIE_EDITOR_PROPERTY_INNER['tooltip-selector'], 'carousel']
|
||||
}
|
||||
protected configBasicStyle(chart: Chart, options: PieOptions): PieOptions {
|
||||
const tmp = super.configBasicStyle(chart, options)
|
||||
|
@ -40,6 +40,7 @@ export class Rose extends G2PlotChartView<RoseOptions, G2Rose> {
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Rose>): Promise<G2Rose> {
|
||||
const { chart, container, action } = drawOptions
|
||||
this.configEmptyDataStyle(chart.data?.data, container, null, t('chart.no_data_or_not_positive'))
|
||||
if (!chart?.data?.data?.length) {
|
||||
return
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ export const TABLE_EDITOR_PROPERTY: EditorProperty[] = [
|
||||
'table-cell-selector',
|
||||
'title-selector',
|
||||
'tooltip-selector',
|
||||
'summary-selector',
|
||||
'function-cfg',
|
||||
'threshold',
|
||||
'scroll-cfg',
|
||||
|
402
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/t-heatmap.js
vendored
Normal file
402
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/t-heatmap.js
vendored
Normal file
@ -0,0 +1,402 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.TableHeatmap = void 0;
|
||||
var g2plot_1 = require("@/views/chart/components/js/panel/types/impl/g2plot");
|
||||
var util_1 = require("@/views/chart/components/js/util");
|
||||
var useI18n_1 = require("@/hooks/web/useI18n");
|
||||
var utils_1 = require("@/utils/utils");
|
||||
var lodash_es_1 = require("lodash-es");
|
||||
var common_antv_1 = require("@/views/chart/components/js/panel/common/common_antv");
|
||||
var formatter_1 = require("@/views/chart/components/js/formatter");
|
||||
var t = useI18n_1.useI18n().t;
|
||||
var DEFAULT_DATA = [];
|
||||
/**
|
||||
* 热力图
|
||||
*/
|
||||
var TableHeatmap = /** @class */ (function (_super) {
|
||||
__extends(TableHeatmap, _super);
|
||||
function TableHeatmap() {
|
||||
var _this = _super.call(this, 't-heatmap', DEFAULT_DATA) || this;
|
||||
_this.properties = [
|
||||
'basic-style-selector',
|
||||
'background-overall-component',
|
||||
'label-selector',
|
||||
'legend-selector',
|
||||
'x-axis-selector',
|
||||
'y-axis-selector',
|
||||
'title-selector',
|
||||
'tooltip-selector',
|
||||
'jump-set',
|
||||
'linkage',
|
||||
'border-style'
|
||||
];
|
||||
_this.propertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
'basic-style-selector': ['colors'],
|
||||
'label-selector': ['fontSize', 'color'],
|
||||
'x-axis-selector': ['name', 'color', 'fontSize', 'position', 'axisLabel', 'axisLine'],
|
||||
'y-axis-selector': [
|
||||
'name',
|
||||
'color',
|
||||
'fontSize',
|
||||
'position',
|
||||
'axisLabel',
|
||||
'axisLine',
|
||||
'showLengthLimit'
|
||||
],
|
||||
'title-selector': [
|
||||
'title',
|
||||
'fontSize',
|
||||
'color',
|
||||
'hPosition',
|
||||
'isItalic',
|
||||
'isBolder',
|
||||
'remarkShow',
|
||||
'fontFamily',
|
||||
'letterSpace',
|
||||
'fontShadow'
|
||||
],
|
||||
'legend-selector': ['orient', 'color', 'fontSize', 'hPosition', 'vPosition'],
|
||||
'tooltip-selector': ['show', 'color', 'fontSize', 'backgroundColor'],
|
||||
'border-style': ['all']
|
||||
};
|
||||
_this.axis = ['xAxis', 'xAxisExt', 'extColor', 'filter'];
|
||||
_this.axisConfig = {
|
||||
xAxis: {
|
||||
name: t('chart.x_axis') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 1
|
||||
},
|
||||
xAxisExt: {
|
||||
name: t('chart.y_axis') + " / " + t('chart.dimension'),
|
||||
type: 'd',
|
||||
limit: 1
|
||||
},
|
||||
extColor: {
|
||||
name: t('chart.color') + " / " + t('chart.dimension_or_quota'),
|
||||
limit: 1
|
||||
}
|
||||
};
|
||||
_this.getDefaultLength = function (chart, l) {
|
||||
var containerDom = document.getElementById(chart.container);
|
||||
var containerHeight = (containerDom === null || containerDom === void 0 ? void 0 : containerDom.clientHeight) || 100;
|
||||
var containerWidth = (containerDom === null || containerDom === void 0 ? void 0 : containerDom.clientWidth) || 100;
|
||||
var defaultLength = containerHeight - containerHeight * 0.5;
|
||||
if (l.orient !== 'vertical') {
|
||||
defaultLength = containerWidth - containerWidth * 0.5;
|
||||
}
|
||||
return defaultLength;
|
||||
};
|
||||
_this.sortData = function (fieldObj, data) {
|
||||
var deType = fieldObj.deType, sort = fieldObj.sort, customSort = fieldObj.customSort;
|
||||
if (sort === 'desc') {
|
||||
if (deType === 0) {
|
||||
return data.sort().reverse();
|
||||
}
|
||||
else {
|
||||
return data.sort(function (a, b) { return b - a; });
|
||||
}
|
||||
}
|
||||
else if (sort === 'asc') {
|
||||
if (deType === 0) {
|
||||
return data.sort();
|
||||
}
|
||||
else {
|
||||
return data.sort(function (a, b) { return a - b; });
|
||||
}
|
||||
}
|
||||
// 如果没有指定排序方式,直接返回原始数据或 customSort
|
||||
return customSort && customSort.length > 0 ? customSort : data;
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
TableHeatmap.prototype.drawChart = function (drawOptions) {
|
||||
return __awaiter(this, void 0, Promise, function () {
|
||||
var chart, container, action, xAxis, xAxisExt, extColor, xField, xFieldExt, extColorField, tmpData, data, initOptions, options, Heatmap, newChart;
|
||||
var _a;
|
||||
var _this = this;
|
||||
return __generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0:
|
||||
chart = drawOptions.chart, container = drawOptions.container, action = drawOptions.action;
|
||||
xAxis = utils_1.deepCopy(chart.xAxis);
|
||||
xAxisExt = utils_1.deepCopy(chart.xAxisExt);
|
||||
extColor = utils_1.deepCopy(chart.extColor);
|
||||
if (!(xAxis === null || xAxis === void 0 ? void 0 : xAxis.length) || !(xAxisExt === null || xAxisExt === void 0 ? void 0 : xAxisExt.length) || !(extColor === null || extColor === void 0 ? void 0 : extColor.length)) {
|
||||
return [2 /*return*/];
|
||||
}
|
||||
xField = xAxis[0].gisbiName;
|
||||
xFieldExt = xAxisExt[0].gisbiName;
|
||||
extColorField = extColor[0].gisbiName;
|
||||
tmpData = lodash_es_1.cloneDeep(chart.data.tableRow);
|
||||
data = tmpData.filter(function (cell) { return cell[xField] && cell[xFieldExt] && cell[extColorField]; });
|
||||
data.forEach(function (i) {
|
||||
Object.keys(i).forEach(function (key) {
|
||||
if (key === '*') {
|
||||
i['@'] = i[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
initOptions = {
|
||||
data: data,
|
||||
xField: xField,
|
||||
yField: xFieldExt,
|
||||
colorField: extColorField === '*' ? '@' : extColorField,
|
||||
appendPadding: common_antv_1.getPadding(chart),
|
||||
meta: (_a = {},
|
||||
_a[xField] = {
|
||||
type: 'cat',
|
||||
values: this.sortData(xAxis[0], __spreadArrays(new Set(data.map(function (i) { return i[[xField]]; }))))
|
||||
},
|
||||
_a[xFieldExt] = {
|
||||
type: 'cat',
|
||||
values: this.sortData(xAxisExt[0], __spreadArrays(new Set(data.map(function (i) { return i[[xFieldExt]]; })))).reverse()
|
||||
},
|
||||
_a),
|
||||
legend: {
|
||||
layout: 'vertical',
|
||||
position: 'right',
|
||||
slidable: true,
|
||||
label: {
|
||||
align: 'left',
|
||||
spacing: 10
|
||||
}
|
||||
}
|
||||
};
|
||||
chart.container = container;
|
||||
options = this.setupOptions(chart, initOptions);
|
||||
return [4 /*yield*/, Promise.resolve().then(function () { return require('@antv/g2plot/esm/plots/heatmap'); })];
|
||||
case 1:
|
||||
Heatmap = (_b.sent()).Heatmap;
|
||||
newChart = new Heatmap(container, options);
|
||||
newChart.on('plot:click', function (param) {
|
||||
var _a;
|
||||
if (!((_a = param.data) === null || _a === void 0 ? void 0 : _a.data)) {
|
||||
return;
|
||||
}
|
||||
var pointData = param.data.data;
|
||||
var dimensionList = [];
|
||||
chart.data.fields.forEach(function (item) {
|
||||
Object.keys(pointData).forEach(function (key) {
|
||||
if (key.startsWith('f_') && item.gisbiName === key) {
|
||||
dimensionList.push({
|
||||
id: item.id,
|
||||
gisbiName: item.gisbiName,
|
||||
value: pointData[key]
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
action({
|
||||
x: param.data.x,
|
||||
y: param.data.y,
|
||||
data: {
|
||||
data: __assign(__assign({}, param.data.data), { value: dimensionList[1].value, name: dimensionList[1].id, dimensionList: dimensionList, quotaList: [dimensionList[1]] })
|
||||
}
|
||||
});
|
||||
});
|
||||
newChart.on('afterrender', function (ev) {
|
||||
var _a;
|
||||
var l = JSON.parse(JSON.stringify(util_1.parseJson(chart.customStyle).legend));
|
||||
if (l.show) {
|
||||
var rail = (_a = ev.view.getController('legend').option[extColor[0].gisbiName]) === null || _a === void 0 ? void 0 : _a['rail'];
|
||||
if (rail) {
|
||||
rail.defaultLength = _this.getDefaultLength(chart, l);
|
||||
}
|
||||
}
|
||||
});
|
||||
common_antv_1.configAxisLabelLengthLimit(chart, newChart);
|
||||
return [2 /*return*/, newChart];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
TableHeatmap.prototype.configTheme = function (chart, options) {
|
||||
var tmp = _super.prototype.configTheme.call(this, chart, options);
|
||||
tmp.theme.innerLabels.offset = 0;
|
||||
return tmp;
|
||||
};
|
||||
TableHeatmap.prototype.configBasicStyle = function (chart, options) {
|
||||
var _a;
|
||||
var basicStyle = util_1.parseJson(chart.customAttr).basicStyle;
|
||||
var color = (_a = basicStyle.colors) === null || _a === void 0 ? void 0 : _a.map(function (ele) {
|
||||
return util_1.hexColorToRGBA(ele, basicStyle.alpha);
|
||||
});
|
||||
return __assign(__assign({}, options), { color: color });
|
||||
};
|
||||
TableHeatmap.prototype.configTooltip = function (chart, options) {
|
||||
var tooltip;
|
||||
var customAttr;
|
||||
if (chart.customAttr) {
|
||||
customAttr = util_1.parseJson(chart.customAttr);
|
||||
// tooltip
|
||||
if (customAttr.tooltip) {
|
||||
var extColor = utils_1.deepCopy(chart.extColor);
|
||||
var xAxisExt = utils_1.deepCopy(chart.xAxisExt);
|
||||
var tooltipFiledList_1 = [xAxisExt, extColor];
|
||||
var t_1 = JSON.parse(JSON.stringify(customAttr.tooltip));
|
||||
if (t_1.show) {
|
||||
tooltip = {
|
||||
showTitle: true,
|
||||
customItems: function (originalItems) {
|
||||
var items = [];
|
||||
var createItem = function (fieldObj, items, originalItems) {
|
||||
var name = (fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.chartShowName) ? fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.chartShowName : fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.name;
|
||||
var value = originalItems[0].data[fieldObj.gisbiName];
|
||||
if (!isNaN(Number(value))) {
|
||||
value = formatter_1.valueFormatter(value, fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.formatterCfg);
|
||||
}
|
||||
items.push(__assign(__assign({}, originalItems[0]), { name: name, value: value }));
|
||||
};
|
||||
tooltipFiledList_1.forEach(function (field) {
|
||||
createItem(field[0], items, originalItems);
|
||||
});
|
||||
return items;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
tooltip = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __assign(__assign({}, options), { tooltip: tooltip });
|
||||
};
|
||||
TableHeatmap.prototype.configXAxis = function (chart, options) {
|
||||
var xAxis = common_antv_1.getXAxis(chart);
|
||||
return __assign(__assign({}, options), { xAxis: xAxis ? __assign(__assign({}, xAxis), { grid: null }) : false });
|
||||
};
|
||||
TableHeatmap.prototype.configYAxis = function (chart, options) {
|
||||
var yAxis = common_antv_1.getYAxis(chart);
|
||||
return __assign(__assign({}, options), { yAxis: yAxis ? __assign(__assign({}, yAxis), { grid: null }) : false });
|
||||
};
|
||||
TableHeatmap.prototype.configLegend = function (chart, options) {
|
||||
var tmpOptions = _super.prototype.configLegend.call(this, chart, options);
|
||||
if (tmpOptions.legend) {
|
||||
var l = JSON.parse(JSON.stringify(util_1.parseJson(chart.customStyle).legend));
|
||||
tmpOptions.legend.slidable = true;
|
||||
tmpOptions.legend.minHeight = 10;
|
||||
tmpOptions.legend.minWidth = 10;
|
||||
tmpOptions.legend.maxHeight = 600;
|
||||
tmpOptions.legend.maxWidth = 600;
|
||||
var containerDom = document.getElementById(chart.container);
|
||||
var containerHeight = (containerDom === null || containerDom === void 0 ? void 0 : containerDom.clientHeight) || 100;
|
||||
var containerWidth = (containerDom === null || containerDom === void 0 ? void 0 : containerDom.clientWidth) || 100;
|
||||
var defaultLength = containerHeight - containerHeight * 0.5;
|
||||
if (l.orient === 'vertical') {
|
||||
tmpOptions.legend.offsetY = -5;
|
||||
}
|
||||
else {
|
||||
defaultLength = containerWidth - containerWidth * 0.5;
|
||||
}
|
||||
tmpOptions.legend.rail = { defaultLength: defaultLength };
|
||||
tmpOptions.legend.label = {
|
||||
spacing: 10,
|
||||
style: {
|
||||
fill: l.color,
|
||||
fontSize: l.fontSize
|
||||
}
|
||||
};
|
||||
}
|
||||
return tmpOptions;
|
||||
};
|
||||
TableHeatmap.prototype.setupDefaultOptions = function (chart) {
|
||||
chart.customStyle.legend.orient = 'vertical';
|
||||
chart.customStyle.legend.vPosition = 'center';
|
||||
chart.customStyle.legend.hPosition = 'right';
|
||||
chart.customStyle.legend['rail'] = { defaultLength: 100 };
|
||||
return chart;
|
||||
};
|
||||
TableHeatmap.prototype.configLabel = function (chart, options) {
|
||||
var tmpOptions = _super.prototype.configLabel.call(this, chart, options);
|
||||
if (tmpOptions.label) {
|
||||
var extColor_1 = utils_1.deepCopy(chart.extColor);
|
||||
var layout = [];
|
||||
if (!tmpOptions.label.fullDisplay) {
|
||||
layout.push.apply(layout, tmpOptions.label.layout);
|
||||
}
|
||||
var label = __assign(__assign({}, tmpOptions.label), { position: 'middle', layout: layout, formatter: function (data) {
|
||||
var _a, _b;
|
||||
var value = data[(_a = extColor_1[0]) === null || _a === void 0 ? void 0 : _a.gisbiName];
|
||||
if (!isNaN(Number(value))) {
|
||||
return formatter_1.valueFormatter(value, (_b = extColor_1[0]) === null || _b === void 0 ? void 0 : _b.formatterCfg);
|
||||
}
|
||||
return value;
|
||||
} });
|
||||
return __assign(__assign({}, tmpOptions), { label: label });
|
||||
}
|
||||
return tmpOptions;
|
||||
};
|
||||
TableHeatmap.prototype.setupOptions = function (chart, options) {
|
||||
return util_1.flow(this.configTheme, this.configXAxis, this.configYAxis, this.configBasicStyle, this.configLegend, this.configTooltip, this.configLabel)(chart, options);
|
||||
};
|
||||
return TableHeatmap;
|
||||
}(g2plot_1.G2PlotChartView));
|
||||
exports.TableHeatmap = TableHeatmap;
|
564
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/table-info.js
vendored
Normal file
564
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/table-info.js
vendored
Normal file
@ -0,0 +1,564 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.TableInfo = void 0;
|
||||
var s2_1 = require("@antv/s2");
|
||||
var formatter_1 = require("../../../formatter");
|
||||
var util_1 = require("../../../util");
|
||||
var s2_2 = require("../../types/impl/s2");
|
||||
var common_1 = require("./common");
|
||||
var useI18n_1 = require("@/hooks/web/useI18n");
|
||||
var lodash_es_1 = require("lodash-es");
|
||||
var common_table_1 = require("@/views/chart/components/js/panel/common/common_table");
|
||||
var t = useI18n_1.useI18n().t;
|
||||
var ImageCell = /** @class */ (function (_super) {
|
||||
__extends(ImageCell, _super);
|
||||
function ImageCell() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
ImageCell.prototype.drawTextShape = function () {
|
||||
common_table_1.drawImage.apply(this);
|
||||
};
|
||||
return ImageCell;
|
||||
}(common_table_1.CustomDataCell));
|
||||
/**
|
||||
* 明细表
|
||||
*/
|
||||
var TableInfo = /** @class */ (function (_super) {
|
||||
__extends(TableInfo, _super);
|
||||
function TableInfo() {
|
||||
var _this = _super.call(this, 'table-info', []) || this;
|
||||
_this.properties = common_1.TABLE_EDITOR_PROPERTY;
|
||||
_this.propertyInner = __assign(__assign({}, common_1.TABLE_EDITOR_PROPERTY_INNER), { 'table-header-selector': __spreadArrays(common_1.TABLE_EDITOR_PROPERTY_INNER['table-header-selector'], [
|
||||
'tableHeaderSort',
|
||||
'showTableHeader',
|
||||
'headerGroup'
|
||||
]), 'basic-style-selector': [
|
||||
'tableColumnMode',
|
||||
'tableBorderColor',
|
||||
'tableScrollBarColor',
|
||||
'alpha',
|
||||
'tablePageMode',
|
||||
'showHoverStyle',
|
||||
'autoWrap'
|
||||
], 'table-cell-selector': __spreadArrays(common_1.TABLE_EDITOR_PROPERTY_INNER['table-cell-selector'], [
|
||||
'tableFreeze',
|
||||
'tableColumnFreezeHead',
|
||||
'tableRowFreezeHead',
|
||||
'mergeCells'
|
||||
]), 'summary-selector': ['showSummary', 'summaryLabel'] });
|
||||
_this.axis = ['xAxis', 'filter', 'drill'];
|
||||
_this.axisConfig = {
|
||||
xAxis: {
|
||||
name: t('chart.drag_block_table_data_column') + " / " + t('chart.dimension_or_quota')
|
||||
}
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
TableInfo.prototype.drawChart = function (drawOption) {
|
||||
var _this = this;
|
||||
var _a, _b, _c, _d, _e;
|
||||
var container = drawOption.container, chart = drawOption.chart, pageInfo = drawOption.pageInfo, action = drawOption.action, resizeAction = drawOption.resizeAction;
|
||||
var containerDom = document.getElementById(container);
|
||||
// fields
|
||||
var fields = (_b = (_a = chart.data) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [];
|
||||
var columns = [];
|
||||
var meta = [];
|
||||
var axisMap = chart.xAxis.reduce(function (pre, cur) {
|
||||
pre[cur.gisbiName] = cur;
|
||||
return pre;
|
||||
}, {});
|
||||
var drillFieldMap = {};
|
||||
if (chart.drill) {
|
||||
// 下钻过滤字段
|
||||
var filterFields_1 = chart.drillFilters.map(function (i) { return i.fieldId; });
|
||||
// 下钻入口的字段下标
|
||||
var drillFieldId_1 = chart.drillFields[0].id;
|
||||
var drillFieldIndex = chart.xAxis.findIndex(function (ele) { return ele.id === drillFieldId_1; });
|
||||
// 当前下钻字段
|
||||
var curDrillFieldId_1 = chart.drillFields[filterFields_1.length].id;
|
||||
var curDrillField = fields.find(function (ele) { return ele.id === curDrillFieldId_1; });
|
||||
filterFields_1.push(curDrillFieldId_1);
|
||||
// 移除下钻字段,把当前下钻字段插入到下钻入口位置
|
||||
fields = fields.filter(function (ele) {
|
||||
return !filterFields_1.includes(ele.id);
|
||||
});
|
||||
drillFieldMap[curDrillField.gisbiName] = chart.drillFields[0].gisbiName;
|
||||
fields.splice(drillFieldIndex, 0, curDrillField);
|
||||
}
|
||||
fields.forEach(function (ele) {
|
||||
var _a;
|
||||
var f = axisMap[ele.gisbiName];
|
||||
if ((f === null || f === void 0 ? void 0 : f.hide) === true) {
|
||||
return;
|
||||
}
|
||||
columns.push(ele.gisbiName);
|
||||
meta.push({
|
||||
field: ele.gisbiName,
|
||||
name: (_a = ele.chartShowName) !== null && _a !== void 0 ? _a : ele.name,
|
||||
formatter: function (value) {
|
||||
if (!f) {
|
||||
return value;
|
||||
}
|
||||
if (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
if (![2, 3, 4].includes(f.deType) || !lodash_es_1.isNumber(value)) {
|
||||
return value;
|
||||
}
|
||||
var formatCfg = f.formatterCfg;
|
||||
if (!formatCfg) {
|
||||
formatCfg = formatter_1.formatterItem;
|
||||
}
|
||||
return formatter_1.valueFormatter(value, formatCfg);
|
||||
}
|
||||
});
|
||||
});
|
||||
var _f = util_1.parseJson(chart.customAttr), basicStyle = _f.basicStyle, tableCell = _f.tableCell, tableHeader = _f.tableHeader, tooltip = _f.tooltip;
|
||||
// 表头分组
|
||||
var headerGroup = tableHeader.headerGroup, showTableHeader = tableHeader.showTableHeader;
|
||||
if (headerGroup && showTableHeader !== false) {
|
||||
var headerGroupConfig = tableHeader.headerGroupConfig;
|
||||
if ((_c = headerGroupConfig === null || headerGroupConfig === void 0 ? void 0 : headerGroupConfig.columns) === null || _c === void 0 ? void 0 : _c.length) {
|
||||
var allKeys = columns.map(function (c) { return drillFieldMap[c] || c; });
|
||||
var leafNodes = common_table_1.getLeafNodes(headerGroupConfig.columns);
|
||||
var leafKeys = leafNodes.map(function (c) { return c.key; });
|
||||
if (lodash_es_1.isEqual(leafKeys, allKeys)) {
|
||||
if (Object.keys(drillFieldMap).length) {
|
||||
var originField = Object.values(drillFieldMap)[0];
|
||||
var drillField = Object.keys(drillFieldMap)[0];
|
||||
var drillCol = common_table_1.getColumns([originField], headerGroupConfig.columns)[0];
|
||||
drillCol.key = drillField;
|
||||
}
|
||||
columns.splice.apply(columns, __spreadArrays([0, columns.length], headerGroupConfig.columns));
|
||||
meta.push.apply(meta, headerGroupConfig.meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 空值处理
|
||||
var newData = this.configEmptyDataStrategy(chart);
|
||||
// data config
|
||||
var s2DataConfig = {
|
||||
fields: {
|
||||
columns: columns
|
||||
},
|
||||
meta: meta,
|
||||
data: newData
|
||||
};
|
||||
// options
|
||||
var s2Options = {
|
||||
width: containerDom.getBoundingClientRect().width,
|
||||
height: containerDom.offsetHeight,
|
||||
showSeriesNumber: tableHeader.showIndex,
|
||||
conditions: this.configConditions(chart),
|
||||
tooltip: {
|
||||
getContainer: function () { return containerDom; },
|
||||
renderTooltip: function (sheet) { return new common_table_1.SortTooltip(sheet); }
|
||||
},
|
||||
interaction: {
|
||||
hoverHighlight: !(basicStyle.showHoverStyle === false),
|
||||
scrollbarPosition: newData.length
|
||||
? s2_1.ScrollbarPositionType.CONTENT
|
||||
: s2_1.ScrollbarPositionType.CANVAS
|
||||
}
|
||||
};
|
||||
s2Options.style = this.configStyle(chart, s2DataConfig);
|
||||
// 自适应列宽模式下,URL 字段的宽度固定为 120
|
||||
if (basicStyle.tableColumnMode === 'adapt') {
|
||||
var urlFields = fields.filter(function (field) { var _a; return field.deType === 7 && !((_a = axisMap[field.gisbiName]) === null || _a === void 0 ? void 0 : _a.hide); });
|
||||
s2Options.style.colCfg.widthByFieldValue = urlFields === null || urlFields === void 0 ? void 0 : urlFields.reduce(function (p, n) {
|
||||
var _a;
|
||||
p[(_a = n.chartShowName) !== null && _a !== void 0 ? _a : n.name] = 120;
|
||||
return p;
|
||||
}, {});
|
||||
}
|
||||
if (tableCell.tableFreeze && !tableCell.mergeCells) {
|
||||
s2Options.frozenColCount = (_d = tableCell.tableColumnFreezeHead) !== null && _d !== void 0 ? _d : 0;
|
||||
s2Options.frozenRowCount = (_e = tableCell.tableRowFreezeHead) !== null && _e !== void 0 ? _e : 0;
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options);
|
||||
// 合并单元格
|
||||
this.configMergeCells(chart, s2Options, s2DataConfig);
|
||||
// 隐藏表头,保留顶部的分割线, 禁用表头横向 resize
|
||||
if (tableHeader.showTableHeader === false) {
|
||||
s2Options.style.colCfg.height = 1;
|
||||
if (tableCell.showHorizonBorder === false) {
|
||||
s2Options.style.colCfg.height = 0;
|
||||
}
|
||||
s2Options.interaction.resize = {
|
||||
colCellVertical: false
|
||||
};
|
||||
s2Options.colCell = function (node, sheet, config) {
|
||||
node.label = ' ';
|
||||
return new s2_1.TableColCell(node, sheet, config);
|
||||
};
|
||||
}
|
||||
else {
|
||||
// header interaction
|
||||
chart.container = container;
|
||||
this.configHeaderInteraction(chart, s2Options);
|
||||
s2Options.colCell = function (node, sheet, config) {
|
||||
// 配置文本自动换行参数
|
||||
node.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap;
|
||||
node.maxLines = basicStyle.maxLines;
|
||||
return new common_table_1.CustomTableColCell(node, sheet, config);
|
||||
};
|
||||
}
|
||||
// 序列号和总计行
|
||||
this.configSummaryRowAndIndex(chart, pageInfo, s2Options, s2DataConfig);
|
||||
// 开始渲染
|
||||
var newChart = new s2_1.TableSheet(containerDom, s2DataConfig, s2Options);
|
||||
// 总计紧贴在单元格后面
|
||||
this.summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary);
|
||||
// 开启自动换行
|
||||
if (basicStyle.autoWrap && !tableCell.mergeCells) {
|
||||
// 调整表头宽度时,计算表头高度
|
||||
newChart.on(s2_1.S2Event.LAYOUT_RESIZE_COL_WIDTH, function (info) {
|
||||
common_table_1.calculateHeaderHeight(info, newChart, tableHeader, basicStyle, null);
|
||||
});
|
||||
newChart.on(s2_1.S2Event.LAYOUT_AFTER_HEADER_LAYOUT, function (ev) {
|
||||
var _a;
|
||||
var maxHeight = newChart.store.get('autoCalcHeight');
|
||||
if (maxHeight) {
|
||||
// 更新列的高度
|
||||
ev.colLeafNodes.forEach(function (n) { return (n.height = maxHeight); });
|
||||
ev.colsHierarchy.height = maxHeight;
|
||||
newChart.store.set('autoCalcHeight', undefined);
|
||||
}
|
||||
else {
|
||||
if ((_a = ev.colLeafNodes) === null || _a === void 0 ? void 0 : _a.length) {
|
||||
var _b = ev.colLeafNodes[0], value = _b.value, width = _b.width;
|
||||
common_table_1.calculateHeaderHeight({ info: { meta: { value: value }, resizedWidth: width } }, newChart, tableHeader, basicStyle, ev);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// 自适应铺满
|
||||
if (basicStyle.tableColumnMode === 'adapt') {
|
||||
newChart.on(s2_1.S2Event.LAYOUT_RESIZE_COL_WIDTH, function () {
|
||||
newChart.store.set('lastLayoutResult', newChart.facet.layoutResult);
|
||||
});
|
||||
newChart.on(s2_1.S2Event.LAYOUT_AFTER_HEADER_LAYOUT, function (ev) {
|
||||
var _a, _b;
|
||||
var lastLayoutResult = newChart.store.get('lastLayoutResult');
|
||||
if (lastLayoutResult) {
|
||||
// 拖动表头 resize
|
||||
var widthByFieldValue_1 = (_b = (_a = newChart.options.style) === null || _a === void 0 ? void 0 : _a.colCfg) === null || _b === void 0 ? void 0 : _b.widthByFieldValue;
|
||||
var lastLayoutWidthMap_1 = (lastLayoutResult === null || lastLayoutResult === void 0 ? void 0 : lastLayoutResult.colLeafNodes.reduce(function (p, n) {
|
||||
var _a;
|
||||
p[n.value] = (_a = widthByFieldValue_1 === null || widthByFieldValue_1 === void 0 ? void 0 : widthByFieldValue_1[n.value]) !== null && _a !== void 0 ? _a : n.width;
|
||||
return p;
|
||||
}, {})) || {};
|
||||
var totalWidth_1 = ev.colLeafNodes.reduce(function (p, n) {
|
||||
n.width = lastLayoutWidthMap_1[n.value] || n.width;
|
||||
n.x = p;
|
||||
return p + n.width;
|
||||
}, 0);
|
||||
// 处理分组的单元格,宽度为所有叶子节点之和
|
||||
ev.colNodes.forEach(function (n) {
|
||||
if (n.colIndex === -1) {
|
||||
n.width = calcTreeWidth(n);
|
||||
n.x = getStartPosition(n);
|
||||
}
|
||||
});
|
||||
ev.colsHierarchy.width = totalWidth_1;
|
||||
newChart.store.set('lastLayoutResult', undefined);
|
||||
return;
|
||||
}
|
||||
// 第一次渲染初始化,把图片字段固定为 120 进行计算
|
||||
var urlFields = fields
|
||||
.filter(function (field) { var _a; return field.deType === 7 && !((_a = axisMap[field.gisbiName]) === null || _a === void 0 ? void 0 : _a.hide); })
|
||||
.map(function (f) { return f.gisbiName; });
|
||||
var totalWidthWithImg = ev.colLeafNodes.reduce(function (p, n) {
|
||||
return p + (urlFields.includes(n.field) ? 120 : n.width);
|
||||
}, 0);
|
||||
var containerWidth = containerDom.getBoundingClientRect().width;
|
||||
if (containerWidth <= totalWidthWithImg) {
|
||||
// 图库计算的布局宽度已经大于等于容器宽度,不需要再扩大,但是需要处理非整数宽度值,不然会出现透明细线
|
||||
ev.colLeafNodes.reduce(function (p, n) {
|
||||
n.width = Math.round(n.width);
|
||||
n.x = p;
|
||||
return p + n.width;
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
// 图片字段固定 120, 剩余宽度按比例均摊到其他字段进行扩大
|
||||
var totalWidthWithoutImg = ev.colLeafNodes.reduce(function (p, n) {
|
||||
return p + (urlFields.includes(n.field) ? 0 : n.width);
|
||||
}, 0);
|
||||
var restWidth = containerWidth - urlFields.length * 120;
|
||||
var scale = restWidth / totalWidthWithoutImg;
|
||||
var totalWidth = ev.colLeafNodes.reduce(function (p, n) {
|
||||
n.width = urlFields.includes(n.field) ? 120 : Math.round(n.width * scale);
|
||||
n.x = p;
|
||||
return p + n.width;
|
||||
}, 0);
|
||||
// 处理分组的单元格,宽度为所有叶子节点之和
|
||||
ev.colNodes.forEach(function (n) {
|
||||
if (n.colIndex === -1) {
|
||||
n.width = calcTreeWidth(n);
|
||||
n.x = getStartPosition(n);
|
||||
}
|
||||
});
|
||||
if (totalWidth > containerWidth) {
|
||||
ev.colLeafNodes[ev.colLeafNodes.length - 1].width -= totalWidth - containerWidth;
|
||||
}
|
||||
ev.colsHierarchy.width = containerWidth;
|
||||
});
|
||||
}
|
||||
// 空数据时表格样式
|
||||
common_table_1.configEmptyDataStyle(newChart, basicStyle, newData, container);
|
||||
// click
|
||||
newChart.on(s2_1.S2Event.DATA_CELL_CLICK, function (ev) {
|
||||
var cell = newChart.getCell(ev.target);
|
||||
var meta = cell.getMeta();
|
||||
var nameIdMap = fields.reduce(function (pre, next) {
|
||||
pre[next['gisbiName']] = next['id'];
|
||||
return pre;
|
||||
}, {});
|
||||
var rowData = newChart.dataSet.getRowData(meta);
|
||||
var dimensionList = [];
|
||||
for (var key in rowData) {
|
||||
if (nameIdMap[key]) {
|
||||
dimensionList.push({ id: nameIdMap[key], value: rowData[key] });
|
||||
}
|
||||
}
|
||||
var param = {
|
||||
x: ev.x,
|
||||
y: ev.y,
|
||||
data: {
|
||||
dimensionList: dimensionList,
|
||||
name: nameIdMap[meta.valueField],
|
||||
sourceType: 'table-info',
|
||||
quotaList: []
|
||||
}
|
||||
};
|
||||
action(param);
|
||||
});
|
||||
// 合并的单元格直接复用数据单元格的事件
|
||||
newChart.on(s2_1.S2Event.MERGED_CELLS_CLICK, function (e) { return newChart.emit(s2_1.S2Event.DATA_CELL_CLICK, e); });
|
||||
// tooltip
|
||||
var show = tooltip.show;
|
||||
if (show) {
|
||||
newChart.on(s2_1.S2Event.COL_CELL_HOVER, function (event) { return _this.showTooltip(newChart, event, meta); });
|
||||
newChart.on(s2_1.S2Event.DATA_CELL_HOVER, function (event) { return _this.showTooltip(newChart, event, meta); });
|
||||
newChart.on(s2_1.S2Event.MERGED_CELLS_HOVER, function (event) { return _this.showTooltip(newChart, event, meta); });
|
||||
// touch
|
||||
this.configTouchEvent(newChart, drawOption, meta);
|
||||
}
|
||||
// header resize
|
||||
newChart.on(s2_1.S2Event.LAYOUT_RESIZE_COL_WIDTH, function (ev) { return resizeAction(ev); });
|
||||
// right click
|
||||
newChart.on(s2_1.S2Event.GLOBAL_CONTEXT_MENU, function (event) { return common_table_1.copyContent(newChart, event, meta); });
|
||||
// theme
|
||||
var customTheme = this.configTheme(chart);
|
||||
newChart.setThemeCfg({ theme: customTheme });
|
||||
return newChart;
|
||||
};
|
||||
TableInfo.prototype.configTheme = function (chart) {
|
||||
var theme = _super.prototype.configTheme.call(this, chart);
|
||||
var _a = util_1.parseJson(chart.customAttr), basicStyle = _a.basicStyle, tableCell = _a.tableCell;
|
||||
if (tableCell.mergeCells) {
|
||||
var tableFontColor = util_1.hexColorToRGBA(tableCell.tableFontColor, basicStyle.alpha);
|
||||
var tableItemBgColor = tableCell.tableItemBgColor;
|
||||
if (!util_1.isAlphaColor(tableItemBgColor)) {
|
||||
tableItemBgColor = util_1.hexColorToRGBA(tableItemBgColor, basicStyle.alpha);
|
||||
}
|
||||
var tableBorderColor = basicStyle.tableBorderColor;
|
||||
var tableItemAlign = tableCell.tableItemAlign, tableItemFontSize = tableCell.tableItemFontSize;
|
||||
var fontStyle = tableCell.isItalic ? 'italic' : 'normal';
|
||||
var fontWeight = tableCell.isBolder === false ? 'normal' : 'bold';
|
||||
var mergeCellTheme = {
|
||||
dataCell: {
|
||||
cell: {
|
||||
crossBackgroundColor: tableItemBgColor
|
||||
}
|
||||
},
|
||||
mergedCell: {
|
||||
cell: {
|
||||
backgroundColor: tableItemBgColor,
|
||||
crossBackgroundColor: tableItemBgColor,
|
||||
horizontalBorderColor: tableBorderColor,
|
||||
verticalBorderColor: tableBorderColor,
|
||||
horizontalBorderWidth: tableCell.showHorizonBorder ? 1 : 0,
|
||||
verticalBorderWidth: tableCell.showVerticalBorder ? 1 : 0
|
||||
},
|
||||
bolderText: {
|
||||
fill: tableFontColor,
|
||||
textAlign: tableItemAlign,
|
||||
fontSize: tableItemFontSize,
|
||||
fontStyle: fontStyle,
|
||||
fontWeight: fontWeight
|
||||
},
|
||||
text: {
|
||||
fill: tableFontColor,
|
||||
textAlign: tableItemAlign,
|
||||
fontSize: tableItemFontSize,
|
||||
fontStyle: fontStyle,
|
||||
fontWeight: fontWeight
|
||||
},
|
||||
measureText: {
|
||||
fill: tableFontColor,
|
||||
textAlign: tableItemAlign,
|
||||
fontSize: tableItemFontSize,
|
||||
fontStyle: fontStyle,
|
||||
fontWeight: fontWeight
|
||||
},
|
||||
seriesText: {
|
||||
fill: tableFontColor,
|
||||
textAlign: tableItemAlign,
|
||||
fontSize: tableItemFontSize,
|
||||
fontStyle: fontStyle,
|
||||
fontWeight: fontWeight
|
||||
}
|
||||
}
|
||||
};
|
||||
lodash_es_1.merge(theme, mergeCellTheme);
|
||||
}
|
||||
return theme;
|
||||
};
|
||||
TableInfo.prototype.configSummaryRowAndIndex = function (chart, pageInfo, s2Options, s2DataConfig) {
|
||||
var _a, _b;
|
||||
var _c = util_1.parseJson(chart.customAttr), tableHeader = _c.tableHeader, basicStyle = _c.basicStyle, tableCell = _c.tableCell;
|
||||
var fields = (_b = (_a = chart.data) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [];
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
var indexLabel_1 = tableHeader.indexLabel;
|
||||
if (!indexLabel_1) {
|
||||
indexLabel_1 = '';
|
||||
}
|
||||
s2Options.layoutCoordinate = function (_, __, col) {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel_1;
|
||||
col.value = indexLabel_1;
|
||||
}
|
||||
};
|
||||
}
|
||||
var showSummary = basicStyle.showSummary, summaryLabel = basicStyle.summaryLabel;
|
||||
var data = s2DataConfig.data;
|
||||
var xAxis = chart.xAxis;
|
||||
if (showSummary && (data === null || data === void 0 ? void 0 : data.length)) {
|
||||
// 设置汇总行高度和表头一致
|
||||
var heightByField = {};
|
||||
heightByField[data.length] = tableHeader.tableTitleHeight;
|
||||
s2Options.style.rowCfg = { heightByField: heightByField };
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1;
|
||||
var axis = lodash_es_1.filter(xAxis, function (axis) { return [2, 3, 4].includes(axis.deType); });
|
||||
var summaryObj = common_table_1.getSummaryRow(data, axis, basicStyle.seriesSummary);
|
||||
data.push(summaryObj);
|
||||
}
|
||||
s2Options.dataCell = function (viewMeta) {
|
||||
var _a;
|
||||
// 总计行处理
|
||||
if (showSummary && viewMeta.rowIndex === data.length - 1) {
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex) {
|
||||
viewMeta.fieldValue = summaryLabel !== null && summaryLabel !== void 0 ? summaryLabel : t('chart.total_show');
|
||||
}
|
||||
else {
|
||||
// 第一列不是数值类型的,显示总计
|
||||
if (![2, 3, 4].includes((_a = xAxis === null || xAxis === void 0 ? void 0 : xAxis[0]) === null || _a === void 0 ? void 0 : _a.deType)) {
|
||||
viewMeta.fieldValue = summaryLabel !== null && summaryLabel !== void 0 ? summaryLabel : t('chart.total_show');
|
||||
}
|
||||
}
|
||||
}
|
||||
return new common_table_1.SummaryCell(viewMeta, viewMeta === null || viewMeta === void 0 ? void 0 : viewMeta.spreadsheet);
|
||||
}
|
||||
var field = fields.find(function (f) { return f.gisbiName === viewMeta.valueField; });
|
||||
if ((field === null || field === void 0 ? void 0 : field.deType) === 7 && chart.showPosition !== 'dialog') {
|
||||
return new ImageCell(viewMeta, viewMeta === null || viewMeta === void 0 ? void 0 : viewMeta.spreadsheet);
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
if (tableCell.mergeCells) {
|
||||
viewMeta.fieldValue = common_table_1.getRowIndex(s2Options.mergedCellsInfo, viewMeta);
|
||||
}
|
||||
else {
|
||||
viewMeta.fieldValue =
|
||||
pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1;
|
||||
}
|
||||
}
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap;
|
||||
viewMeta.maxLines = basicStyle.maxLines;
|
||||
return new common_table_1.CustomDataCell(viewMeta, viewMeta === null || viewMeta === void 0 ? void 0 : viewMeta.spreadsheet);
|
||||
};
|
||||
};
|
||||
TableInfo.prototype.summaryRowStyle = function (newChart, newData, tableCell, tableHeader, showSummary) {
|
||||
if (!showSummary || !newData.length)
|
||||
return;
|
||||
var columns = newChart.dataCfg.fields.columns;
|
||||
var showHeader = tableHeader.showTableHeader === true;
|
||||
// 不显示表头时,减少一个表头的高度
|
||||
var headerAndSummaryHeight = showHeader ? getMaxTreeDepth(columns) + 1 : 1;
|
||||
newChart.on(s2_1.S2Event.LAYOUT_BEFORE_RENDER, function () {
|
||||
var totalHeight = tableHeader.tableTitleHeight * headerAndSummaryHeight +
|
||||
tableCell.tableItemHeight * (newData.length - 1);
|
||||
if (totalHeight < newChart.container.cfg.height) {
|
||||
newChart.options.height =
|
||||
totalHeight < newChart.container.cfg.height - 8 ? totalHeight + 8 : totalHeight;
|
||||
}
|
||||
});
|
||||
};
|
||||
return TableInfo;
|
||||
}(s2_2.S2ChartView));
|
||||
exports.TableInfo = TableInfo;
|
||||
function calcTreeWidth(node) {
|
||||
var _a;
|
||||
if (!((_a = node.children) === null || _a === void 0 ? void 0 : _a.length)) {
|
||||
return node.width;
|
||||
}
|
||||
return node.children.reduce(function (pre, cur) {
|
||||
return pre + calcTreeWidth(cur);
|
||||
}, 0);
|
||||
}
|
||||
function getStartPosition(node) {
|
||||
var _a;
|
||||
if (!((_a = node.children) === null || _a === void 0 ? void 0 : _a.length)) {
|
||||
return node.x;
|
||||
}
|
||||
return getStartPosition(node.children[0]);
|
||||
}
|
||||
function getMaxTreeDepth(nodes) {
|
||||
if (!(nodes === null || nodes === void 0 ? void 0 : nodes.length)) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max.apply(Math, nodes.map(function (node) {
|
||||
var _a;
|
||||
if (!((_a = node.children) === null || _a === void 0 ? void 0 : _a.length)) {
|
||||
return 1;
|
||||
}
|
||||
return getMaxTreeDepth(node.children) + 1;
|
||||
}));
|
||||
}
|
356
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/table-normal.js
vendored
Normal file
356
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/table-normal.js
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
exports.TableNormal = void 0;
|
||||
var useI18n_1 = require("@/hooks/web/useI18n");
|
||||
var formatter_1 = require("@/views/chart/components/js/formatter");
|
||||
var common_table_1 = require("@/views/chart/components/js/panel/common/common_table");
|
||||
var s2_1 = require("@/views/chart/components/js/panel/types/impl/s2");
|
||||
var util_1 = require("@/views/chart/components/js/util");
|
||||
var s2_2 = require("@antv/s2");
|
||||
var lodash_es_1 = require("lodash-es");
|
||||
var common_1 = require("./common");
|
||||
var t = useI18n_1.useI18n().t;
|
||||
/**
|
||||
* 汇总表
|
||||
*/
|
||||
var TableNormal = /** @class */ (function (_super) {
|
||||
__extends(TableNormal, _super);
|
||||
function TableNormal() {
|
||||
var _this = _super.call(this, 'table-normal', []) || this;
|
||||
_this.properties = common_1.TABLE_EDITOR_PROPERTY;
|
||||
_this.propertyInner = __assign(__assign({}, common_1.TABLE_EDITOR_PROPERTY_INNER), { 'table-header-selector': __spreadArrays(common_1.TABLE_EDITOR_PROPERTY_INNER['table-header-selector'], [
|
||||
'tableHeaderSort',
|
||||
'showTableHeader'
|
||||
]), 'basic-style-selector': __spreadArrays(common_1.TABLE_EDITOR_PROPERTY_INNER['basic-style-selector'], [
|
||||
'tablePageMode',
|
||||
'showHoverStyle'
|
||||
]), 'table-cell-selector': __spreadArrays(common_1.TABLE_EDITOR_PROPERTY_INNER['table-cell-selector'], [
|
||||
'tableFreeze',
|
||||
'tableColumnFreezeHead',
|
||||
'tableRowFreezeHead'
|
||||
]), 'summary-selector': ['showSummary', 'summaryLabel'] });
|
||||
_this.axis = ['xAxis', 'yAxis', 'drill', 'filter'];
|
||||
_this.axisConfig = {
|
||||
xAxis: {
|
||||
name: t('chart.drag_block_table_data_column') + " / " + t('chart.dimension'),
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: t('chart.drag_block_table_data_column') + " / " + t('chart.quota'),
|
||||
type: 'q'
|
||||
}
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
TableNormal.prototype.setupDefaultOptions = function (chart) {
|
||||
chart.xAxis = [];
|
||||
return chart;
|
||||
};
|
||||
TableNormal.prototype.drawChart = function (drawOption) {
|
||||
var _this = this;
|
||||
var _a, _b;
|
||||
var container = drawOption.container, chart = drawOption.chart, action = drawOption.action, pageInfo = drawOption.pageInfo, resizeAction = drawOption.resizeAction;
|
||||
var containerDom = document.getElementById(container);
|
||||
if (!containerDom)
|
||||
return;
|
||||
// fields
|
||||
var fields = chart.data.fields;
|
||||
var columns = [];
|
||||
var meta = [];
|
||||
if (chart.drill) {
|
||||
// 下钻过滤字段
|
||||
var filterFields_1 = chart.drillFilters.map(function (i) { return i.fieldId; });
|
||||
// 下钻入口的字段下标
|
||||
var drillFieldId_1 = chart.drillFields[0].id;
|
||||
var drillFieldIndex = chart.xAxis.findIndex(function (ele) { return ele.id === drillFieldId_1; });
|
||||
// 当前下钻字段
|
||||
var curDrillFieldId_1 = chart.drillFields[filterFields_1.length].id;
|
||||
var curDrillField = fields.filter(function (ele) { return ele.id === curDrillFieldId_1; });
|
||||
filterFields_1.push(curDrillFieldId_1);
|
||||
// 移除下钻字段,把当前下钻字段插入到下钻入口位置
|
||||
fields = fields.filter(function (ele) {
|
||||
return !filterFields_1.includes(ele.id);
|
||||
});
|
||||
fields.splice.apply(fields, __spreadArrays([drillFieldIndex, 0], curDrillField));
|
||||
}
|
||||
var axisMap = __spreadArrays(chart.xAxis, chart.yAxis).reduce(function (pre, cur) {
|
||||
pre[cur.gisbiName] = cur;
|
||||
return pre;
|
||||
}, {});
|
||||
// add drill list
|
||||
fields.forEach(function (ele) {
|
||||
var _a;
|
||||
var f = axisMap[ele.gisbiName];
|
||||
if ((f === null || f === void 0 ? void 0 : f.hide) === true) {
|
||||
return;
|
||||
}
|
||||
columns.push(ele.gisbiName);
|
||||
meta.push({
|
||||
field: ele.gisbiName,
|
||||
name: (_a = ele.chartShowName) !== null && _a !== void 0 ? _a : ele.name,
|
||||
formatter: function (value) {
|
||||
if (!f) {
|
||||
return value;
|
||||
}
|
||||
if (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
if (![2, 3, 4].includes(f.deType) || !lodash_es_1.isNumber(value)) {
|
||||
return value;
|
||||
}
|
||||
var formatCfg = f.formatterCfg;
|
||||
if (!formatCfg) {
|
||||
formatCfg = formatter_1.formatterItem;
|
||||
}
|
||||
return formatter_1.valueFormatter(value, formatCfg);
|
||||
}
|
||||
});
|
||||
});
|
||||
// 空值处理
|
||||
var newData = this.configEmptyDataStrategy(chart);
|
||||
// data config
|
||||
var s2DataConfig = {
|
||||
fields: {
|
||||
columns: columns
|
||||
},
|
||||
meta: meta,
|
||||
data: newData
|
||||
};
|
||||
var _c = util_1.parseJson(chart.customAttr), basicStyle = _c.basicStyle, tableCell = _c.tableCell, tableHeader = _c.tableHeader, tooltip = _c.tooltip;
|
||||
// options
|
||||
var s2Options = {
|
||||
width: containerDom.getBoundingClientRect().width,
|
||||
height: containerDom.offsetHeight,
|
||||
showSeriesNumber: tableHeader.showIndex,
|
||||
conditions: this.configConditions(chart),
|
||||
tooltip: {
|
||||
getContainer: function () { return containerDom; },
|
||||
renderTooltip: function (sheet) { return new common_table_1.SortTooltip(sheet); }
|
||||
},
|
||||
interaction: {
|
||||
hoverHighlight: !(basicStyle.showHoverStyle === false),
|
||||
scrollbarPosition: newData.length
|
||||
? s2_2.ScrollbarPositionType.CONTENT
|
||||
: s2_2.ScrollbarPositionType.CANVAS
|
||||
}
|
||||
};
|
||||
// 列宽设置
|
||||
s2Options.style = this.configStyle(chart, s2DataConfig);
|
||||
// 行列冻结
|
||||
if (tableCell.tableFreeze) {
|
||||
s2Options.frozenColCount = (_a = tableCell.tableColumnFreezeHead) !== null && _a !== void 0 ? _a : 0;
|
||||
s2Options.frozenRowCount = (_b = tableCell.tableRowFreezeHead) !== null && _b !== void 0 ? _b : 0;
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options);
|
||||
// 隐藏表头,保留顶部的分割线, 禁用表头横向 resize
|
||||
if (tableHeader.showTableHeader === false) {
|
||||
s2Options.style.colCfg.height = 1;
|
||||
if (tableCell.showHorizonBorder === false) {
|
||||
s2Options.style.colCfg.height = 0;
|
||||
}
|
||||
s2Options.interaction.resize = {
|
||||
colCellVertical: false
|
||||
};
|
||||
s2Options.colCell = function (node, sheet, config) {
|
||||
node.label = ' ';
|
||||
return new s2_2.TableColCell(node, sheet, config);
|
||||
};
|
||||
}
|
||||
else {
|
||||
// header interaction
|
||||
chart.container = container;
|
||||
this.configHeaderInteraction(chart, s2Options);
|
||||
}
|
||||
// 配置总计和序号列
|
||||
this.configSummaryRowAndIndex(chart, pageInfo, s2Options, s2DataConfig);
|
||||
// 开始渲染
|
||||
var newChart = new s2_2.TableSheet(containerDom, s2DataConfig, s2Options);
|
||||
// 总计紧贴在单元格后面
|
||||
this.summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary);
|
||||
// 自适应铺满
|
||||
if (basicStyle.tableColumnMode === 'adapt') {
|
||||
newChart.on(s2_2.S2Event.LAYOUT_RESIZE_COL_WIDTH, function () {
|
||||
newChart.store.set('lastLayoutResult', newChart.facet.layoutResult);
|
||||
});
|
||||
newChart.on(s2_2.S2Event.LAYOUT_AFTER_HEADER_LAYOUT, function (ev) {
|
||||
var _a, _b;
|
||||
var lastLayoutResult = newChart.store.get('lastLayoutResult');
|
||||
if (lastLayoutResult) {
|
||||
// 拖动表头 resize
|
||||
var widthByFieldValue_1 = (_b = (_a = newChart.options.style) === null || _a === void 0 ? void 0 : _a.colCfg) === null || _b === void 0 ? void 0 : _b.widthByFieldValue;
|
||||
var lastLayoutWidthMap_1 = (lastLayoutResult === null || lastLayoutResult === void 0 ? void 0 : lastLayoutResult.colLeafNodes.reduce(function (p, n) {
|
||||
var _a;
|
||||
p[n.value] = (_a = widthByFieldValue_1 === null || widthByFieldValue_1 === void 0 ? void 0 : widthByFieldValue_1[n.value]) !== null && _a !== void 0 ? _a : n.width;
|
||||
return p;
|
||||
}, {})) || {};
|
||||
var totalWidth_1 = ev.colLeafNodes.reduce(function (p, n) {
|
||||
n.width = lastLayoutWidthMap_1[n.value] || n.width;
|
||||
n.x = p;
|
||||
return p + n.width;
|
||||
}, 0);
|
||||
ev.colsHierarchy.width = totalWidth_1;
|
||||
newChart.store.set('lastLayoutResult', undefined);
|
||||
return;
|
||||
}
|
||||
var containerWidth = containerDom.getBoundingClientRect().width;
|
||||
var scale = containerWidth / ev.colsHierarchy.width;
|
||||
if (scale <= 1) {
|
||||
// 图库计算的布局宽度已经大于等于容器宽度,不需要再扩大,但是需要处理非整数宽度值,不然会出现透明细线
|
||||
ev.colLeafNodes.reduce(function (p, n) {
|
||||
n.width = Math.round(n.width);
|
||||
n.x = p;
|
||||
return p + n.width;
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
var totalWidth = ev.colLeafNodes.reduce(function (p, n) {
|
||||
n.width = Math.round(n.width * scale);
|
||||
n.x = p;
|
||||
return p + n.width;
|
||||
}, 0);
|
||||
if (totalWidth > containerWidth) {
|
||||
// 从最后一列减掉
|
||||
ev.colLeafNodes[ev.colLeafNodes.length - 1].width -= totalWidth - containerWidth;
|
||||
}
|
||||
ev.colsHierarchy.width = containerWidth;
|
||||
});
|
||||
}
|
||||
common_table_1.configEmptyDataStyle(newChart, basicStyle, newData, container);
|
||||
// click
|
||||
newChart.on(s2_2.S2Event.DATA_CELL_CLICK, function (ev) {
|
||||
var cell = newChart.getCell(ev.target);
|
||||
var meta = cell.getMeta();
|
||||
var nameIdMap = fields.reduce(function (pre, next) {
|
||||
pre[next['gisbiName']] = next['id'];
|
||||
return pre;
|
||||
}, {});
|
||||
var rowData = newChart.dataSet.getRowData(meta);
|
||||
var dimensionList = [];
|
||||
for (var key in rowData) {
|
||||
if (nameIdMap[key]) {
|
||||
dimensionList.push({ id: nameIdMap[key], value: rowData[key] });
|
||||
}
|
||||
}
|
||||
var param = {
|
||||
x: ev.x,
|
||||
y: ev.y,
|
||||
data: {
|
||||
dimensionList: dimensionList,
|
||||
name: nameIdMap[meta.valueField],
|
||||
sourceType: 'table-normal',
|
||||
quotaList: []
|
||||
}
|
||||
};
|
||||
action(param);
|
||||
});
|
||||
// tooltip
|
||||
var show = tooltip.show;
|
||||
if (show) {
|
||||
newChart.on(s2_2.S2Event.COL_CELL_HOVER, function (event) { return _this.showTooltip(newChart, event, meta); });
|
||||
newChart.on(s2_2.S2Event.DATA_CELL_HOVER, function (event) { return _this.showTooltip(newChart, event, meta); });
|
||||
// touch
|
||||
this.configTouchEvent(newChart, drawOption, meta);
|
||||
}
|
||||
// header resize
|
||||
newChart.on(s2_2.S2Event.LAYOUT_RESIZE_COL_WIDTH, function (ev) { return resizeAction(ev); });
|
||||
// right click
|
||||
newChart.on(s2_2.S2Event.GLOBAL_CONTEXT_MENU, function (event) { return common_table_1.copyContent(newChart, event, meta); });
|
||||
// theme
|
||||
var customTheme = this.configTheme(chart);
|
||||
newChart.setThemeCfg({ theme: customTheme });
|
||||
return newChart;
|
||||
};
|
||||
TableNormal.prototype.configSummaryRowAndIndex = function (chart, pageInfo, s2Options, s2DataConfig) {
|
||||
var _a = util_1.parseJson(chart.customAttr), tableHeader = _a.tableHeader, basicStyle = _a.basicStyle;
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
var indexLabel_1 = tableHeader.indexLabel;
|
||||
if (!indexLabel_1) {
|
||||
indexLabel_1 = '';
|
||||
}
|
||||
s2Options.layoutCoordinate = function (_, __, col) {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel_1;
|
||||
col.value = indexLabel_1;
|
||||
}
|
||||
};
|
||||
}
|
||||
var showSummary = basicStyle.showSummary, summaryLabel = basicStyle.summaryLabel;
|
||||
var data = s2DataConfig.data;
|
||||
var xAxis = chart.xAxis, yAxis = chart.yAxis;
|
||||
if (showSummary && (data === null || data === void 0 ? void 0 : data.length)) {
|
||||
// 设置汇总行高度和表头一致
|
||||
var heightByField = {};
|
||||
heightByField[data.length] = tableHeader.tableTitleHeight;
|
||||
s2Options.style.rowCfg = { heightByField: heightByField };
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1;
|
||||
var summaryObj = common_table_1.getSummaryRow(data, yAxis, basicStyle.seriesSummary);
|
||||
data.push(summaryObj);
|
||||
}
|
||||
s2Options.dataCell = function (viewMeta) {
|
||||
// 总计行处理
|
||||
if (showSummary && viewMeta.rowIndex === data.length - 1) {
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex || (xAxis === null || xAxis === void 0 ? void 0 : xAxis.length)) {
|
||||
viewMeta.fieldValue = summaryLabel !== null && summaryLabel !== void 0 ? summaryLabel : t('chart.total_show');
|
||||
}
|
||||
}
|
||||
return new common_table_1.SummaryCell(viewMeta, viewMeta === null || viewMeta === void 0 ? void 0 : viewMeta.spreadsheet);
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
viewMeta.fieldValue = pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1;
|
||||
}
|
||||
return new common_table_1.CustomDataCell(viewMeta, viewMeta === null || viewMeta === void 0 ? void 0 : viewMeta.spreadsheet);
|
||||
};
|
||||
};
|
||||
TableNormal.prototype.summaryRowStyle = function (newChart, newData, tableCell, tableHeader, showSummary) {
|
||||
if (!showSummary || !newData.length)
|
||||
return;
|
||||
newChart.on(s2_2.S2Event.LAYOUT_BEFORE_RENDER, function () {
|
||||
var showHeader = tableHeader.showTableHeader === true;
|
||||
// 不显示表头时,减少一个表头的高度
|
||||
var headerAndSummaryHeight = showHeader ? 2 : 1;
|
||||
var totalHeight = tableHeader.tableTitleHeight * headerAndSummaryHeight +
|
||||
tableCell.tableItemHeight * (newData.length - 1);
|
||||
if (totalHeight < newChart.container.cfg.height) {
|
||||
newChart.options.height =
|
||||
totalHeight < newChart.container.cfg.height - 8 ? totalHeight + 8 : totalHeight;
|
||||
}
|
||||
});
|
||||
};
|
||||
return TableNormal;
|
||||
}(s2_1.S2ChartView));
|
||||
exports.TableNormal = TableNormal;
|
1278
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/table-pivot.js
vendored
Normal file
1278
frontend/src/data-visualization/chart/components/js/panel/charts/table/dist/table-pivot.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -119,11 +119,12 @@ export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
|
||||
if (!xAxis?.length || !xAxisExt?.length || !extColor?.length) {
|
||||
return
|
||||
}
|
||||
const xField = xAxis[0].dataeaseName
|
||||
const xFieldExt = xAxisExt[0].dataeaseName
|
||||
const extColorField = extColor[0].dataeaseName
|
||||
const xField = xAxis[0].gisbiName
|
||||
const xFieldExt = xAxisExt[0].gisbiName
|
||||
const extColorField = extColor[0].gisbiName
|
||||
// data
|
||||
const data = cloneDeep(chart.data.tableRow)
|
||||
const tmpData = cloneDeep(chart.data.tableRow)
|
||||
const data = tmpData.filter(cell => cell[xField] && cell[xFieldExt] && cell[extColorField])
|
||||
data.forEach(i => {
|
||||
Object.keys(i).forEach(key => {
|
||||
if (key === '*') {
|
||||
@ -171,10 +172,10 @@ export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
|
||||
const dimensionList = []
|
||||
chart.data.fields.forEach(item => {
|
||||
Object.keys(pointData).forEach(key => {
|
||||
if (key.startsWith('f_') && item.dataeaseName === key) {
|
||||
if (key.startsWith('f_') && item.gisbiName === key) {
|
||||
dimensionList.push({
|
||||
id: item.id,
|
||||
dataeaseName: item.dataeaseName,
|
||||
gisbiName: item.gisbiName,
|
||||
value: pointData[key]
|
||||
})
|
||||
}
|
||||
@ -197,7 +198,7 @@ export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
|
||||
newChart.on('afterrender', ev => {
|
||||
const l = JSON.parse(JSON.stringify(parseJson(chart.customStyle).legend))
|
||||
if (l.show) {
|
||||
const rail = ev.view.getController('legend').option[extColor[0].dataeaseName]?.['rail']
|
||||
const rail = ev.view.getController('legend').option[extColor[0].gisbiName]?.['rail']
|
||||
if (rail) {
|
||||
rail.defaultLength = this.getDefaultLength(chart, l)
|
||||
}
|
||||
@ -207,6 +208,12 @@ export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
|
||||
return newChart
|
||||
}
|
||||
|
||||
protected configTheme(chart: Chart, options: HeatmapOptions): HeatmapOptions {
|
||||
const tmp = super.configTheme(chart, options)
|
||||
tmp.theme.innerLabels.offset = 0
|
||||
return tmp
|
||||
}
|
||||
|
||||
protected configBasicStyle(chart: Chart, options: HeatmapOptions): HeatmapOptions {
|
||||
const basicStyle = parseJson(chart.customAttr).basicStyle
|
||||
const color = basicStyle.colors?.map(ele => {
|
||||
@ -235,7 +242,7 @@ export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
|
||||
const items = []
|
||||
const createItem = (fieldObj, items, originalItems) => {
|
||||
const name = fieldObj?.chartShowName ? fieldObj?.chartShowName : fieldObj?.name
|
||||
let value = originalItems[0].data[fieldObj.dataeaseName]
|
||||
let value = originalItems[0].data[fieldObj.gisbiName]
|
||||
if (!isNaN(Number(value))) {
|
||||
value = valueFormatter(value, fieldObj?.formatterCfg)
|
||||
}
|
||||
@ -329,7 +336,7 @@ export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
|
||||
position: 'middle',
|
||||
layout,
|
||||
formatter: data => {
|
||||
const value = data[extColor[0]?.dataeaseName]
|
||||
const value = data[extColor[0]?.gisbiName]
|
||||
if (!isNaN(Number(value))) {
|
||||
return valueFormatter(value, extColor[0]?.formatterCfg)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import { hexColorToRGBA, isAlphaColor, parseJson } from '../../../util'
|
||||
import { S2ChartView, S2DrawOptions } from '../../types/impl/s2'
|
||||
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { isEqual, isNumber, merge } from 'lodash-es'
|
||||
import { filter, isEqual, isNumber, merge } from 'lodash-es'
|
||||
import {
|
||||
copyContent,
|
||||
CustomDataCell,
|
||||
@ -22,37 +22,19 @@ import {
|
||||
getRowIndex,
|
||||
calculateHeaderHeight,
|
||||
SortTooltip,
|
||||
configSummaryRow,
|
||||
summaryRowStyle,
|
||||
configEmptyDataStyle,
|
||||
getLeafNodes,
|
||||
getColumns
|
||||
getColumns,
|
||||
drawImage,
|
||||
getSummaryRow,
|
||||
SummaryCell
|
||||
} from '@/data-visualization/chart/components/js/panel/common/common_table'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
class ImageCell extends CustomDataCell {
|
||||
protected drawTextShape(): void {
|
||||
const img = new Image()
|
||||
const { x, y, width, height, fieldValue } = this.meta
|
||||
img.src = fieldValue as string
|
||||
img.setAttribute('crossOrigin', 'anonymous')
|
||||
img.onload = () => {
|
||||
!this.cfg.children && (this.cfg.children = [])
|
||||
const { width: imgWidth, height: imgHeight } = img
|
||||
const ratio = Math.max(imgWidth / width, imgHeight / height)
|
||||
// 不铺满,部分留白
|
||||
const imgShowWidth = (imgWidth / ratio) * 0.8
|
||||
const imgShowHeight = (imgHeight / ratio) * 0.8
|
||||
this.textShape = this.addShape('image', {
|
||||
attrs: {
|
||||
x: x + (imgShowWidth < width ? (width - imgShowWidth) / 2 : 0),
|
||||
y: y + (imgShowHeight < height ? (height - imgShowHeight) / 2 : 0),
|
||||
width: imgShowWidth,
|
||||
height: imgShowHeight,
|
||||
img
|
||||
}
|
||||
})
|
||||
}
|
||||
drawImage.apply(this)
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -75,9 +57,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
'alpha',
|
||||
'tablePageMode',
|
||||
'showHoverStyle',
|
||||
'autoWrap',
|
||||
'showSummary',
|
||||
'summaryLabel'
|
||||
'autoWrap'
|
||||
],
|
||||
'table-cell-selector': [
|
||||
...TABLE_EDITOR_PROPERTY_INNER['table-cell-selector'],
|
||||
@ -85,7 +65,8 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
'tableColumnFreezeHead',
|
||||
'tableRowFreezeHead',
|
||||
'mergeCells'
|
||||
]
|
||||
],
|
||||
'summary-selector': ['showSummary', 'summaryLabel']
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'filter', 'drill']
|
||||
axisConfig: AxisConfig = {
|
||||
@ -103,7 +84,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
const columns = []
|
||||
const meta = []
|
||||
const axisMap = chart.xAxis.reduce((pre, cur) => {
|
||||
pre[cur.dataeaseName] = cur
|
||||
pre[cur.gisbiName] = cur
|
||||
return pre
|
||||
}, {})
|
||||
const drillFieldMap = {}
|
||||
@ -121,17 +102,17 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
fields = fields.filter(ele => {
|
||||
return !filterFields.includes(ele.id)
|
||||
})
|
||||
drillFieldMap[curDrillField.dataeaseName] = chart.drillFields[0].dataeaseName
|
||||
drillFieldMap[curDrillField.gisbiName] = chart.drillFields[0].gisbiName
|
||||
fields.splice(drillFieldIndex, 0, curDrillField)
|
||||
}
|
||||
fields.forEach(ele => {
|
||||
const f = axisMap[ele.dataeaseName]
|
||||
const f = axisMap[ele.gisbiName]
|
||||
if (f?.hide === true) {
|
||||
return
|
||||
}
|
||||
columns.push(ele.dataeaseName)
|
||||
columns.push(ele.gisbiName)
|
||||
meta.push({
|
||||
field: ele.dataeaseName,
|
||||
field: ele.gisbiName,
|
||||
name: ele.chartShowName ?? ele.name,
|
||||
formatter: function (value) {
|
||||
if (!f) {
|
||||
@ -140,7 +121,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
if (value === null || value === undefined) {
|
||||
return value
|
||||
}
|
||||
if (![2, 3].includes(f.deType) || !isNumber(value)) {
|
||||
if (![2, 3, 4].includes(f.deType) || !isNumber(value)) {
|
||||
return value
|
||||
}
|
||||
let formatCfg = f.formatterCfg
|
||||
@ -204,7 +185,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
// 自适应列宽模式下,URL 字段的宽度固定为 120
|
||||
if (basicStyle.tableColumnMode === 'adapt') {
|
||||
const urlFields = fields.filter(
|
||||
field => field.deType === 7 && !axisMap[field.dataeaseName]?.hide
|
||||
field => field.deType === 7 && !axisMap[field.gisbiName]?.hide
|
||||
)
|
||||
s2Options.style.colCfg.widthByFieldValue = urlFields?.reduce((p, n) => {
|
||||
p[n.chartShowName ?? n.name] = 120
|
||||
@ -215,37 +196,6 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
s2Options.frozenColCount = tableCell.tableColumnFreezeHead ?? 0
|
||||
s2Options.frozenRowCount = tableCell.tableRowFreezeHead ?? 0
|
||||
}
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
const field = fields.filter(f => f.dataeaseName === viewMeta.valueField)?.[0]
|
||||
if (field?.deType === 7 && chart.showPosition !== 'dialog') {
|
||||
return new ImageCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
if (tableCell.mergeCells) {
|
||||
viewMeta.fieldValue = getRowIndex(s2Options.mergedCellsInfo, viewMeta)
|
||||
} else {
|
||||
viewMeta.fieldValue =
|
||||
pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
}
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options)
|
||||
// 合并单元格
|
||||
@ -274,12 +224,12 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
return new CustomTableColCell(node, sheet, config)
|
||||
}
|
||||
}
|
||||
// 总计
|
||||
configSummaryRow(chart, s2Options, newData, tableHeader, basicStyle, basicStyle.showSummary)
|
||||
// 序列号和总计行
|
||||
this.configSummaryRowAndIndex(chart, pageInfo, s2Options, s2DataConfig)
|
||||
// 开始渲染
|
||||
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)
|
||||
// 总计紧贴在单元格后面
|
||||
summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary)
|
||||
this.summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary)
|
||||
// 开启自动换行
|
||||
if (basicStyle.autoWrap && !tableCell.mergeCells) {
|
||||
// 调整表头宽度时,计算表头高度
|
||||
@ -340,8 +290,8 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
}
|
||||
// 第一次渲染初始化,把图片字段固定为 120 进行计算
|
||||
const urlFields = fields
|
||||
.filter(field => field.deType === 7 && !axisMap[field.dataeaseName]?.hide)
|
||||
.map(f => f.dataeaseName)
|
||||
.filter(field => field.deType === 7 && !axisMap[field.gisbiName]?.hide)
|
||||
.map(f => f.gisbiName)
|
||||
const totalWidthWithImg = ev.colLeafNodes.reduce((p, n) => {
|
||||
return p + (urlFields.includes(n.field) ? 120 : n.width)
|
||||
}, 0)
|
||||
@ -386,7 +336,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
const cell = newChart.getCell(ev.target)
|
||||
const meta = cell.getMeta() as ViewMeta
|
||||
const nameIdMap = fields.reduce((pre, next) => {
|
||||
pre[next['dataeaseName']] = next['id']
|
||||
pre[next['gisbiName']] = next['id']
|
||||
return pre
|
||||
}, {})
|
||||
|
||||
@ -417,13 +367,13 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
newChart.on(S2Event.COL_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
newChart.on(S2Event.DATA_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
newChart.on(S2Event.MERGED_CELLS_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
// touch
|
||||
this.configTouchEvent(newChart, drawOption, meta)
|
||||
}
|
||||
// header resize
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev))
|
||||
// right click
|
||||
newChart.on(S2Event.GLOBAL_CONTEXT_MENU, event => copyContent(newChart, event, meta))
|
||||
// touch
|
||||
this.configTouchEvent(newChart, drawOption, meta)
|
||||
// theme
|
||||
const customTheme = this.configTheme(chart)
|
||||
newChart.setThemeCfg({ theme: customTheme })
|
||||
@ -444,6 +394,11 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
const fontStyle = tableCell.isItalic ? 'italic' : 'normal'
|
||||
const fontWeight = tableCell.isBolder === false ? 'normal' : 'bold'
|
||||
const mergeCellTheme: S2Theme = {
|
||||
dataCell: {
|
||||
cell: {
|
||||
crossBackgroundColor: tableItemBgColor
|
||||
}
|
||||
},
|
||||
mergedCell: {
|
||||
cell: {
|
||||
backgroundColor: tableItemBgColor,
|
||||
@ -488,6 +443,92 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
return theme
|
||||
}
|
||||
|
||||
protected configSummaryRowAndIndex(
|
||||
chart: Chart,
|
||||
pageInfo: PageInfo,
|
||||
s2Options: S2Options,
|
||||
s2DataConfig: S2DataConfig
|
||||
) {
|
||||
const { tableHeader, basicStyle, tableCell } = parseJson(chart.customAttr)
|
||||
const fields = chart.data?.fields ?? []
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
const { showSummary, summaryLabel } = basicStyle
|
||||
const data = s2DataConfig.data
|
||||
const xAxis = chart.xAxis
|
||||
if (showSummary && data?.length) {
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[data.length] = tableHeader.tableTitleHeight
|
||||
s2Options.style.rowCfg = { heightByField }
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1
|
||||
const axis = filter(xAxis, axis => [2, 3, 4].includes(axis.deType))
|
||||
const summaryObj = getSummaryRow(data, axis, basicStyle.seriesSummary) as any
|
||||
data.push(summaryObj)
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
// 总计行处理
|
||||
if (showSummary && viewMeta.rowIndex === data.length - 1) {
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex) {
|
||||
viewMeta.fieldValue = summaryLabel ?? t('chart.total_show')
|
||||
} else {
|
||||
// 第一列不是数值类型的,显示总计
|
||||
if (![2, 3, 4].includes(xAxis?.[0]?.deType)) {
|
||||
viewMeta.fieldValue = summaryLabel ?? t('chart.total_show')
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SummaryCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
const field = fields.find(f => f.gisbiName === viewMeta.valueField)
|
||||
if (field?.deType === 7 && chart.showPosition !== 'dialog') {
|
||||
return new ImageCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
if (tableCell.mergeCells) {
|
||||
viewMeta.fieldValue = getRowIndex(s2Options.mergedCellsInfo, viewMeta)
|
||||
} else {
|
||||
viewMeta.fieldValue =
|
||||
pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
}
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
}
|
||||
|
||||
protected summaryRowStyle(newChart: TableSheet, newData, tableCell, tableHeader, showSummary) {
|
||||
if (!showSummary || !newData.length) return
|
||||
const columns = newChart.dataCfg.fields.columns
|
||||
const showHeader = tableHeader.showTableHeader === true
|
||||
// 不显示表头时,减少一个表头的高度
|
||||
const headerAndSummaryHeight = showHeader ? getMaxTreeDepth(columns) + 1 : 1
|
||||
newChart.on(S2Event.LAYOUT_BEFORE_RENDER, () => {
|
||||
const totalHeight =
|
||||
tableHeader.tableTitleHeight * headerAndSummaryHeight +
|
||||
tableCell.tableItemHeight * (newData.length - 1)
|
||||
if (totalHeight < newChart.container.cfg.height) {
|
||||
newChart.options.height =
|
||||
totalHeight < newChart.container.cfg.height - 8 ? totalHeight + 8 : totalHeight
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super('table-info', [])
|
||||
}
|
||||
@ -508,3 +549,17 @@ function getStartPosition(node) {
|
||||
}
|
||||
return getStartPosition(node.children[0])
|
||||
}
|
||||
|
||||
function getMaxTreeDepth(nodes) {
|
||||
if (!nodes?.length) {
|
||||
return 0
|
||||
}
|
||||
return Math.max(
|
||||
...nodes.map(node => {
|
||||
if (!node.children?.length) {
|
||||
return 1
|
||||
}
|
||||
return getMaxTreeDepth(node.children) + 1
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import { formatterItem, valueFormatter } from '@/data-visualization/chart/components/js/formatter'
|
||||
import {
|
||||
configEmptyDataStyle,
|
||||
configSummaryRow,
|
||||
copyContent,
|
||||
CustomDataCell,
|
||||
getSummaryRow,
|
||||
SortTooltip,
|
||||
summaryRowStyle
|
||||
SummaryCell
|
||||
} from '@/data-visualization/chart/components/js/panel/common/common_table'
|
||||
import { S2ChartView, S2DrawOptions } from '@/data-visualization/chart/components/js/panel/types/impl/s2'
|
||||
import { parseJson } from '@/data-visualization/chart/components/js/util'
|
||||
@ -19,7 +20,7 @@ import {
|
||||
TableSheet,
|
||||
ViewMeta
|
||||
} from '@antv/s2'
|
||||
import { cloneDeep, isNumber } from 'lodash-es'
|
||||
import { isNumber } from 'lodash-es'
|
||||
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
|
||||
|
||||
const { t } = useI18n()
|
||||
@ -37,8 +38,7 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
],
|
||||
'basic-style-selector': [
|
||||
...TABLE_EDITOR_PROPERTY_INNER['basic-style-selector'],
|
||||
'showSummary',
|
||||
'summaryLabel',
|
||||
'tablePageMode',
|
||||
'showHoverStyle'
|
||||
],
|
||||
'table-cell-selector': [
|
||||
@ -46,7 +46,8 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
'tableFreeze',
|
||||
'tableColumnFreezeHead',
|
||||
'tableRowFreezeHead'
|
||||
]
|
||||
],
|
||||
'summary-selector': ['showSummary', 'summaryLabel']
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'drill', 'filter']
|
||||
axisConfig: AxisConfig = {
|
||||
@ -66,7 +67,7 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
}
|
||||
|
||||
drawChart(drawOption: S2DrawOptions<TableSheet>): TableSheet {
|
||||
const { container, chart, action, resizeAction } = drawOption
|
||||
const { container, chart, action, pageInfo, resizeAction } = drawOption
|
||||
const containerDom = document.getElementById(container)
|
||||
if (!containerDom) return
|
||||
|
||||
@ -92,18 +93,18 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
fields.splice(drillFieldIndex, 0, ...curDrillField)
|
||||
}
|
||||
const axisMap = [...chart.xAxis, ...chart.yAxis].reduce((pre, cur) => {
|
||||
pre[cur.dataeaseName] = cur
|
||||
pre[cur.gisbiName] = cur
|
||||
return pre
|
||||
}, {})
|
||||
// add drill list
|
||||
fields.forEach(ele => {
|
||||
const f = axisMap[ele.dataeaseName]
|
||||
const f = axisMap[ele.gisbiName]
|
||||
if (f?.hide === true) {
|
||||
return
|
||||
}
|
||||
columns.push(ele.dataeaseName)
|
||||
columns.push(ele.gisbiName)
|
||||
meta.push({
|
||||
field: ele.dataeaseName,
|
||||
field: ele.gisbiName,
|
||||
name: ele.chartShowName ?? ele.name,
|
||||
formatter: function (value) {
|
||||
if (!f) {
|
||||
@ -112,7 +113,7 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
if (value === null || value === undefined) {
|
||||
return value
|
||||
}
|
||||
if (![2, 3].includes(f.deType) || !isNumber(value)) {
|
||||
if (![2, 3, 4].includes(f.deType) || !isNumber(value)) {
|
||||
return value
|
||||
}
|
||||
let formatCfg = f.formatterCfg
|
||||
@ -160,19 +161,6 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
s2Options.frozenColCount = tableCell.tableColumnFreezeHead ?? 0
|
||||
s2Options.frozenRowCount = tableCell.tableRowFreezeHead ?? 0
|
||||
}
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options)
|
||||
// 隐藏表头,保留顶部的分割线, 禁用表头横向 resize
|
||||
@ -193,13 +181,12 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
chart.container = container
|
||||
this.configHeaderInteraction(chart, s2Options)
|
||||
}
|
||||
|
||||
// 总计
|
||||
configSummaryRow(chart, s2Options, newData, tableHeader, basicStyle, basicStyle.showSummary)
|
||||
// 配置总计和序号列
|
||||
this.configSummaryRowAndIndex(chart, pageInfo, s2Options, s2DataConfig)
|
||||
// 开始渲染
|
||||
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)
|
||||
// 总计紧贴在单元格后面
|
||||
summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary)
|
||||
this.summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary)
|
||||
// 自适应铺满
|
||||
if (basicStyle.tableColumnMode === 'adapt') {
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, () => {
|
||||
@ -253,7 +240,7 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
const cell = newChart.getCell(ev.target)
|
||||
const meta = cell.getMeta() as ViewMeta
|
||||
const nameIdMap = fields.reduce((pre, next) => {
|
||||
pre[next['dataeaseName']] = next['id']
|
||||
pre[next['gisbiName']] = next['id']
|
||||
return pre
|
||||
}, {})
|
||||
|
||||
@ -281,19 +268,86 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
if (show) {
|
||||
newChart.on(S2Event.COL_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
newChart.on(S2Event.DATA_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
// touch
|
||||
this.configTouchEvent(newChart, drawOption, meta)
|
||||
}
|
||||
// header resize
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev))
|
||||
// right click
|
||||
newChart.on(S2Event.GLOBAL_CONTEXT_MENU, event => copyContent(newChart, event, meta))
|
||||
// touch
|
||||
this.configTouchEvent(newChart, drawOption, meta)
|
||||
// theme
|
||||
const customTheme = this.configTheme(chart)
|
||||
newChart.setThemeCfg({ theme: customTheme })
|
||||
|
||||
return newChart
|
||||
}
|
||||
|
||||
protected configSummaryRowAndIndex(
|
||||
chart: Chart,
|
||||
pageInfo: PageInfo,
|
||||
s2Options: S2Options,
|
||||
s2DataConfig: S2DataConfig
|
||||
) {
|
||||
const { tableHeader, basicStyle } = parseJson(chart.customAttr)
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
const { showSummary, summaryLabel } = basicStyle
|
||||
const data = s2DataConfig.data
|
||||
const { xAxis, yAxis } = chart
|
||||
if (showSummary && data?.length) {
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[data.length] = tableHeader.tableTitleHeight
|
||||
s2Options.style.rowCfg = { heightByField }
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1
|
||||
const summaryObj = getSummaryRow(data, yAxis, basicStyle.seriesSummary) as any
|
||||
data.push(summaryObj)
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
// 总计行处理
|
||||
if (showSummary && viewMeta.rowIndex === data.length - 1) {
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex || xAxis?.length) {
|
||||
viewMeta.fieldValue = summaryLabel ?? t('chart.total_show')
|
||||
}
|
||||
}
|
||||
return new SummaryCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
viewMeta.fieldValue = pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
}
|
||||
|
||||
protected summaryRowStyle(newChart, newData, tableCell, tableHeader, showSummary) {
|
||||
if (!showSummary || !newData.length) return
|
||||
newChart.on(S2Event.LAYOUT_BEFORE_RENDER, () => {
|
||||
const showHeader = tableHeader.showTableHeader === true
|
||||
// 不显示表头时,减少一个表头的高度
|
||||
const headerAndSummaryHeight = showHeader ? 2 : 1
|
||||
const totalHeight =
|
||||
tableHeader.tableTitleHeight * headerAndSummaryHeight +
|
||||
tableCell.tableItemHeight * (newData.length - 1)
|
||||
if (totalHeight < newChart.container.cfg.height) {
|
||||
newChart.options.height =
|
||||
totalHeight < newChart.container.cfg.height - 8 ? totalHeight + 8 : totalHeight
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super('table-normal', [])
|
||||
}
|
||||
|
@ -13,7 +13,8 @@ import {
|
||||
TotalStatus,
|
||||
Aggregation,
|
||||
S2DataConfig,
|
||||
MergedCell
|
||||
MergedCell,
|
||||
LayoutResult
|
||||
} from '@antv/s2'
|
||||
import { formatterItem, valueFormatter } from '../../../formatter'
|
||||
import { hexColorToRGBA, isAlphaColor, parseJson } from '../../../util'
|
||||
@ -91,7 +92,8 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
'showColTooltip',
|
||||
'showRowTooltip',
|
||||
'showHorizonBorder',
|
||||
'showVerticalBorder'
|
||||
'showVerticalBorder',
|
||||
'rowHeaderFreeze'
|
||||
],
|
||||
'table-total-selector': ['row', 'col'],
|
||||
'basic-style-selector': [
|
||||
@ -100,7 +102,9 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
'tableScrollBarColor',
|
||||
'alpha',
|
||||
'tableLayoutMode',
|
||||
'showHoverStyle'
|
||||
'showHoverStyle',
|
||||
'quotaPosition',
|
||||
'quotaColLabel'
|
||||
]
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'xAxisExt', 'yAxis', 'filter']
|
||||
@ -126,7 +130,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
|
||||
const { xAxisExt: columnFields, xAxis: rowFields, yAxis: valueFields } = chart
|
||||
const [c, r, v] = [columnFields, rowFields, valueFields].map(arr =>
|
||||
arr.map(i => i.dataeaseName)
|
||||
arr.map(i => i.gisbiName)
|
||||
)
|
||||
|
||||
// fields
|
||||
@ -146,14 +150,14 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
...chart.xAxisExt,
|
||||
...chart.yAxis
|
||||
].reduce((p, n) => {
|
||||
p[n.dataeaseName] = n
|
||||
p[n.gisbiName] = n
|
||||
return p
|
||||
}, {})
|
||||
fields.forEach(ele => {
|
||||
const f = valueFieldMap[ele.dataeaseName]
|
||||
columns.push(ele.dataeaseName)
|
||||
const f = valueFieldMap[ele.gisbiName]
|
||||
columns.push(ele.gisbiName)
|
||||
meta.push({
|
||||
field: ele.dataeaseName,
|
||||
field: ele.gisbiName,
|
||||
name: ele.chartShowName ?? ele.name,
|
||||
formatter: value => {
|
||||
if (!f) {
|
||||
@ -162,7 +166,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
if (value === null || value === undefined) {
|
||||
return value
|
||||
}
|
||||
if (![2, 3].includes(f.deType) || !isNumber(value)) {
|
||||
if (![2, 3, 4].includes(f.deType) || !isNumber(value)) {
|
||||
return value
|
||||
}
|
||||
if (f.formatterCfg) {
|
||||
@ -175,7 +179,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
})
|
||||
|
||||
// total config
|
||||
const { basicStyle, tooltip, tableTotal } = parseJson(chart.customAttr)
|
||||
const { basicStyle, tooltip, tableTotal, tableHeader } = parseJson(chart.customAttr)
|
||||
if (!tableTotal.row.subTotalsDimensionsNew || tableTotal.row.subTotalsDimensions == undefined) {
|
||||
tableTotal.row.subTotalsDimensions = r
|
||||
}
|
||||
@ -183,6 +187,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
|
||||
// 解析合计、小计排序
|
||||
const sortParams = []
|
||||
let rowTotalSort = false
|
||||
if (
|
||||
tableTotal.row.totalSort &&
|
||||
tableTotal.row.totalSort !== 'none' &&
|
||||
@ -190,16 +195,20 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
tableTotal.row.showGrandTotals &&
|
||||
v.indexOf(tableTotal.row.totalSortField) > -1
|
||||
) {
|
||||
const sort = {
|
||||
sortFieldId: c[0],
|
||||
sortMethod: tableTotal.row.totalSort.toUpperCase(),
|
||||
sortByMeasure: TOTAL_VALUE,
|
||||
query: {
|
||||
[EXTRA_FIELD]: tableTotal.row.totalSortField
|
||||
c.forEach(i => {
|
||||
const sort = {
|
||||
sortFieldId: i,
|
||||
sortMethod: tableTotal.row.totalSort.toUpperCase(),
|
||||
sortByMeasure: TOTAL_VALUE,
|
||||
query: {
|
||||
[EXTRA_FIELD]: tableTotal.row.totalSortField
|
||||
}
|
||||
}
|
||||
}
|
||||
sortParams.push(sort)
|
||||
sortParams.push(sort)
|
||||
})
|
||||
rowTotalSort = true
|
||||
}
|
||||
let colTotalSort = false
|
||||
if (
|
||||
tableTotal.col.totalSort &&
|
||||
tableTotal.col.totalSort !== 'none' &&
|
||||
@ -207,15 +216,18 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
tableTotal.col.showGrandTotals &&
|
||||
v.indexOf(tableTotal.col.totalSortField) > -1
|
||||
) {
|
||||
const sort = {
|
||||
sortFieldId: r[0],
|
||||
sortMethod: tableTotal.col.totalSort.toUpperCase(),
|
||||
sortByMeasure: TOTAL_VALUE,
|
||||
query: {
|
||||
[EXTRA_FIELD]: tableTotal.col.totalSortField
|
||||
r.forEach(i => {
|
||||
const sort = {
|
||||
sortFieldId: i,
|
||||
sortMethod: tableTotal.col.totalSort.toUpperCase(),
|
||||
sortByMeasure: TOTAL_VALUE,
|
||||
query: {
|
||||
[EXTRA_FIELD]: tableTotal.col.totalSortField
|
||||
}
|
||||
}
|
||||
}
|
||||
sortParams.push(sort)
|
||||
sortParams.push(sort)
|
||||
})
|
||||
colTotalSort = true
|
||||
}
|
||||
//列维度为空,行排序按照指标列来排序,取第一个有排序设置的指标
|
||||
if (!columnFields?.length) {
|
||||
@ -226,7 +238,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
sortMethod: sortField.sort.toUpperCase(),
|
||||
sortByMeasure: TOTAL_VALUE,
|
||||
query: {
|
||||
[EXTRA_FIELD]: sortField.dataeaseName
|
||||
[EXTRA_FIELD]: sortField.gisbiName
|
||||
}
|
||||
}
|
||||
sortParams.push(sort)
|
||||
@ -244,15 +256,29 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
col: chart.xAxisExt,
|
||||
quota: chart.yAxis
|
||||
}
|
||||
//树形模式下,列维度为空,行小计会变成列总计,特殊处理下
|
||||
if (basicStyle.tableLayoutMode === 'tree' && !chart.xAxisExt?.length) {
|
||||
tableTotal.col.calcTotals = tableTotal.row.calcSubTotals
|
||||
// 沒有列维度需要特殊处理
|
||||
if (!chart.xAxisExt?.length) {
|
||||
//树形模式下,列维度为空,行小计的配置会变成列总计
|
||||
if (basicStyle.tableLayoutMode === 'tree') {
|
||||
tableTotal.col.calcTotals = tableTotal.row.calcSubTotals
|
||||
if (!tableTotal.col.calcTotals.cfg?.length) {
|
||||
tableTotal.col.calcTotals.cfg = chart.yAxis.map(y => {
|
||||
return {
|
||||
gisbiName: y.gisbiName,
|
||||
aggregation: 'SUM'
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 列总计设置为空
|
||||
tableTotal.col.calcTotals.calcFunc = () => '-'
|
||||
}
|
||||
}
|
||||
totals.forEach(total => {
|
||||
if (total.cfg?.length) {
|
||||
delete total.aggregation
|
||||
const totalCfgMap = total.cfg.reduce((p, n) => {
|
||||
p[n.dataeaseName] = n
|
||||
p[n.gisbiName] = n
|
||||
return p
|
||||
}, {})
|
||||
total.calcFunc = (query, data, _, status) => {
|
||||
@ -262,12 +288,93 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
})
|
||||
// 空值处理
|
||||
const newData = this.configEmptyDataStrategy(chart)
|
||||
// 行列维度排序
|
||||
if (!rowTotalSort) {
|
||||
c?.forEach((f, i) => {
|
||||
if (valueFieldMap[f]?.sort === 'none') {
|
||||
return
|
||||
}
|
||||
const sort = {
|
||||
sortFieldId: f
|
||||
}
|
||||
const sortMethod = valueFieldMap[f]?.sort?.toUpperCase()
|
||||
if (sortMethod === 'CUSTOM_SORT') {
|
||||
sort.sortBy = valueFieldMap[f].customSort
|
||||
} else {
|
||||
if (i === 0) {
|
||||
sort.sortMethod = sortMethod
|
||||
} else {
|
||||
const fieldValues = newData.map(item => item[f])
|
||||
const uniqueValues = [...new Set(fieldValues)]
|
||||
|
||||
// 根据配置动态决定排序顺序
|
||||
uniqueValues.sort((a, b) => {
|
||||
if ([2, 3, 4].includes(valueFieldMap[f]?.deType)) {
|
||||
return sortMethod === 'ASC' ? a - b : b - a
|
||||
}
|
||||
if (!a && !b) {
|
||||
return 0
|
||||
}
|
||||
if (!a) {
|
||||
return sortMethod === 'ASC' ? -1 : 1
|
||||
}
|
||||
if (!b) {
|
||||
return sortMethod === 'ASC' ? 1 : -1
|
||||
}
|
||||
return sortMethod === 'ASC' ? a.localeCompare(b) : b.localeCompare(a)
|
||||
})
|
||||
sort.sortBy = uniqueValues
|
||||
}
|
||||
}
|
||||
sortParams.push(sort)
|
||||
})
|
||||
}
|
||||
if (!colTotalSort) {
|
||||
r?.forEach((f, i) => {
|
||||
if (valueFieldMap[f]?.sort === 'none') {
|
||||
return
|
||||
}
|
||||
const sort = {
|
||||
sortFieldId: f
|
||||
}
|
||||
const sortMethod = valueFieldMap[f]?.sort?.toUpperCase()
|
||||
if (sortMethod === 'CUSTOM_SORT') {
|
||||
sort.sortBy = valueFieldMap[f].customSort
|
||||
} else {
|
||||
if (i === 0) {
|
||||
sort.sortMethod = sortMethod
|
||||
} else {
|
||||
const fieldValues = newData.map(item => item[f])
|
||||
const uniqueValues = [...new Set(fieldValues)]
|
||||
// 根据配置动态决定排序顺序
|
||||
uniqueValues.sort((a, b) => {
|
||||
if ([2, 3, 4].includes(valueFieldMap[f]?.deType)) {
|
||||
return sortMethod === 'ASC' ? a - b : b - a
|
||||
}
|
||||
if (!a && !b) {
|
||||
return 0
|
||||
}
|
||||
if (!a) {
|
||||
return sortMethod === 'ASC' ? -1 : 1
|
||||
}
|
||||
if (!b) {
|
||||
return sortMethod === 'ASC' ? 1 : -1
|
||||
}
|
||||
return sortMethod === 'ASC' ? a.localeCompare(b) : b.localeCompare(a)
|
||||
})
|
||||
sort.sortBy = uniqueValues
|
||||
}
|
||||
}
|
||||
sortParams.push(sort)
|
||||
})
|
||||
}
|
||||
// data config
|
||||
const s2DataConfig: S2DataConfig = {
|
||||
fields: {
|
||||
rows: r,
|
||||
columns: c,
|
||||
values: v
|
||||
values: v,
|
||||
valueInCols: !(basicStyle.quotaPosition === 'row')
|
||||
},
|
||||
meta: meta,
|
||||
data: newData,
|
||||
@ -277,6 +384,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
width: containerDom.offsetWidth,
|
||||
height: containerDom.offsetHeight,
|
||||
totals: tableTotal as Totals,
|
||||
cornerExtraFieldText: basicStyle.quotaColLabel ?? t('dataset.value'),
|
||||
conditions: this.configConditions(chart),
|
||||
tooltip: {
|
||||
getContainer: () => containerDom
|
||||
@ -288,21 +396,204 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
},
|
||||
dataCell: meta => {
|
||||
return new CustomDataCell(meta, meta.spreadsheet)
|
||||
}
|
||||
},
|
||||
frozenRowHeader: !(tableHeader.rowHeaderFreeze === false)
|
||||
}
|
||||
// options
|
||||
s2Options.style = this.configStyle(chart, s2DataConfig)
|
||||
s2Options.style.hierarchyCollapse = true
|
||||
// 默认展开层级
|
||||
if (basicStyle.tableLayoutMode === 'tree') {
|
||||
const { defaultExpandLevel } = basicStyle
|
||||
if (isNumber(defaultExpandLevel)) {
|
||||
if (defaultExpandLevel >= chart.xAxis.length) {
|
||||
s2Options.style.rowExpandDepth = defaultExpandLevel
|
||||
} else {
|
||||
s2Options.style.rowExpandDepth = defaultExpandLevel - 2
|
||||
}
|
||||
}
|
||||
if (defaultExpandLevel === 'all') {
|
||||
s2Options.style.rowExpandDepth = chart.xAxis.length
|
||||
}
|
||||
if (!defaultExpandLevel) {
|
||||
s2Options.style.hierarchyCollapse = true
|
||||
}
|
||||
}
|
||||
// 列汇总别名
|
||||
if (!(basicStyle.quotaPosition === 'row' && basicStyle.tableLayoutMode === 'tree')) {
|
||||
if (
|
||||
basicStyle.quotaPosition !== 'row' &&
|
||||
chart.xAxisExt?.length &&
|
||||
chart.yAxis?.length > 1 &&
|
||||
tableTotal.col.showGrandTotals &&
|
||||
tableTotal.col.calcTotals?.cfg?.length
|
||||
) {
|
||||
const colTotalCfgMap = tableTotal.col.calcTotals.cfg.reduce((p, n) => {
|
||||
p[n.gisbiName] = n
|
||||
return p
|
||||
}, {})
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col?.isGrandTotals) {
|
||||
if (colTotalCfgMap[col.value]?.label) {
|
||||
col.label = colTotalCfgMap[col.value].label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
basicStyle.quotaPosition === 'row' &&
|
||||
chart.xAxisExt?.length &&
|
||||
chart.yAxis?.length > 1 &&
|
||||
tableTotal.row.showGrandTotals &&
|
||||
tableTotal.row.calcTotals?.cfg?.length
|
||||
) {
|
||||
const rowTotalCfgMap = tableTotal.row.calcTotals.cfg.reduce((p, n) => {
|
||||
p[n.gisbiName] = n
|
||||
return p
|
||||
}, {})
|
||||
// eslint-disable-next-line
|
||||
s2Options.layoutCoordinate = (_, row, __) => {
|
||||
if (row?.isGrandTotals) {
|
||||
if (rowTotalCfgMap[row.value]?.label) {
|
||||
row.label = rowTotalCfgMap[row.value].label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options)
|
||||
// 开始渲染
|
||||
const s2 = new PivotSheet(containerDom, s2DataConfig, s2Options as unknown as S2Options)
|
||||
// 自适应铺满
|
||||
if (basicStyle.tableColumnMode === 'adapt') {
|
||||
s2.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, () => {
|
||||
s2.store.set('lastLayoutResult', s2.facet.layoutResult)
|
||||
})
|
||||
// 平铺模式行头resize
|
||||
s2.on(S2Event.LAYOUT_RESIZE_ROW_WIDTH, () => {
|
||||
s2.store.set('lastLayoutResult', s2.facet.layoutResult)
|
||||
})
|
||||
// 树形模式行头resize
|
||||
s2.on(S2Event.LAYOUT_RESIZE_TREE_WIDTH, () => {
|
||||
s2.store.set('lastLayoutResult', s2.facet.layoutResult)
|
||||
})
|
||||
s2.on(S2Event.LAYOUT_AFTER_HEADER_LAYOUT, (ev: LayoutResult) => {
|
||||
const lastLayoutResult = s2.store.get('lastLayoutResult') as LayoutResult
|
||||
if (lastLayoutResult) {
|
||||
// 拖动 col 表头 resize
|
||||
const colWidthByFieldValue = s2.options.style?.colCfg?.widthByFieldValue
|
||||
// 平铺模式拖动 row 表头 resize
|
||||
const rowWidthByField = s2.options.style?.rowCfg?.widthByField
|
||||
// 树形模式拖动 row 表头 resize
|
||||
const treeRowWidth =
|
||||
s2.options.style?.treeRowsWidth || lastLayoutResult.rowsHierarchy.width
|
||||
const colWidthMap =
|
||||
lastLayoutResult.colLeafNodes.reduce((p, n) => {
|
||||
p[n.id] = colWidthByFieldValue?.[n.value] ?? n.width
|
||||
return p
|
||||
}, {}) || {}
|
||||
const totalColWidth = ev.colLeafNodes.reduce((p, n) => {
|
||||
n.width = colWidthMap[n.id] || n.width
|
||||
n.x = p
|
||||
return p + n.width
|
||||
}, 0)
|
||||
ev.colNodes.forEach(n => {
|
||||
if (n.isLeaf) {
|
||||
return
|
||||
}
|
||||
n.width = this.getColWidth(n)
|
||||
n.x = this.getLeftChild(n).x
|
||||
})
|
||||
if (basicStyle.tableLayoutMode === 'tree') {
|
||||
ev.rowNodes.forEach(n => {
|
||||
n.width = treeRowWidth
|
||||
})
|
||||
ev.rowsHierarchy.width = treeRowWidth
|
||||
ev.colsHierarchy.width = totalColWidth
|
||||
} else {
|
||||
const rowWidthMap =
|
||||
lastLayoutResult.rowNodes.reduce((p, n) => {
|
||||
p[n.id] = rowWidthByField?.[n.field] ?? n.width
|
||||
return p
|
||||
}, {}) || {}
|
||||
ev.rowNodes.forEach(n => {
|
||||
n.x = 0
|
||||
n.width = rowWidthMap[n.id] || n.width
|
||||
let tmp = n
|
||||
while (tmp.parent.id !== 'root') {
|
||||
n.x += tmp.parent.width
|
||||
tmp = tmp.parent
|
||||
}
|
||||
})
|
||||
const totlaRowWidth = ev.rowsHierarchy.sampleNodesForAllLevels.reduce((p, n) => {
|
||||
return p + n.width
|
||||
}, 0)
|
||||
const maxRowLevel = ev.rowsHierarchy.maxLevel
|
||||
ev.rowNodes.forEach(n => {
|
||||
// 总计和中间层级的小计需要重新计算宽度
|
||||
if (n.isTotalRoot || (n.isSubTotals && n.level < maxRowLevel)) {
|
||||
let width = 0
|
||||
for (let i = n.level; i <= maxRowLevel; i++) {
|
||||
width += ev.rowsHierarchy.sampleNodesForAllLevels[i].width
|
||||
}
|
||||
n.width = width
|
||||
}
|
||||
})
|
||||
ev.rowsHierarchy.width = totlaRowWidth
|
||||
ev.colsHierarchy.width = totalColWidth
|
||||
}
|
||||
s2.store.set('lastLayoutResult', undefined)
|
||||
return
|
||||
}
|
||||
const containerWidth = containerDom.getBoundingClientRect().width
|
||||
const scale = containerWidth / (ev.colsHierarchy.width + ev.rowsHierarchy.width)
|
||||
if (scale <= 1) {
|
||||
return
|
||||
}
|
||||
const totalRowWidth = Math.round(ev.rowsHierarchy.width * scale)
|
||||
ev.rowNodes.forEach(n => {
|
||||
n.width = Math.round(n.width * scale)
|
||||
})
|
||||
if (basicStyle.tableLayoutMode !== 'tree') {
|
||||
ev.rowNodes.forEach(n => {
|
||||
n.x = 0
|
||||
let tmp = n
|
||||
while (tmp.parent.id !== 'root') {
|
||||
n.x += tmp.parent.width
|
||||
tmp = tmp.parent
|
||||
}
|
||||
})
|
||||
}
|
||||
let totalColWidth = ev.colLeafNodes.reduce((p, n) => {
|
||||
n.width = Math.round(n.width * scale)
|
||||
n.x = p
|
||||
return p + n.width
|
||||
}, 0)
|
||||
ev.colNodes.forEach(n => {
|
||||
if (n.isLeaf) {
|
||||
return
|
||||
}
|
||||
n.width = this.getColWidth(n)
|
||||
n.x = this.getLeftChild(n).x
|
||||
})
|
||||
const totalWidth = totalColWidth + totalRowWidth
|
||||
if (totalWidth > containerWidth) {
|
||||
// 从最后一列减掉
|
||||
ev.colLeafNodes[ev.colLeafNodes.length - 1].width -= totalWidth - containerWidth
|
||||
totalColWidth = totalColWidth - (totalWidth - containerWidth)
|
||||
}
|
||||
ev.colsHierarchy.width = totalColWidth
|
||||
ev.rowsHierarchy.width = totalRowWidth
|
||||
})
|
||||
}
|
||||
// tooltip
|
||||
const { show } = tooltip
|
||||
if (show) {
|
||||
s2.on(S2Event.COL_CELL_HOVER, event => this.showTooltip(s2, event, meta))
|
||||
s2.on(S2Event.ROW_CELL_HOVER, event => this.showTooltip(s2, event, meta))
|
||||
s2.on(S2Event.DATA_CELL_HOVER, event => this.showTooltip(s2, event, meta))
|
||||
// touch
|
||||
this.configTouchEvent(s2, drawOption, meta)
|
||||
}
|
||||
// empty data tip
|
||||
configEmptyDataStyle(s2, newData)
|
||||
@ -312,19 +603,34 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
s2.on(S2Event.COL_CELL_CLICK, ev => this.headerCellClickAction(chart, ev, s2, action))
|
||||
// right click
|
||||
s2.on(S2Event.GLOBAL_CONTEXT_MENU, event => copyContent(s2, event, meta))
|
||||
// touch
|
||||
this.configTouchEvent(s2, drawOption, meta)
|
||||
// theme
|
||||
const customTheme = this.configTheme(chart)
|
||||
s2.setThemeCfg({ theme: customTheme })
|
||||
|
||||
return s2
|
||||
}
|
||||
private getColWidth(node) {
|
||||
let width = 0
|
||||
if (node.children?.length) {
|
||||
node.children.forEach(child => {
|
||||
width += this.getColWidth(child)
|
||||
})
|
||||
} else {
|
||||
width = node.width
|
||||
}
|
||||
return width
|
||||
}
|
||||
private getLeftChild(node) {
|
||||
if (!node.children?.length) {
|
||||
return node
|
||||
}
|
||||
return this.getLeftChild(node.children[0])
|
||||
}
|
||||
private dataCellClickAction(chart: Chart, ev, s2Instance: PivotSheet, callback) {
|
||||
const cell = s2Instance.getCell(ev.target)
|
||||
const meta = cell.getMeta()
|
||||
const nameIdMap = chart.data.fields.reduce((pre, next) => {
|
||||
pre[next['dataeaseName']] = next['id']
|
||||
pre[next['gisbiName']] = next['id']
|
||||
return pre
|
||||
}, {})
|
||||
const rowData = { ...meta.rowQuery, ...meta.colQuery }
|
||||
@ -352,7 +658,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
const meta = cell.getMeta()
|
||||
const rowData = meta.query
|
||||
const nameIdMap = chart.data.fields.reduce((pre, next) => {
|
||||
pre[next['dataeaseName']] = next['id']
|
||||
pre[next['gisbiName']] = next['id']
|
||||
return pre
|
||||
}, {})
|
||||
const dimensionList = []
|
||||
@ -522,7 +828,7 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
}
|
||||
function customCalcFunc(query, data, status, chart, totalCfgMap, axisMap, customCalc) {
|
||||
if (!data?.length || !query[EXTRA_FIELD]) {
|
||||
return 0
|
||||
return '-'
|
||||
}
|
||||
const aggregation = totalCfgMap[query[EXTRA_FIELD]]?.aggregation || 'SUM'
|
||||
switch (aggregation) {
|
||||
@ -549,10 +855,13 @@ function customCalcFunc(query, data, status, chart, totalCfgMap, axisMap, custom
|
||||
})
|
||||
return result?.[query[EXTRA_FIELD]]
|
||||
}
|
||||
case 'NONE': {
|
||||
return '-'
|
||||
}
|
||||
case 'CUSTOM': {
|
||||
const val = getCustomCalcResult(query, axisMap, chart, status, customCalc || {})
|
||||
if (val === '') {
|
||||
return val
|
||||
if (val === '' || val === undefined) {
|
||||
return '-'
|
||||
}
|
||||
return parseFloat(val)
|
||||
}
|
||||
@ -593,11 +902,17 @@ function getTreeCustomCalcResult(query, axisMap, status: TotalStatus, customCalc
|
||||
// 列小计
|
||||
if (status.isColSubTotal && !status.isRowTotal && !status.isRowSubTotal) {
|
||||
const { colSubTotal } = customCalc
|
||||
const subLevel = getSubLevel(query, col)
|
||||
const subColLevel = getSubLevel(query, col)
|
||||
const subRowLevel = getSubLevel(query, row)
|
||||
const rowPath = getTreePath(query, row)
|
||||
const colPath = getTreePath(query, col)
|
||||
const path = [...rowPath, ...colPath]
|
||||
const data = colSubTotal?.[subLevel]?.data
|
||||
let data = colSubTotal?.[subColLevel]?.data
|
||||
// 列小计里面的行小计
|
||||
if (rowPath.length < row.length) {
|
||||
const { rowSubInColSub } = customCalc
|
||||
data = rowSubInColSub?.[subRowLevel]?.[subColLevel]?.data
|
||||
}
|
||||
let val
|
||||
if (path.length && data) {
|
||||
path.push(quotaField)
|
||||
@ -647,7 +962,7 @@ function getTreeCustomCalcResult(query, axisMap, status: TotalStatus, customCalc
|
||||
if (status.isRowTotal && status.isColSubTotal) {
|
||||
const { colSubInRowTotal } = customCalc
|
||||
const colLevel = getSubLevel(query, col)
|
||||
const { data } = colSubInRowTotal?.[colLevel]
|
||||
const data = colSubInRowTotal?.[colLevel]?.data
|
||||
const colPath = getTreePath(query, col)
|
||||
let val
|
||||
if (colPath.length && colSubInRowTotal) {
|
||||
@ -669,23 +984,7 @@ function getTreeCustomCalcResult(query, axisMap, status: TotalStatus, customCalc
|
||||
}
|
||||
return val
|
||||
}
|
||||
// 列小计里面的行小计
|
||||
if (status.isColSubTotal && status.isRowSubTotal) {
|
||||
const { rowSubInColSub } = customCalc
|
||||
const rowSubLevel = getSubLevel(query, row)
|
||||
const colSubLevel = getSubLevel(query, col)
|
||||
const data = rowSubInColSub?.[rowSubLevel]?.[colSubLevel]?.data
|
||||
const rowPath = getTreePath(query, row)
|
||||
const colPath = getTreePath(query, col)
|
||||
const path = [...rowPath, ...colPath]
|
||||
let val
|
||||
if (path.length && rowSubInColSub) {
|
||||
path.push(quotaField)
|
||||
val = get(data, path)
|
||||
}
|
||||
return val
|
||||
}
|
||||
return NaN
|
||||
return '-'
|
||||
}
|
||||
|
||||
function getGridCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
@ -759,7 +1058,7 @@ function getGridCustomCalcResult(query, axisMap, status: TotalStatus, customCalc
|
||||
if (status.isRowTotal && status.isColSubTotal) {
|
||||
const { colSubInRowTotal } = customCalc
|
||||
const colLevel = getSubLevel(query, col)
|
||||
const { data } = colSubInRowTotal?.[colLevel]
|
||||
const data = colSubInRowTotal?.[colLevel]?.data
|
||||
const colPath = getTreePath(query, col)
|
||||
let val
|
||||
if (colPath.length && colSubInRowTotal) {
|
||||
@ -807,7 +1106,7 @@ function getCustomCalcResult(query, axisMap, chart: ChartObj, status: TotalStatu
|
||||
}
|
||||
|
||||
function getSubLevel(query, axis) {
|
||||
const fields: [] = axis.map(a => a.dataeaseName)
|
||||
const fields: [] = axis.map(a => a.gisbiName)
|
||||
let subLevel = -1
|
||||
const queryFields = keys(query)
|
||||
for (let i = fields.length - 1; i >= 0; i--) {
|
||||
@ -824,9 +1123,9 @@ function getTreePath(query, axis) {
|
||||
const path = []
|
||||
const fields = keys(query)
|
||||
axis.forEach(a => {
|
||||
const index = fields.findIndex(f => f === a.dataeaseName)
|
||||
const index = fields.findIndex(f => f === a.gisbiName)
|
||||
if (index !== -1) {
|
||||
path.push(query[a.dataeaseName])
|
||||
path.push(query[a.gisbiName])
|
||||
}
|
||||
})
|
||||
return path
|
||||
|
@ -33,10 +33,23 @@ import { PositionType } from '@antv/l7-core'
|
||||
import { centroid } from '@turf/centroid'
|
||||
import type { Plot } from '@antv/g2plot'
|
||||
import type { PickOptions } from '@antv/g2plot/lib/core/plot'
|
||||
import { defaults } from 'lodash-es'
|
||||
import { defaults, find } from 'lodash-es'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
const { t: tI18n } = useI18n()
|
||||
import { isMobile } from '@/data-visualization/utils/utils'
|
||||
import { GaodeMap, TMap, TencentMap } from '@antv/l7-maps'
|
||||
import {
|
||||
gaodeMapStyleOptions,
|
||||
qqMapStyleOptions,
|
||||
tdtMapStyleOptions
|
||||
} from '@/data-visualization/chart/components/js/panel/charts/map/common'
|
||||
import ChartCarouselTooltip, {
|
||||
isPie,
|
||||
isColumn,
|
||||
isMix,
|
||||
isSupport
|
||||
} from '@/data-visualization/chart/components/js/g2plot_tooltip_carousel'
|
||||
|
||||
const { t: tI18n } = useI18n()
|
||||
|
||||
export function getPadding(chart: Chart): number[] {
|
||||
if (chart.drill) {
|
||||
@ -137,14 +150,22 @@ export function getTheme(chart: Chart) {
|
||||
},
|
||||
'g2-tooltip-list-item': {
|
||||
display: 'flex',
|
||||
'align-items': 'center'
|
||||
'align-items': 'flex-start',
|
||||
'justify-content': 'space-between',
|
||||
'line-height': tooltipFontsize + 'px'
|
||||
},
|
||||
'g2-tooltip-name': {
|
||||
display: 'inline-block',
|
||||
'line-height': tooltipFontsize + 'px',
|
||||
flex: 1
|
||||
'line-height': tooltipFontsize + 'px'
|
||||
},
|
||||
'g2-tooltip-value': {
|
||||
flex: 1,
|
||||
display: 'inline-block',
|
||||
'text-align': 'end',
|
||||
'line-height': tooltipFontsize + 'px'
|
||||
},
|
||||
'g2-tooltip-marker': {
|
||||
'margin-top': (tooltipFontsize - 8) / 2 + 'px',
|
||||
'min-width': '8px',
|
||||
'min-height': '8px'
|
||||
}
|
||||
@ -469,7 +490,8 @@ export function getXAxis(chart: Chart) {
|
||||
style: {
|
||||
fill: a.axisLabel.color,
|
||||
fontSize: a.axisLabel.fontSize,
|
||||
textAlign: textAlign
|
||||
textAlign: textAlign,
|
||||
fontFamily: chart.fontFamily
|
||||
},
|
||||
formatter: value => {
|
||||
return chart.type === 'bidirectional-bar' && value.length > a.axisLabel.lengthLimit
|
||||
@ -574,7 +596,8 @@ export function getYAxis(chart: Chart) {
|
||||
fill: yAxis.axisLabel.color,
|
||||
fontSize: yAxis.axisLabel.fontSize,
|
||||
textBaseline,
|
||||
textAlign
|
||||
textAlign,
|
||||
fontFamily: chart.fontFamily
|
||||
},
|
||||
formatter: value => {
|
||||
return value.length > yAxis.axisLabel.lengthLimit
|
||||
@ -603,7 +626,7 @@ export function getYAxisExt(chart: Chart) {
|
||||
return false
|
||||
}
|
||||
const title =
|
||||
yAxis.name && yAxis.name !== ''
|
||||
yAxis.nameShow && yAxis.name && yAxis.name !== ''
|
||||
? {
|
||||
text: yAxis.name,
|
||||
style: {
|
||||
@ -629,14 +652,16 @@ export function getYAxisExt(chart: Chart) {
|
||||
? {
|
||||
style: {
|
||||
stroke: axisCfg.lineStyle.color,
|
||||
lineWidth: axisCfg.lineStyle.width
|
||||
lineWidth: axisCfg.lineStyle.width,
|
||||
lineDash: getLineDash(axisCfg.lineStyle.style)
|
||||
}
|
||||
}
|
||||
: null
|
||||
const tickLine = axisCfg.show
|
||||
? {
|
||||
style: {
|
||||
stroke: axisCfg.lineStyle.color
|
||||
stroke: axisCfg.lineStyle.color,
|
||||
lineWidth: axisCfg.lineStyle.width
|
||||
}
|
||||
}
|
||||
: null
|
||||
@ -673,7 +698,8 @@ export function getYAxisExt(chart: Chart) {
|
||||
fill: yAxis.axisLabel.color,
|
||||
fontSize: yAxis.axisLabel.fontSize,
|
||||
textBaseline,
|
||||
textAlign
|
||||
textAlign,
|
||||
fontFamily: chart.fontFamily
|
||||
}
|
||||
}
|
||||
: null
|
||||
@ -821,10 +847,9 @@ export function getAnalyseHorizontal(chart: Chart) {
|
||||
const assistLineArr = senior.assistLineCfg.assistLine
|
||||
if (assistLineArr?.length > 0) {
|
||||
const customStyle = parseJson(chart.customStyle)
|
||||
let xAxisPosition, axisFormatterCfg
|
||||
let axisFormatterCfg
|
||||
if (customStyle.xAxis) {
|
||||
const a = JSON.parse(JSON.stringify(customStyle.xAxis))
|
||||
xAxisPosition = transAxisPosition(a.position)
|
||||
axisFormatterCfg = a.axisLabelFormatter
|
||||
? a.axisLabelFormatter
|
||||
: DEFAULT_XAXIS_STYLE.axisLabelFormatter
|
||||
@ -894,7 +919,9 @@ export function getLineDash(type) {
|
||||
*/
|
||||
export function setGradientColor(rawColor: string, show = false, angle = 0, start = 0) {
|
||||
const item = rawColor.split(',')
|
||||
item.splice(3, 1, '0.3)')
|
||||
const alpha = parseFloat(item[3].replace(')', ''))
|
||||
const startAlpha = alpha * 0.3
|
||||
item.splice(3, 1, `${startAlpha})`)
|
||||
let color: string
|
||||
if (start == 0) {
|
||||
color = `l(${angle}) 0:${item.join(',')} 1:${rawColor}`
|
||||
@ -993,6 +1020,9 @@ export function configL7Tooltip(chart: Chart): TooltipOptions {
|
||||
return result
|
||||
}
|
||||
const head = originalItem.properties
|
||||
if (!head) {
|
||||
return result
|
||||
}
|
||||
const formatter = formatterMap[head.quotaList?.[0]?.id]
|
||||
if (!isEmpty(formatter)) {
|
||||
const originValue = parseFloat(head.value as string)
|
||||
@ -1152,13 +1182,27 @@ export class CustomZoom extends Zoom {
|
||||
'l7-button-control',
|
||||
container,
|
||||
() => {
|
||||
if (this.controlOption['bounds']) {
|
||||
this.mapsService.fitBounds(this.controlOption['bounds'], { animate: true })
|
||||
if (this.mapsService.map?.deMapProvider == 'qq') {
|
||||
if (this.mapsService.map.deMapAutoFit) {
|
||||
this.mapsService.setZoomAndCenter(this.mapsService.map.deMapAutoZoom, [
|
||||
this.mapsService.map.deMapAutoLng,
|
||||
this.mapsService.map.deMapAutoLat
|
||||
])
|
||||
} else {
|
||||
this.mapsService.setZoomAndCenter(
|
||||
this.controlOption['initZoom'],
|
||||
this.controlOption['center']
|
||||
)
|
||||
}
|
||||
} else {
|
||||
this.mapsService.setZoomAndCenter(
|
||||
this.controlOption['initZoom'],
|
||||
this.controlOption['center']
|
||||
)
|
||||
if (this.controlOption['bounds']) {
|
||||
this.mapsService.fitBounds(this.controlOption['bounds'], { animate: true })
|
||||
} else {
|
||||
this.mapsService.setZoomAndCenter(
|
||||
this.controlOption['initZoom'],
|
||||
this.controlOption['center']
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -1208,7 +1252,11 @@ export class CustomZoom extends Zoom {
|
||||
} as IZoomControlOption
|
||||
}
|
||||
}
|
||||
export function configL7Zoom(chart: Chart, scene: Scene) {
|
||||
export function configL7Zoom(
|
||||
chart: Chart,
|
||||
scene: Scene,
|
||||
mapKey?: { key: string; securityCode: string; mapType: string }
|
||||
) {
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
const zoomOption = scene?.getControlByName('zoom')
|
||||
if (zoomOption) {
|
||||
@ -1220,20 +1268,56 @@ export function configL7Zoom(chart: Chart, scene: Scene) {
|
||||
if (!scene?.getControlByName('zoom')) {
|
||||
if (!scene.map) {
|
||||
scene.once('loaded', () => {
|
||||
scene.map.on('complete', () => {
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().lng, scene.map.getCenter().lat]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
})
|
||||
switch (mapKey?.mapType) {
|
||||
case 'tianditu':
|
||||
//天地图
|
||||
{
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().getLng(), scene.map.getCenter().getLat()]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
}
|
||||
break
|
||||
case 'qq':
|
||||
{
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().lng, scene.map.getCenter().lat]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
}
|
||||
break
|
||||
default:
|
||||
scene.map.on('complete', () => {
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().lng, scene.map.getCenter().lat]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const newZoomOptions = {
|
||||
@ -1250,19 +1334,19 @@ export function configL7Zoom(chart: Chart, scene: Scene) {
|
||||
const endAxis = chart.xAxisExt
|
||||
if (startAxis?.length === 2) {
|
||||
chart.data?.tableRow?.forEach(row => {
|
||||
coordinates.push([row[startAxis[0].dataeaseName], row[startAxis[1].dataeaseName]])
|
||||
coordinates.push([row[startAxis[0].gisbiName], row[startAxis[1].gisbiName]])
|
||||
})
|
||||
}
|
||||
if (endAxis?.length === 2) {
|
||||
chart.data?.tableRow?.forEach(row => {
|
||||
coordinates.push([row[endAxis[0].dataeaseName], row[endAxis[1].dataeaseName]])
|
||||
coordinates.push([row[endAxis[0].gisbiName], row[endAxis[1].gisbiName]])
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const axis = chart.xAxis
|
||||
if (axis?.length === 2) {
|
||||
chart.data?.tableRow?.forEach(row => {
|
||||
coordinates.push([row[axis[0].dataeaseName], row[axis[1].dataeaseName]])
|
||||
coordinates.push([row[axis[0].gisbiName], row[axis[1].gisbiName]])
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1335,6 +1419,18 @@ export function mapRendering(dom: HTMLElement | string) {
|
||||
dom.classList.add('de-map-rendering')
|
||||
}
|
||||
|
||||
export function qqMapRendered(scene?: Scene) {
|
||||
if (scene?.map && scene.map.deMapProvider === 'qq') {
|
||||
setTimeout(() => {
|
||||
if (scene.map) {
|
||||
scene.map.deMapAutoZoom = scene.map.getZoom()
|
||||
scene.map.deMapAutoLng = scene.map.getCenter().getLng()
|
||||
scene.map.deMapAutoLat = scene.map.getCenter().getLat()
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
export function mapRendered(dom: HTMLElement | string) {
|
||||
if (typeof dom === 'string') {
|
||||
dom = document.getElementById(dom)
|
||||
@ -1342,6 +1438,213 @@ export function mapRendered(dom: HTMLElement | string) {
|
||||
dom.classList.add('de-map-rendered')
|
||||
}
|
||||
|
||||
export function getMapCenter(basicStyle: ChartBasicStyle) {
|
||||
let center: [number, number]
|
||||
if (basicStyle.autoFit === false) {
|
||||
const longitude = basicStyle?.mapCenter?.longitude ?? DEFAULT_BASIC_STYLE.mapCenter.longitude
|
||||
const latitude = basicStyle?.mapCenter?.latitude ?? DEFAULT_BASIC_STYLE.mapCenter.latitude
|
||||
center = [longitude, latitude]
|
||||
} else {
|
||||
center = undefined
|
||||
}
|
||||
return center
|
||||
}
|
||||
|
||||
export function getMapStyle(
|
||||
mapKey: { key: string; securityCode: string; mapType: string },
|
||||
basicStyle: ChartBasicStyle
|
||||
) {
|
||||
let mapStyle: string
|
||||
switch (mapKey.mapType) {
|
||||
case 'tianditu':
|
||||
if (!find(tdtMapStyleOptions, s => s.value === basicStyle.mapStyle)) {
|
||||
mapStyle = 'normal'
|
||||
} else {
|
||||
mapStyle = basicStyle.mapStyle
|
||||
}
|
||||
break
|
||||
case 'qq':
|
||||
if (
|
||||
!find(qqMapStyleOptions, s => s.value === basicStyle.mapStyle) ||
|
||||
basicStyle.mapStyle === 'normal'
|
||||
) {
|
||||
mapStyle = 'normal'
|
||||
} else {
|
||||
mapStyle = basicStyle.mapStyleUrl
|
||||
}
|
||||
break
|
||||
default:
|
||||
if (!find(gaodeMapStyleOptions, s => s.value === basicStyle.mapStyle)) {
|
||||
basicStyle.mapStyle = 'normal'
|
||||
}
|
||||
mapStyle = basicStyle.mapStyleUrl
|
||||
if (basicStyle.mapStyle !== 'custom') {
|
||||
mapStyle = `amap://styles/${basicStyle.mapStyle ? basicStyle.mapStyle : 'normal'}`
|
||||
}
|
||||
break
|
||||
}
|
||||
return mapStyle
|
||||
}
|
||||
|
||||
export async function getMapScene(
|
||||
chart: Chart,
|
||||
scene: Scene,
|
||||
container: string,
|
||||
mapKey: { key: string; securityCode: string; mapType: string },
|
||||
basicStyle: ChartBasicStyle,
|
||||
miscStyle: ChartMiscAttr,
|
||||
mapStyle: string,
|
||||
center?: [number, number]
|
||||
) {
|
||||
if (!scene) {
|
||||
scene = new Scene({
|
||||
id: container,
|
||||
logoVisible: false,
|
||||
map: getMapObject(mapKey, basicStyle, miscStyle, mapStyle, center)
|
||||
})
|
||||
} else {
|
||||
if (mapKey.mapType === 'tianditu') {
|
||||
scene.map?.checkResize()
|
||||
}
|
||||
if (scene.getLayers()?.length) {
|
||||
await scene.removeAllLayer()
|
||||
try {
|
||||
scene.setPitch(miscStyle.mapPitch)
|
||||
} catch (e) {}
|
||||
if (mapKey.mapType === 'tianditu') {
|
||||
if (mapStyle === 'normal') {
|
||||
scene.map?.removeStyle()
|
||||
} else {
|
||||
scene.setMapStyle(mapStyle)
|
||||
}
|
||||
} else {
|
||||
scene.setMapStyle(mapStyle)
|
||||
}
|
||||
|
||||
scene.map.showLabel = !(basicStyle.showLabel === false)
|
||||
if (mapKey.mapType === 'qq') {
|
||||
scene.map.setBaseMap({
|
||||
//底图设置(参数为:VectorBaseMap对象)
|
||||
type: 'vector', //类型:失量底图
|
||||
features: basicStyle.showLabel === false ? ['base', 'building2d'] : undefined
|
||||
//仅渲染:道路及底面(base) + 2d建筑物(building2d),以达到隐藏文字的效果
|
||||
})
|
||||
}
|
||||
}
|
||||
if (basicStyle.autoFit === false) {
|
||||
scene.setZoomAndCenter(basicStyle.zoomLevel, center)
|
||||
if (mapKey.mapType === 'qq') {
|
||||
scene.map.deMapAutoFit = false
|
||||
scene.map.deMapZoom = basicStyle.zoomLevel
|
||||
scene.map.deMapCenter = center
|
||||
}
|
||||
}
|
||||
}
|
||||
mapRendering(container)
|
||||
scene.once('loaded', () => {
|
||||
mapRendered(container)
|
||||
if (mapKey.mapType === 'qq') {
|
||||
scene.map.setBaseMap({
|
||||
//底图设置(参数为:VectorBaseMap对象)
|
||||
type: 'vector', //类型:失量底图
|
||||
features: basicStyle.showLabel === false ? ['base', 'building2d'] : undefined
|
||||
//仅渲染:道路及底面(base) + 2d建筑物(building2d),以达到隐藏文字的效果
|
||||
})
|
||||
scene.setMapStyle(mapStyle)
|
||||
|
||||
scene.map.deMapProvider = 'qq'
|
||||
scene.map.deMapAutoFit = !!basicStyle.autoFit
|
||||
// scene.map.deMapAutoZoom = scene.map.getZoom()
|
||||
// scene.map.deMapAutoLng = scene.map.getCenter().getLng()
|
||||
// scene.map.deMapAutoLat = scene.map.getCenter().getLat()
|
||||
}
|
||||
// 去除天地图自己的缩放按钮
|
||||
if (mapKey.mapType === 'tianditu') {
|
||||
if (mapStyle === 'normal') {
|
||||
scene.map?.removeStyle()
|
||||
} else {
|
||||
scene.setMapStyle(mapStyle)
|
||||
}
|
||||
|
||||
const tdtControl = document.querySelector(
|
||||
`#component${chart.id} .tdt-control-zoom.tdt-bar.tdt-control`
|
||||
)
|
||||
if (tdtControl) {
|
||||
tdtControl.style.display = 'none'
|
||||
}
|
||||
const tdtControlOuter = document.querySelectorAll(
|
||||
`#wrapper-outer-id-${chart.id} .tdt-control-zoom.tdt-bar.tdt-control`
|
||||
)
|
||||
if (tdtControlOuter && tdtControlOuter.length > 0) {
|
||||
for (let i = 0; i < tdtControlOuter.length; i++) {
|
||||
tdtControlOuter[i].style.display = 'none'
|
||||
}
|
||||
}
|
||||
const tdtCopyrightControl = document.querySelector(
|
||||
`#component${chart.id} .tdt-control-copyright.tdt-control`
|
||||
)
|
||||
if (tdtCopyrightControl) {
|
||||
tdtCopyrightControl.style.display = 'none'
|
||||
}
|
||||
const tdtCopyrightControlOuter = document.querySelectorAll(
|
||||
`#wrapper-outer-id-${chart.id} .tdt-control-copyright.tdt-control`
|
||||
)
|
||||
if (tdtCopyrightControlOuter && tdtCopyrightControlOuter.length > 0) {
|
||||
for (let i = 0; i < tdtCopyrightControlOuter.length; i++) {
|
||||
tdtCopyrightControlOuter[i].style.display = 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return scene
|
||||
}
|
||||
|
||||
export function getMapObject(
|
||||
mapKey: { key: string; securityCode: string; mapType: string },
|
||||
basicStyle: ChartBasicStyle,
|
||||
miscStyle: ChartMiscAttr,
|
||||
mapStyle: string,
|
||||
center?: [number, number]
|
||||
) {
|
||||
switch (mapKey.mapType) {
|
||||
case 'tianditu':
|
||||
return new TMap({
|
||||
token: mapKey?.key ?? undefined,
|
||||
style: mapStyle, //不生效
|
||||
pitch: undefined, //不支持
|
||||
center,
|
||||
zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : undefined,
|
||||
showLabel: !(basicStyle.showLabel === false), //不支持
|
||||
WebGLParams: {
|
||||
preserveDrawingBuffer: true
|
||||
}
|
||||
})
|
||||
case 'qq':
|
||||
return new TencentMap({
|
||||
token: mapKey?.key ?? undefined,
|
||||
style: mapStyle,
|
||||
pitch: miscStyle.mapPitch,
|
||||
center,
|
||||
zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : 12,
|
||||
showLabel: !(basicStyle.showLabel === false),
|
||||
WebGLParams: {
|
||||
preserveDrawingBuffer: true
|
||||
}
|
||||
})
|
||||
default:
|
||||
return new GaodeMap({
|
||||
token: mapKey?.key ?? undefined,
|
||||
style: mapStyle,
|
||||
pitch: miscStyle.mapPitch,
|
||||
center,
|
||||
zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : undefined,
|
||||
showLabel: !(basicStyle.showLabel === false),
|
||||
WebGLParams: {
|
||||
preserveDrawingBuffer: true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 隐藏缩放控件
|
||||
* @param basicStyle
|
||||
@ -1358,6 +1661,8 @@ export function getTooltipContainer(id) {
|
||||
let wrapperDom = document.getElementById(G2_TOOLTIP_WRAPPER)
|
||||
if (!wrapperDom) {
|
||||
wrapperDom = document.createElement('div')
|
||||
wrapperDom.style.position = 'absolute'
|
||||
wrapperDom.style.zIndex = '9999'
|
||||
wrapperDom.id = G2_TOOLTIP_WRAPPER
|
||||
document.body.appendChild(wrapperDom)
|
||||
}
|
||||
@ -1391,14 +1696,78 @@ export function getTooltipContainer(id) {
|
||||
}
|
||||
return g2Tooltip
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置提示轮播
|
||||
* @param plot
|
||||
* @param chart
|
||||
*/
|
||||
function configCarouselTooltip(plot, chart) {
|
||||
const start = isSupport(chart.type) && !document.getElementById('multiplexingDrawer')
|
||||
if (start) {
|
||||
// 启用轮播
|
||||
plot.once('afterrender', () => {
|
||||
const carousel = chart.customAttr?.tooltip?.carousel
|
||||
ChartCarouselTooltip.manage(plot, chart, {
|
||||
xField: 'field',
|
||||
duration: carousel.enable ? carousel?.stayTime * 1000 : 2000,
|
||||
interval: carousel.enable ? carousel?.intervalTime * 1000 : 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 计算 Tooltip 的位置
|
||||
* @param {Chart} chart - 图表实例
|
||||
* @param {boolean} isCarousel - 是否为轮播模式
|
||||
* @param {object} tooltipCtl - Tooltip 控制器
|
||||
* @param {HTMLElement} chartElement - 图表元素
|
||||
* @param {Event} event - 事件对象
|
||||
* @param {boolean} enlargeElement - 放大弹窗
|
||||
* @returns {{x: number, y: number}} - 计算后的 x 和 y 坐标
|
||||
*/
|
||||
function calculateTooltipPosition(chart, isCarousel, tooltipCtl, chartElement, event) {
|
||||
// 辅助函数: 根据不同图表类型计算 Tooltip 的y位置
|
||||
const getTooltipY = () => {
|
||||
const top = Number(chartElement.getBoundingClientRect().top)
|
||||
if (isColumn(chart.type)) {
|
||||
return top + chartElement.getBoundingClientRect().height / 2
|
||||
}
|
||||
if (isMix(chart.type) || isPie(chart.type)) {
|
||||
return top + tooltipCtl.point.y
|
||||
}
|
||||
return top + tooltipCtl.point.y + 60
|
||||
}
|
||||
if (isCarousel) {
|
||||
return {
|
||||
x: tooltipCtl.point.x + Number(chartElement.getBoundingClientRect().left),
|
||||
y: getTooltipY()
|
||||
}
|
||||
} else {
|
||||
return { x: event.clientX, y: event.clientY }
|
||||
}
|
||||
}
|
||||
export function configPlotTooltipEvent<O extends PickOptions, P extends Plot<O>>(
|
||||
chart: Chart,
|
||||
plot: P
|
||||
) {
|
||||
const { tooltip } = parseJson(chart.customAttr)
|
||||
if (!tooltip.show) {
|
||||
ChartCarouselTooltip.destroyByContainer(chart.container)
|
||||
return
|
||||
}
|
||||
// 图表容器,用于计算 tooltip 的位置
|
||||
// 获取图表元素,优先顺序:放大 > 预览 > 公共连接页面 > 默认
|
||||
const chartElement =
|
||||
document.getElementById('container-viewDialog-' + chart.id + '-common') ||
|
||||
document.getElementById('container-preview-' + chart.id + '-common') ||
|
||||
document.getElementById('enlarge-inner-content-' + chart.id) ||
|
||||
document.getElementById('shape-id-' + chart.id)
|
||||
// 是否是放大弹窗
|
||||
const enlargeElement = chartElement?.id.includes('viewDialog')
|
||||
// 轮播时tooltip的zIndex
|
||||
const carousel_zIndex = enlargeElement ? '9999' : '1002'
|
||||
configCarouselTooltip(plot, chart)
|
||||
// 鼠标可移入, 移入之后保持显示, 移出之后隐藏
|
||||
plot.options.tooltip.container.addEventListener('mouseenter', e => {
|
||||
e.target.style.visibility = 'visible'
|
||||
@ -1415,10 +1784,25 @@ export function configPlotTooltipEvent<O extends PickOptions, P extends Plot<O>>
|
||||
if (!tooltipCtl) {
|
||||
return
|
||||
}
|
||||
// 处理 tooltip 与下拉菜单的显示冲突问题
|
||||
const viewTrackBarElement = document.getElementById('view-track-bar-' + chart.id)
|
||||
const event = plot.chart.interactions.tooltip?.context?.event
|
||||
// 是否时轮播模式
|
||||
const isCarousel =
|
||||
chart.customAttr?.tooltip?.carousel &&
|
||||
(!event || // 事件触发时,使用event的client坐标
|
||||
['plot:leave', 'plot:mouseleave'].includes(event?.type) || //鼠标离开时,使用tooltipCtl.point
|
||||
['pie', 'pie-rose', 'pie-donut'].includes(chart.type)) // 饼图时,使用tooltipCtl.point
|
||||
plot.options.tooltip.showMarkers = isCarousel ? true : false
|
||||
const wrapperDom = document.getElementById(G2_TOOLTIP_WRAPPER)
|
||||
wrapperDom.style.zIndex = isCarousel && wrapperDom ? carousel_zIndex : '9999'
|
||||
if (tooltipCtl.tooltip) {
|
||||
// 处理视图放大后再关闭 tooltip 的 dom 被清除
|
||||
const container = tooltipCtl.tooltip.cfg.container
|
||||
// 当下拉菜单不显示时,移除tooltip的hidden-tooltip样式
|
||||
if (viewTrackBarElement?.getAttribute('aria-expanded') === 'false') {
|
||||
container.classList.toggle('hidden-tooltip', false)
|
||||
}
|
||||
container.style.display = 'block'
|
||||
const dom = document.getElementById(container.id)
|
||||
if (!dom) {
|
||||
@ -1433,8 +1817,17 @@ export function configPlotTooltipEvent<O extends PickOptions, P extends Plot<O>>
|
||||
}
|
||||
plot.chart.getOptions().tooltip.follow = false
|
||||
tooltipCtl.title = Math.random().toString()
|
||||
plot.chart.getTheme().components.tooltip.x = event.clientX
|
||||
plot.chart.getTheme().components.tooltip.y = event.clientY
|
||||
// 当显示提示为事件触发时,使用event的client坐标,否则使用tooltipCtl.point 数据点的位置,在图表中,需要加上图表在绘制区的位置
|
||||
const { x, y } = calculateTooltipPosition(
|
||||
chart,
|
||||
isCarousel,
|
||||
tooltipCtl,
|
||||
chartElement,
|
||||
event,
|
||||
enlargeElement
|
||||
)
|
||||
plot.chart.getTheme().components.tooltip.x = x
|
||||
plot.chart.getTheme().components.tooltip.y = y
|
||||
})
|
||||
// https://github.com/antvis/G2/blob/master/src/chart/controller/tooltip.ts#hideTooltip
|
||||
plot.on('plot:leave', () => {
|
||||
@ -1457,14 +1850,22 @@ export function configPlotTooltipEvent<O extends PickOptions, P extends Plot<O>>
|
||||
if (!tooltipCtl) {
|
||||
return
|
||||
}
|
||||
const container = tooltipCtl.tooltip.cfg.container
|
||||
const container = tooltipCtl.tooltip?.cfg.container
|
||||
for (const ele of wrapperDom.children) {
|
||||
if (container.id !== ele.id) {
|
||||
if (!container || container.id !== ele.id) {
|
||||
ele.style.display = 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
plot.on('tooltip:hidden', () => {
|
||||
const tooltipCtl = plot.chart.getController('tooltip')
|
||||
if (!tooltipCtl) {
|
||||
return
|
||||
}
|
||||
const container = tooltipCtl.tooltip?.cfg.container
|
||||
container && (container.style.display = 'none')
|
||||
})
|
||||
}
|
||||
|
||||
export const TOOLTIP_TPL =
|
||||
@ -1699,10 +2100,12 @@ export function configYaxisTitleLengthLimit(chart, plot) {
|
||||
? wrappedTitle.slice(0, wrappedTitle.length - 2) + '...'
|
||||
: wrappedTitle + '...'
|
||||
}
|
||||
|
||||
// 更新Y轴标题的原始文本和截断后的文本
|
||||
ev.view.options.axes.yAxisExt.title.originalText = yAxis.name
|
||||
ev.view.options.axes.yAxisExt.title.text = wrappedTitle
|
||||
const { title } = ev.view.options.axes.yAxisExt
|
||||
if (title) {
|
||||
title.originalText = yAxis.name
|
||||
title.text = wrappedTitle
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -1731,7 +2134,7 @@ export const addConditionsStyleColorToData = (chart: Chart, options) => {
|
||||
})
|
||||
} else if (item.quotaList?.length) {
|
||||
const quotaList = item.quotaList.map(q => q.id) ?? []
|
||||
quotaList.forEach((q, index) => {
|
||||
quotaList.forEach(q => {
|
||||
// 定义后,在 handleConditionsStyle 函数中使用
|
||||
let currentValue = item[valueField]
|
||||
if (chart.type === 'progress-bar') {
|
||||
@ -1798,7 +2201,7 @@ const getColorByConditions = (quotaList: [], values: number | number[], chart) =
|
||||
* @param chart
|
||||
* @param options
|
||||
*/
|
||||
export function handleConditionsStyle(chart: Chart, options: O) {
|
||||
export function handleConditionsStyle(chart: Chart, options) {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
if (!threshold.enable) return options
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
@ -1810,8 +2213,6 @@ export function handleConditionsStyle(chart: Chart, options: O) {
|
||||
// 辅助函数:配置柱条样式颜色,条形图为barStyle,柱形图为columnStyle
|
||||
const columnStyle = data => {
|
||||
return {
|
||||
...options.columnStyle,
|
||||
...options.barStyle,
|
||||
...(data[colorField]?.[0] ? { fill: data[colorField][0] } : {})
|
||||
}
|
||||
}
|
||||
@ -1825,8 +2226,8 @@ export function handleConditionsStyle(chart: Chart, options: O) {
|
||||
const tmpOption = {
|
||||
...options,
|
||||
rawFields,
|
||||
columnStyle: columnStyle,
|
||||
barStyle: columnStyle,
|
||||
...configRoundAngle(chart, 'columnStyle', columnStyle),
|
||||
...configRoundAngle(chart, 'barStyle', columnStyle),
|
||||
tooltip: {
|
||||
...options.tooltip,
|
||||
...(options.tooltip['customItems']
|
||||
@ -1934,7 +2335,7 @@ export const getTooltipItemConditionColor = item => {
|
||||
* @param newData
|
||||
* @param container
|
||||
*/
|
||||
export const configEmptyDataStyle = (newChart, newData, container) => {
|
||||
export const configEmptyDataStyle = (newData, container, newChart?, content?) => {
|
||||
/**
|
||||
* 辅助函数:移除空数据dom
|
||||
*/
|
||||
@ -1949,15 +2350,121 @@ export const configEmptyDataStyle = (newChart, newData, container) => {
|
||||
if (!newData.length) {
|
||||
const emptyDom = document.createElement('div')
|
||||
emptyDom.id = container + '_empty'
|
||||
emptyDom.textContent = tI18n('data_set.no_data')
|
||||
emptyDom.textContent = content || tI18n('data_set.no_data')
|
||||
emptyDom.setAttribute(
|
||||
'style',
|
||||
`position: absolute;
|
||||
left: 45%;
|
||||
top: 50%;`
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: darkgray;
|
||||
textAlign: center;`
|
||||
)
|
||||
const parent = document.getElementById(container)
|
||||
parent.insertBefore(emptyDom, parent.firstChild)
|
||||
newChart.destroy()
|
||||
newChart?.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export const numberToChineseUnderHundred = (num: number): string => {
|
||||
// 合法性检查
|
||||
if (num <= 0 || num > 99 || !Number.isInteger(num)) {
|
||||
throw new Error('请输入1-99之间的整数')
|
||||
}
|
||||
|
||||
const digits = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九']
|
||||
|
||||
// 处理个位数
|
||||
if (num < 10) return digits[num]
|
||||
|
||||
const tens = Math.floor(num / 10)
|
||||
const ones = num % 10
|
||||
|
||||
// 处理整十
|
||||
if (ones === 0) {
|
||||
return tens === 1 ? '十' : digits[tens] + '十'
|
||||
}
|
||||
|
||||
// 处理其他两位数
|
||||
return tens === 1 ? '十' + digits[ones] : digits[tens] + '十' + digits[ones]
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置柱条图的圆角
|
||||
* @param styleName
|
||||
* @param callBack 自定义其他属性函数
|
||||
*/
|
||||
export const configRoundAngle = (chart: Chart, styleName: string, callBack?: (datum) => {}) => {
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
if (['roundAngle', 'topRoundAngle'].includes(basicStyle.radiusColumnBar)) {
|
||||
const radius = Array(2).fill(basicStyle.columnBarRightAngleRadius)
|
||||
const topRadius = [0, 0, ...radius]
|
||||
const bottomRadius = [...radius, 0, 0]
|
||||
const finalRadius = [...radius, ...radius]
|
||||
if (chart.type.includes('-stack')) {
|
||||
return {
|
||||
[styleName]: datum => {
|
||||
if (!datum.value) return { radius: [], ...(callBack ? callBack(datum) : {}) }
|
||||
return { radius: finalRadius, ...(callBack ? callBack(datum) : {}) }
|
||||
}
|
||||
}
|
||||
}
|
||||
const isTopRound = basicStyle.radiusColumnBar === 'topRoundAngle'
|
||||
// 对称条形图
|
||||
if (chart.type === 'bidirectional-bar') {
|
||||
const valueField = basicStyle.layout === 'vertical' ? 'valueExt' : 'value'
|
||||
return {
|
||||
[styleName]: datum => ({
|
||||
radius: datum[valueField] && isTopRound ? topRadius : isTopRound ? radius : finalRadius,
|
||||
...(callBack ? callBack(datum) : {})
|
||||
})
|
||||
}
|
||||
}
|
||||
// 进度条
|
||||
if (chart.type === 'progress-bar') {
|
||||
return {
|
||||
[styleName]: datum => {
|
||||
return {
|
||||
radius: isTopRound ? bottomRadius : finalRadius,
|
||||
...(callBack ? callBack(datum) : {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 区间条形图
|
||||
if (chart.type === 'bar-range') {
|
||||
return {
|
||||
[styleName]: datum => {
|
||||
return {
|
||||
radius:
|
||||
datum?.values[0] < datum?.values[1]
|
||||
? isTopRound
|
||||
? bottomRadius
|
||||
: finalRadius
|
||||
: isTopRound
|
||||
? topRadius
|
||||
: finalRadius,
|
||||
...(callBack ? callBack(datum) : {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 配置柱条样式
|
||||
const style = datum => {
|
||||
if (isTopRound) {
|
||||
return { radius, ...(callBack ? callBack(datum) : {}) }
|
||||
}
|
||||
if (!isTopRound) {
|
||||
return { radius: finalRadius, ...(callBack ? callBack(datum) : {}) }
|
||||
}
|
||||
}
|
||||
return {
|
||||
[styleName]: style
|
||||
}
|
||||
}
|
||||
return {
|
||||
[styleName]: datum => {
|
||||
return { ...(callBack ? callBack(datum) : {}) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,10 @@ import {
|
||||
isAlphaColor,
|
||||
isTransparent,
|
||||
parseJson,
|
||||
resetRgbOpacity
|
||||
} from '../../util'
|
||||
resetRgbOpacity,
|
||||
safeDecimalSum,
|
||||
safeDecimalMean
|
||||
} from '../..//util'
|
||||
import {
|
||||
DEFAULT_BASIC_STYLE,
|
||||
DEFAULT_TABLE_CELL,
|
||||
@ -43,13 +45,31 @@ import {
|
||||
updateShapeAttr,
|
||||
ViewMeta
|
||||
} from '@antv/s2'
|
||||
import { cloneDeep, filter, find, intersection, keys, merge, repeat } from 'lodash-es'
|
||||
import {
|
||||
cloneDeep,
|
||||
filter,
|
||||
find,
|
||||
intersection,
|
||||
keys,
|
||||
map,
|
||||
maxBy,
|
||||
meanBy,
|
||||
merge,
|
||||
minBy,
|
||||
repeat,
|
||||
sumBy,
|
||||
size,
|
||||
sum
|
||||
} from 'lodash-es'
|
||||
import { createVNode, render } from 'vue'
|
||||
import TableTooltip from '@/data-visualization/chart/components/editor/common/TableTooltip.vue'
|
||||
import Exceljs from 'exceljs'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { ElMessage } from 'element-plus-secondary'
|
||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||
import Decimal from 'decimal.js'
|
||||
|
||||
|
||||
const { t: i18nt } = useI18n()
|
||||
|
||||
export function getCustomTheme(chart: Chart): S2Theme {
|
||||
@ -401,8 +421,7 @@ export function getCustomTheme(chart: Chart): S2Theme {
|
||||
},
|
||||
dataCell: {
|
||||
cell: {
|
||||
crossBackgroundColor:
|
||||
enableTableCrossBG && !tableCell.mergeCells ? tableItemSubBgColor : tableItemBgColor,
|
||||
crossBackgroundColor: enableTableCrossBG ? tableItemSubBgColor : tableItemBgColor,
|
||||
backgroundColor: tableItemBgColor
|
||||
},
|
||||
bolderText: {
|
||||
@ -504,8 +523,8 @@ export function getStyle(chart: Chart, dataConfig: S2DataConfig): Style {
|
||||
item => item.id === chart.drillFilters[0].fieldId
|
||||
)
|
||||
const drillEnterField = xAxis[drillEnterFieldIndex]
|
||||
fieldMap[curDrillField.dataeaseName] = {
|
||||
width: fieldMap[drillEnterField.dataeaseName]?.width
|
||||
fieldMap[curDrillField.gisbiName] = {
|
||||
width: fieldMap[drillEnterField.gisbiName]?.width
|
||||
}
|
||||
}
|
||||
// 铺满
|
||||
@ -579,7 +598,7 @@ export function getCurrentField(valueFieldList: Axis[], field: ChartViewField) {
|
||||
if (list) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const f = list[i]
|
||||
if (field.dataeaseName === f.dataeaseName) {
|
||||
if (field.gisbiName === f.gisbiName) {
|
||||
res = f
|
||||
break
|
||||
}
|
||||
@ -600,10 +619,10 @@ export function getConditions(chart: Chart) {
|
||||
}
|
||||
const conditions = threshold.tableThreshold ?? []
|
||||
|
||||
const dimFields = [...chart.xAxis, ...chart.xAxisExt].map(i => i.dataeaseName)
|
||||
const dimFields = [...chart.xAxis, ...chart.xAxisExt].map(i => i.gisbiName)
|
||||
if (conditions?.length > 0) {
|
||||
const { tableCell, basicStyle, tableHeader } = parseJson(chart.customAttr)
|
||||
// 合并单元格时,班马纹失效
|
||||
// 合并单元格时斑马纹失效
|
||||
const enableTableCrossBG =
|
||||
chart.type === 'table-info'
|
||||
? tableCell.enableTableCrossBG && !tableCell.mergeCells
|
||||
@ -626,12 +645,12 @@ export function getConditions(chart: Chart) {
|
||||
let defaultValueColor = valueColor
|
||||
let defaultBgColor = valueBgColor
|
||||
// 透视表表头颜色配置
|
||||
if (chart.type === 'table-pivot' && dimFields.includes(field.field.dataeaseName)) {
|
||||
if (chart.type === 'table-pivot' && dimFields.includes(field.field.gisbiName)) {
|
||||
defaultValueColor = headerValueColor
|
||||
defaultBgColor = headerValueBgColor
|
||||
}
|
||||
res.text.push({
|
||||
field: field.field.dataeaseName,
|
||||
field: field.field.gisbiName,
|
||||
mapping(value, rowData) {
|
||||
// 总计小计
|
||||
if (rowData?.isTotals) {
|
||||
@ -647,7 +666,7 @@ export function getConditions(chart: Chart) {
|
||||
}
|
||||
})
|
||||
res.background.push({
|
||||
field: field.field.dataeaseName,
|
||||
field: field.field.gisbiName,
|
||||
mapping(value, rowData) {
|
||||
if (rowData?.isTotals) {
|
||||
return null
|
||||
@ -783,6 +802,9 @@ export function mappingColor(value, defaultColor, field, type, filedValueMap?, r
|
||||
}
|
||||
} else {
|
||||
// time
|
||||
if (!tv || !value) {
|
||||
break
|
||||
}
|
||||
const fc = field.conditions[i]
|
||||
tv = new Date(tv.replace(/-/g, '/') + ' GMT+8').getTime()
|
||||
const v = new Date(value.replace(/-/g, '/') + ' GMT+8').getTime()
|
||||
@ -842,7 +864,7 @@ function getFieldValueMap(view) {
|
||||
|
||||
function getValue(field, filedValueMap, rowData) {
|
||||
if (field.summary === 'value') {
|
||||
return rowData ? rowData[field.field?.dataeaseName] : undefined
|
||||
return rowData ? rowData[field.field?.gisbiName] : undefined
|
||||
} else {
|
||||
return filedValueMap[field.summary + '-' + field.fieldId]
|
||||
}
|
||||
@ -880,6 +902,7 @@ export function handleTableEmptyStrategy(chart: Chart) {
|
||||
}
|
||||
return newData
|
||||
}
|
||||
|
||||
export class SortTooltip extends BaseTooltip {
|
||||
show(showOptions) {
|
||||
const { iconName } = showOptions
|
||||
@ -934,6 +957,7 @@ export class SortTooltip extends BaseTooltip {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const SORT_DEFAULT =
|
||||
'<svg t="1711681787276" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4355" width="200" height="200"><path d="M922.345786 372.183628l-39.393195 38.687114L676.138314 211.079416l0 683.909301-54.713113 0L621.425202 129.010259l53.320393 0L922.345786 372.183628zM349.254406 894.989741 101.654214 651.815349l39.393195-38.687114 206.814276 199.792349L347.861686 129.010259l54.713113 0 0 765.978459L349.254406 894.988718z" fill="{fill}" p-id="4356"></path></svg>'
|
||||
const SORT_UP =
|
||||
@ -1063,7 +1087,14 @@ export function copyContent(s2Instance: SpreadSheet, event, fieldMeta) {
|
||||
if (cells.length === 1) {
|
||||
const curCell = cells[0]
|
||||
if (cell.getMeta().id === curCell.id) {
|
||||
copyString(cellMeta.value + '', true)
|
||||
const cellMeta = cell.getMeta()
|
||||
const value = cellMeta.data?.[cellMeta.valueField]
|
||||
const metaObj = find(fieldMeta, m => m.field === cellMeta.valueField)
|
||||
let fieldVal = value?.toString()
|
||||
if (metaObj) {
|
||||
fieldVal = metaObj.formatter(value)
|
||||
}
|
||||
copyString(fieldVal, true)
|
||||
}
|
||||
s2Instance.interaction.clearState()
|
||||
return
|
||||
@ -1189,7 +1220,7 @@ export async function exportGridPivot(instance: PivotSheet, chart: ChartObj) {
|
||||
const { meta, fields } = instance.dataCfg
|
||||
const rowLength = fields?.rows?.length || 0
|
||||
const colLength = fields?.columns?.length || 0
|
||||
const colNums = layoutResult.colLeafNodes.length + rowLength + 1
|
||||
const colNums = layoutResult.colLeafNodes.length + rowLength
|
||||
if (colNums > 16384) {
|
||||
ElMessage.warning(i18nt('chart.pivot_export_invalid_col_exceed'))
|
||||
return
|
||||
@ -1346,9 +1377,180 @@ export async function exportGridPivot(instance: PivotSheet, chart: ChartObj) {
|
||||
if (fieldValue === 0 || fieldValue) {
|
||||
const meta = metaMap[dataCellMeta.valueField]
|
||||
const cell = worksheet.getCell(rowIndex + maxColHeight + 1, rowLength + colIndex + 1)
|
||||
const value = meta?.formatter?.(fieldValue) || fieldValue.toString()
|
||||
const value = meta?.formatter?.(fieldValue) || fieldValue
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.value = value
|
||||
cell.value = isNumeric(value) ? parseFloat(value) : value
|
||||
}
|
||||
}
|
||||
}
|
||||
const buffer = await workbook.xlsx.writeBuffer()
|
||||
const dataBlob = new Blob([buffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'
|
||||
})
|
||||
saveAs(dataBlob, `${chart.title ?? '透视表'}.xlsx`)
|
||||
}
|
||||
|
||||
export async function exportRowQuotaGridPivot(instance: PivotSheet, chart: ChartObj) {
|
||||
const { layoutResult } = instance.facet
|
||||
const { meta, fields } = instance.dataCfg
|
||||
const rowLength = fields?.rows?.length || 0
|
||||
const colLength = fields?.columns?.length || 0
|
||||
const colNums = layoutResult.colLeafNodes.length + rowLength
|
||||
if (colNums > 16384) {
|
||||
ElMessage.warning(i18nt('chart.pivot_export_invalid_col_exceed'))
|
||||
return
|
||||
}
|
||||
const workbook = new Exceljs.Workbook()
|
||||
const worksheet = workbook.addWorksheet(i18nt('chart.chart_data'))
|
||||
const metaMap: Record<string, Meta> = meta?.reduce((p, n) => {
|
||||
if (n.field) {
|
||||
p[n.field] = n
|
||||
}
|
||||
return p
|
||||
}, {})
|
||||
// 角头
|
||||
if (colLength > 1) {
|
||||
fields.columns.forEach((column: string, index) => {
|
||||
if (index >= colLength - 1) {
|
||||
return
|
||||
}
|
||||
const cell = worksheet.getCell(index + 1, 1)
|
||||
cell.value = metaMap[column]?.name ?? column
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
right: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
worksheet.mergeCells(index + 1, 1, index + 1, rowLength + 1)
|
||||
})
|
||||
}
|
||||
fields?.rows?.forEach((row, index) => {
|
||||
const cell = worksheet.getCell(colLength === 0 ? 1 : colLength, index + 1)
|
||||
cell.value = metaMap[row]?.name ?? row
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = { bottom: { style: 'thick', color: { argb: '00000000' } } }
|
||||
})
|
||||
const quotaColLabel = chart.customAttr.basicStyle.quotaColLabel ?? t('dataset.value')
|
||||
const quotaColHeadCell = worksheet.getCell(colLength === 0 ? 1 : colLength, rowLength + 1)
|
||||
quotaColHeadCell.value = quotaColLabel
|
||||
quotaColHeadCell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
quotaColHeadCell.border = {
|
||||
bottom: { style: 'thick', color: { argb: '00000000' } },
|
||||
right: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
// 行头
|
||||
const { rowLeafNodes, rowNodes } = layoutResult
|
||||
const notLeafNodeHeightMap: Record<string, number> = {}
|
||||
rowLeafNodes.forEach(node => {
|
||||
// 行头的高度由子节点相加决定,也就是行头子节点中包含的叶子节点数量
|
||||
let curNode = node.parent
|
||||
while (curNode) {
|
||||
const height = notLeafNodeHeightMap[curNode.id] ?? 0
|
||||
notLeafNodeHeightMap[curNode.id] = height + 1
|
||||
curNode = curNode.parent
|
||||
}
|
||||
const { rowIndex } = node
|
||||
const writeRowIndex = rowIndex + 2 + (colLength === 0 ? 1 : colLength - 1)
|
||||
const writeColIndex = node.level + 1
|
||||
const cell = worksheet.getCell(writeRowIndex, writeColIndex)
|
||||
let value = node.label
|
||||
if (node.field === '$$extra$$' && metaMap[value]?.name) {
|
||||
value = metaMap[value].name
|
||||
}
|
||||
cell.value = value
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
right: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
})
|
||||
|
||||
const getNodeStartRowIndex = (node: Node) => {
|
||||
if (!node.children?.length) {
|
||||
return node.rowIndex + 1
|
||||
} else {
|
||||
return getNodeStartRowIndex(node.children[0])
|
||||
}
|
||||
}
|
||||
rowNodes?.forEach(node => {
|
||||
if (node.isLeaf) {
|
||||
return
|
||||
}
|
||||
const rowIndex = getNodeStartRowIndex(node)
|
||||
const height = notLeafNodeHeightMap[node.id]
|
||||
const writeRowIndex = rowIndex + 1 + (colLength === 0 ? 1 : colLength - 1)
|
||||
const mergeColCount = node.children[0].level - node.level
|
||||
const cell = worksheet.getCell(writeRowIndex, node.level + 1)
|
||||
cell.value = node.label
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
if (mergeColCount > 1 || height > 1) {
|
||||
worksheet.mergeCells(
|
||||
writeRowIndex,
|
||||
node.level + 1,
|
||||
writeRowIndex + height - 1,
|
||||
node.level + mergeColCount
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// 列头
|
||||
const { colLeafNodes, colNodes, colsHierarchy } = layoutResult
|
||||
const maxColHeight = colsHierarchy.maxLevel + 1
|
||||
const notLeafNodeWidthMap: Record<string, number> = {}
|
||||
colLeafNodes.forEach(node => {
|
||||
// 列头的宽度由子节点相加决定,也就是列头子节点中包含的叶子节点数量
|
||||
let curNode = node.parent
|
||||
while (curNode) {
|
||||
const width = notLeafNodeWidthMap[curNode.id] ?? 0
|
||||
notLeafNodeWidthMap[curNode.id] = width + 1
|
||||
curNode = curNode.parent
|
||||
}
|
||||
const { colIndex } = node
|
||||
const writeRowIndex = node.level + 1
|
||||
const writeColIndex = colIndex + rowLength + 2
|
||||
const cell = worksheet.getCell(writeRowIndex, writeColIndex)
|
||||
const value = node.label
|
||||
cell.value = value
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
if (writeRowIndex < maxColHeight) {
|
||||
worksheet.mergeCells(writeRowIndex, writeColIndex, maxColHeight, writeColIndex)
|
||||
}
|
||||
cell.border = {
|
||||
bottom: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
})
|
||||
const getNodeStartColIndex = (node: Node) => {
|
||||
if (!node.children?.length) {
|
||||
return node.colIndex + 1
|
||||
} else {
|
||||
return getNodeStartColIndex(node.children[0])
|
||||
}
|
||||
}
|
||||
colNodes.forEach(node => {
|
||||
if (node.isLeaf) {
|
||||
return
|
||||
}
|
||||
const colIndex = getNodeStartColIndex(node)
|
||||
const width = notLeafNodeWidthMap[node.id]
|
||||
const writeRowIndex = node.level + 1
|
||||
const value = node.label
|
||||
const writeColIndex = colIndex + rowLength + 1
|
||||
const cell = worksheet.getCell(writeRowIndex, writeColIndex)
|
||||
cell.value = value
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
if (width > 1) {
|
||||
worksheet.mergeCells(writeRowIndex, writeColIndex, writeRowIndex, writeColIndex + width - 1)
|
||||
}
|
||||
})
|
||||
// 单元格数据
|
||||
for (let rowIndex = 0; rowIndex < rowLeafNodes.length; rowIndex++) {
|
||||
for (let colIndex = 0; colIndex < colLeafNodes.length; colIndex++) {
|
||||
const dataCellMeta = layoutResult.getCellMeta(rowIndex, colIndex)
|
||||
const { fieldValue } = dataCellMeta
|
||||
if (fieldValue === 0 || fieldValue) {
|
||||
const meta = metaMap[dataCellMeta.valueField]
|
||||
const cell = worksheet.getCell(rowIndex + maxColHeight + 1, rowLength + colIndex + 2)
|
||||
const value = meta?.formatter?.(fieldValue) || fieldValue
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.value = isNumeric(value) ? parseFloat(value) : value
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1361,7 +1563,7 @@ export async function exportGridPivot(instance: PivotSheet, chart: ChartObj) {
|
||||
|
||||
export async function exportTreePivot(instance: PivotSheet, chart: ChartObj) {
|
||||
const layoutResult = instance.facet.layoutResult
|
||||
if (layoutResult.colLeafNodes.length + 2 > 16384) {
|
||||
if (layoutResult.colLeafNodes.length + 1 > 16384) {
|
||||
ElMessage.warning(i18nt('chart.pivot_export_invalid_col_exceed'))
|
||||
return
|
||||
}
|
||||
@ -1468,9 +1670,9 @@ export async function exportTreePivot(instance: PivotSheet, chart: ChartObj) {
|
||||
if (fieldValue === 0 || fieldValue) {
|
||||
const meta = metaMap[dataCellMeta.valueField]
|
||||
const cell = worksheet.getCell(rowIndex + maxColHeight + 1, colIndex + 1 + 1)
|
||||
const value = meta?.formatter?.(fieldValue) || fieldValue.toString()
|
||||
const value = meta?.formatter?.(fieldValue) || fieldValue
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.value = value
|
||||
cell.value = isNumeric(value) ? parseFloat(value) : value
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1480,6 +1682,135 @@ export async function exportTreePivot(instance: PivotSheet, chart: ChartObj) {
|
||||
})
|
||||
saveAs(dataBlob, `${chart.title ?? '透视表'}.xlsx`)
|
||||
}
|
||||
|
||||
export async function exportRowQuotaTreePivot(instance: PivotSheet, chart: ChartObj) {
|
||||
const layoutResult = instance.facet.layoutResult
|
||||
if (layoutResult.colLeafNodes.length + 1 > 16384) {
|
||||
ElMessage.warning(i18nt('chart.pivot_export_invalid_col_exceed'))
|
||||
return
|
||||
}
|
||||
const { meta, fields } = instance.dataCfg
|
||||
const colLength = fields?.columns?.length || 0
|
||||
const workbook = new Exceljs.Workbook()
|
||||
const worksheet = workbook.addWorksheet(i18nt('chart.chart_data'))
|
||||
const metaMap: Record<string, Meta> = meta?.reduce((p, n) => {
|
||||
if (n.field) {
|
||||
p[n.field] = n
|
||||
}
|
||||
return p
|
||||
}, {})
|
||||
|
||||
// 角头
|
||||
fields.columns?.forEach((column, index) => {
|
||||
if (index >= fields.columns.length - 1) {
|
||||
return
|
||||
}
|
||||
const cell = worksheet.getCell(index + 1, 1)
|
||||
cell.value = metaMap[column]?.name ?? column
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
right: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
})
|
||||
const quotaColLabel = chart.customAttr.basicStyle.quotaColLabel ?? t('dataset.value')
|
||||
const maxColHeight = layoutResult.colsHierarchy.maxLevel + 1
|
||||
const rowName = fields?.rows
|
||||
?.map(row => metaMap[row]?.name ?? row)
|
||||
.concat(quotaColLabel)
|
||||
.join('/')
|
||||
const cell = worksheet.getCell(colLength, 1)
|
||||
cell.value = rowName
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
right: { style: 'thick', color: { argb: '00000000' } },
|
||||
bottom: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
//行头
|
||||
const { rowLeafNodes } = layoutResult
|
||||
rowLeafNodes.forEach((node, index) => {
|
||||
const cell = worksheet.getCell(maxColHeight + index + 1, 1)
|
||||
let value = node.label
|
||||
if (node.field === '$$extra$$' && metaMap[value]?.name) {
|
||||
value = metaMap[value].name
|
||||
}
|
||||
cell.value = repeat(' ', node.level) + value
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'left' }
|
||||
cell.border = {
|
||||
right: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
})
|
||||
// 列头
|
||||
const notLeafNodeWidthMap: Record<string, number> = {}
|
||||
const { colLeafNodes } = layoutResult
|
||||
colLeafNodes.forEach(node => {
|
||||
let curNode = node.parent
|
||||
while (curNode) {
|
||||
const width = notLeafNodeWidthMap[curNode.id] ?? 0
|
||||
notLeafNodeWidthMap[curNode.id] = width + 1
|
||||
curNode = curNode.parent
|
||||
}
|
||||
const { colIndex } = node
|
||||
const writeRowIndex = node.level + 1
|
||||
const writeColIndex = colIndex + 2
|
||||
const cell = worksheet.getCell(writeRowIndex, writeColIndex)
|
||||
cell.value = node.label
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
if (writeRowIndex < maxColHeight) {
|
||||
worksheet.mergeCells(writeRowIndex, writeColIndex, maxColHeight, writeColIndex)
|
||||
}
|
||||
cell.border = {
|
||||
bottom: { style: 'thick', color: { argb: '00000000' } }
|
||||
}
|
||||
})
|
||||
const colNodes = layoutResult.colNodes
|
||||
const getNodeStartIndex = (node: Node) => {
|
||||
if (!node.children?.length) {
|
||||
return node.colIndex + 1
|
||||
} else {
|
||||
return getNodeStartIndex(node.children[0])
|
||||
}
|
||||
}
|
||||
colNodes.forEach(node => {
|
||||
if (node.isLeaf) {
|
||||
return
|
||||
}
|
||||
const colIndex = getNodeStartIndex(node)
|
||||
const width = notLeafNodeWidthMap[node.id]
|
||||
const writeRowIndex = node.level + 1
|
||||
const writeColIndex = colIndex + 1
|
||||
const cell = worksheet.getCell(writeRowIndex, writeColIndex)
|
||||
cell.value = node.label
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
if (width > 1) {
|
||||
worksheet.mergeCells(writeRowIndex, writeColIndex, writeRowIndex, writeColIndex + width - 1)
|
||||
}
|
||||
})
|
||||
// 单元格数据
|
||||
for (let rowIndex = 0; rowIndex < rowLeafNodes.length; rowIndex++) {
|
||||
for (let colIndex = 0; colIndex < colLeafNodes.length; colIndex++) {
|
||||
const dataCellMeta = layoutResult.getCellMeta(rowIndex, colIndex)
|
||||
const { fieldValue } = dataCellMeta
|
||||
if (fieldValue === 0 || fieldValue) {
|
||||
const meta = metaMap[dataCellMeta.valueField]
|
||||
const cell = worksheet.getCell(rowIndex + maxColHeight + 1, colIndex + 2)
|
||||
const value = meta?.formatter?.(fieldValue) || fieldValue
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.value = isNumeric(value) ? parseFloat(value) : value
|
||||
}
|
||||
}
|
||||
}
|
||||
const buffer = await workbook.xlsx.writeBuffer()
|
||||
const dataBlob = new Blob([buffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'
|
||||
})
|
||||
saveAs(dataBlob, `${chart.title ?? '透视表'}.xlsx`)
|
||||
}
|
||||
|
||||
|
||||
function isNumeric(value: string): boolean {
|
||||
return /^[+-]?\d+(\.\d+)?$/.test(value)
|
||||
}
|
||||
|
||||
export async function exportPivotExcel(instance: PivotSheet, chart: ChartObj) {
|
||||
const { fields } = instance.dataCfg
|
||||
const rowLength = fields?.rows?.length || 0
|
||||
@ -1488,10 +1819,19 @@ export async function exportPivotExcel(instance: PivotSheet, chart: ChartObj) {
|
||||
ElMessage.warning(i18nt('chart.pivot_export_invalid_field'))
|
||||
return
|
||||
}
|
||||
const { quotaPosition } = chart.customAttr.basicStyle
|
||||
if (chart.customAttr.basicStyle.tableLayoutMode !== 'tree') {
|
||||
exportGridPivot(instance, chart)
|
||||
if (quotaPosition === 'row') {
|
||||
exportRowQuotaGridPivot(instance, chart)
|
||||
} else {
|
||||
exportGridPivot(instance, chart)
|
||||
}
|
||||
} else {
|
||||
exportTreePivot(instance, chart)
|
||||
if (quotaPosition === 'row') {
|
||||
exportRowQuotaTreePivot(instance, chart)
|
||||
} else {
|
||||
exportTreePivot(instance, chart)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1504,7 +1844,7 @@ export function configMergeCells(chart: Chart, options: S2Options, dataConfig: S
|
||||
const fields = chart.data.fields || []
|
||||
const fieldsMap =
|
||||
fields.reduce((p, n) => {
|
||||
p[n.dataeaseName] = n
|
||||
p[n.gisbiName] = n
|
||||
return p
|
||||
}, {}) || {}
|
||||
const quotaIndex = dataConfig.meta.findIndex(m => fieldsMap[m.field]?.groupType === 'q')
|
||||
@ -1571,6 +1911,7 @@ export function configMergeCells(chart: Chart, options: S2Options, dataConfig: S
|
||||
if (showIndex && meta.colIndex === 0) {
|
||||
meta.fieldValue = getRowIndex(mergedCellsInfo, meta)
|
||||
}
|
||||
meta.deFieldType = fieldsMap[meta.valueField]?.deType
|
||||
return new CustomMergedCell(sheet, cells, meta)
|
||||
}
|
||||
}
|
||||
@ -1598,12 +1939,13 @@ export function getRowIndex(mergedCellsInfo: MergedCellInfo[][], meta: ViewMeta)
|
||||
}, 0)
|
||||
return curRangeStartIndex - lostCells + 1
|
||||
}
|
||||
|
||||
class CustomMergedCell extends MergedCell {
|
||||
protected drawBackgroundShape() {
|
||||
const allPoints = getPolygonPoints(this.cells)
|
||||
// 处理条件样式,这里没有用透明度
|
||||
// 因为合并的单元格是单独的图层,透明度降低的话会显示底下未合并的单元格,需要单独处理被覆盖的单元格
|
||||
const { backgroundColor: fill, backgroundColorOpacity: fillOpacity } = this.getBackgroundColor()
|
||||
const { backgroundColor: fill } = this.getBackgroundColor()
|
||||
const cellTheme = this.theme.dataCell.cell
|
||||
this.backgroundShape = renderPolygon(this, {
|
||||
points: allPoints,
|
||||
@ -1612,6 +1954,14 @@ class CustomMergedCell extends MergedCell {
|
||||
lineHeight: cellTheme.horizontalBorderWidth
|
||||
})
|
||||
}
|
||||
|
||||
drawTextShape(): void {
|
||||
if (this.meta.deFieldType === 7) {
|
||||
drawImage.apply(this)
|
||||
} else {
|
||||
super.drawTextShape()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomDataCell extends TableDataCell {
|
||||
@ -1847,96 +2197,95 @@ const getWrapTextHeight = (wrapText, textStyle, spreadsheet, maxLines) => {
|
||||
return Math.min(lines, maxLines) * maxHeight
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置汇总行
|
||||
* @param chart
|
||||
* @param s2Options
|
||||
* @param newData
|
||||
* @param tableHeader
|
||||
* @param basicStyle
|
||||
* @param showSummary
|
||||
*/
|
||||
export const configSummaryRow = (
|
||||
chart,
|
||||
s2Options,
|
||||
newData,
|
||||
tableHeader,
|
||||
basicStyle,
|
||||
showSummary
|
||||
) => {
|
||||
if (!showSummary || !newData.length) return
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[newData.length] = tableHeader.tableTitleHeight
|
||||
s2Options.style.rowCfg = { heightByField }
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1
|
||||
const yAxis = chart.yAxis
|
||||
const xAxis = chart.xAxis
|
||||
const summaryObj = newData.reduce(
|
||||
(p, n) => {
|
||||
if (chart.type === 'table-info') {
|
||||
xAxis
|
||||
.filter(axis => [2, 3, 4].includes(axis.deType))
|
||||
.forEach(axis => {
|
||||
p[axis.dataeaseName] =
|
||||
(parseFloat(n[axis.dataeaseName]) || 0) + (parseFloat(p[axis.dataeaseName]) || 0)
|
||||
// 导出获取汇总行的函数
|
||||
export function getSummaryRow(data, axis, sumCon = []) {
|
||||
const summaryObj = { SUMMARY: true }
|
||||
for (let i = 0; i < axis.length; i++) {
|
||||
const a = axis[i].gisbiName
|
||||
let savedAxis = find(sumCon, s => s.field === a)
|
||||
if (savedAxis) {
|
||||
if (savedAxis.summary == undefined) {
|
||||
savedAxis.summary = 'sum' // 默认汇总方式为求和
|
||||
}
|
||||
if (savedAxis.show == undefined) {
|
||||
savedAxis.show = true // 默认显示汇总结果
|
||||
}
|
||||
} else {
|
||||
savedAxis = {
|
||||
field: a,
|
||||
summary: 'sum',
|
||||
show: true
|
||||
}
|
||||
}
|
||||
// 如果配置为不显示,则跳过该字段
|
||||
if (!savedAxis.show) {
|
||||
continue
|
||||
}
|
||||
// 根据汇总方式处理数据
|
||||
switch (savedAxis.summary) {
|
||||
case 'sum':
|
||||
// 计算字段的总和
|
||||
summaryObj[a] = safeDecimalSum(data, a)
|
||||
break
|
||||
case 'avg':
|
||||
// 计算字段的平均值
|
||||
summaryObj[a] = safeDecimalMean(data, a)
|
||||
break
|
||||
case 'max':
|
||||
// 计算字段的最大值
|
||||
summaryObj[a] = maxBy(
|
||||
filter(data, d => parseFloat(d[a]) !== undefined),
|
||||
d => parseFloat(d[a]) // 提取数值
|
||||
)[a]
|
||||
break
|
||||
case 'min':
|
||||
// 计算字段的最小值
|
||||
summaryObj[a] = minBy(
|
||||
filter(data, d => parseFloat(d[a]) !== undefined),
|
||||
d => parseFloat(d[a]) // 提取数值
|
||||
)[a]
|
||||
break
|
||||
case 'var_pop':
|
||||
// 计算总体方差(需要至少2个数据点)
|
||||
if (data.length < 2) {
|
||||
continue
|
||||
} else {
|
||||
const mean = safeDecimalMean(data, a) // 计算平均值
|
||||
// 计算每个数据点与平均值的差的平方
|
||||
const squaredDeviations = map(data, d => {
|
||||
const value = new Decimal(d[a] ?? 0) // 获取字段值,如果不存在则使用0
|
||||
const dev = value.minus(mean) // 计算差值
|
||||
return dev.times(dev) // 计算平方
|
||||
})
|
||||
} else {
|
||||
yAxis.forEach(axis => {
|
||||
p[axis.dataeaseName] =
|
||||
(parseFloat(n[axis.dataeaseName]) || 0) + (parseFloat(p[axis.dataeaseName]) || 0)
|
||||
})
|
||||
}
|
||||
return p
|
||||
},
|
||||
{ SUMMARY: true }
|
||||
)
|
||||
newData.push(summaryObj)
|
||||
s2Options.dataCell = viewMeta => {
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
if (viewMeta.rowIndex !== newData.length - 1) {
|
||||
return new CustomDataCell(viewMeta, viewMeta.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex) {
|
||||
viewMeta.fieldValue = basicStyle.summaryLabel ?? i18nt('chart.total_show')
|
||||
} else {
|
||||
if (xAxis.length) {
|
||||
viewMeta.fieldValue = basicStyle.summaryLabel ?? i18nt('chart.total_show')
|
||||
// 计算方差(平方差的平均值)
|
||||
const variance = squaredDeviations.reduce((acc, val) => acc.plus(val), new Decimal(0))
|
||||
summaryObj[a] = variance.dividedBy(data.length - 1).toNumber() // 计算总体方差
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'stddev_pop':
|
||||
// 计算总体标准差(需要至少2个数据点)
|
||||
if (data.length < 2) {
|
||||
continue
|
||||
} else {
|
||||
const mean = safeDecimalMean(data, a) // 计算平均值
|
||||
// 计算每个数据点与平均值的差的平方
|
||||
const squaredDeviations = map(data, d => {
|
||||
const value = new Decimal(d[a] ?? 0) // 获取字段值,如果不存在则使用0
|
||||
const dev = value.minus(mean) // 计算差值
|
||||
return dev.times(dev) // 计算平方
|
||||
})
|
||||
// 计算方差(平方差的平均值)
|
||||
const variance = squaredDeviations.reduce((acc, val) => acc.plus(val), new Decimal(0))
|
||||
summaryObj[a] = variance.dividedBy(data.length - 1).sqrt().toNumber() // 计算总体标准差
|
||||
}
|
||||
break
|
||||
}
|
||||
return new SummaryCell(viewMeta, viewMeta.spreadsheet)
|
||||
}
|
||||
|
||||
// 返回汇总结果对象
|
||||
return summaryObj
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总行样式,紧贴在单元格后面
|
||||
* @param newChart
|
||||
* @param newData
|
||||
* @param tableCell
|
||||
* @param tableHeader
|
||||
* @param showSummary
|
||||
*/
|
||||
export const summaryRowStyle = (newChart, newData, tableCell, tableHeader, showSummary) => {
|
||||
if (!showSummary || !newData.length) return
|
||||
newChart.on(S2Event.LAYOUT_BEFORE_RENDER, () => {
|
||||
const showHeader = tableHeader.showTableHeader === true
|
||||
// 不显示表头时,减少一个表头的高度
|
||||
const headerAndSummaryHeight = showHeader ? 2 : 1
|
||||
const totalHeight =
|
||||
tableHeader.tableTitleHeight * headerAndSummaryHeight +
|
||||
tableCell.tableItemHeight * (newData.length - 1)
|
||||
if (totalHeight < newChart.options.height) {
|
||||
// 6 是阴影高度
|
||||
newChart.options.height =
|
||||
totalHeight < newChart.options.height - 6 ? totalHeight + 6 : totalHeight
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export class SummaryCell extends CustomDataCell {
|
||||
getTextStyle() {
|
||||
@ -1944,6 +2293,7 @@ export class SummaryCell extends CustomDataCell {
|
||||
textStyle.textAlign = this.theme.dataCell.text.textAlign
|
||||
return textStyle
|
||||
}
|
||||
|
||||
getBackgroundColor() {
|
||||
const { backgroundColor, backgroundColorOpacity } = this.theme.colCell.cell
|
||||
return { backgroundColor, backgroundColorOpacity }
|
||||
@ -2019,3 +2369,27 @@ export const getColumns = (fields, cols: Array<ColumnNode>) => {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function drawImage() {
|
||||
const img = new Image()
|
||||
const { x, y, width, height, fieldValue } = this.meta
|
||||
img.src = fieldValue as string
|
||||
img.setAttribute('crossOrigin', 'anonymous')
|
||||
img.onload = () => {
|
||||
!this.cfg.children && (this.cfg.children = [])
|
||||
const { width: imgWidth, height: imgHeight } = img
|
||||
const ratio = Math.max(imgWidth / width, imgHeight / height)
|
||||
// 不铺满,部分留白
|
||||
const imgShowWidth = (imgWidth / ratio) * 0.8
|
||||
const imgShowHeight = (imgHeight / ratio) * 0.8
|
||||
this.textShape = this.addShape('image', {
|
||||
attrs: {
|
||||
x: x + (imgShowWidth < width ? (width - imgShowWidth) / 2 : 0),
|
||||
y: y + (imgShowHeight < height ? (height - imgShowHeight) / 2 : 0),
|
||||
width: imgShowWidth,
|
||||
height: imgShowHeight,
|
||||
img
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
2404
frontend/src/data-visualization/chart/components/js/panel/common/dist/common_antv.js
vendored
Normal file
2404
frontend/src/data-visualization/chart/components/js/panel/common/dist/common_antv.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2442
frontend/src/data-visualization/chart/components/js/panel/common/dist/common_table.js
vendored
Normal file
2442
frontend/src/data-visualization/chart/components/js/panel/common/dist/common_table.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -170,7 +170,7 @@ export abstract class G2PlotChartView<
|
||||
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
|
||||
return setupSeriesColor(chart, data)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
public setupSubSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
|
||||
return undefined
|
||||
}
|
||||
@ -191,8 +191,8 @@ export abstract class G2PlotChartView<
|
||||
return addConditionsStyleColorToData(chart, data)
|
||||
}
|
||||
|
||||
protected configEmptyDataStyle(newChart, newData: any[], container: string) {
|
||||
configEmptyDataStyle(newChart, newData, container)
|
||||
protected configEmptyDataStyle(newData, container, newChart?, content?) {
|
||||
configEmptyDataStyle(newData, container, newChart, content)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,8 +107,8 @@ export abstract class L7ChartView<
|
||||
return options
|
||||
}
|
||||
|
||||
protected configZoomButton(chart: Chart, plot: S) {
|
||||
configL7Zoom(chart, plot)
|
||||
protected configZoomButton(chart: Chart, plot: S, mapKey?: any) {
|
||||
configL7Zoom(chart, plot, mapKey)
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: O): O {
|
||||
|
@ -136,18 +136,18 @@ export abstract class S2ChartView<P extends SpreadSheet> extends AntVAbstractCha
|
||||
if (duration > 300) {
|
||||
return
|
||||
}
|
||||
const canvasPosition = canvas.getBoundingClientRect()
|
||||
const touchPosition = [e.changedTouches[0].pageX, e.changedTouches[0].pageY]
|
||||
const relativePosition = [
|
||||
touchPosition[0] - canvasPosition.x,
|
||||
touchPosition[1] - canvasPosition.y
|
||||
]
|
||||
const shape = s2Instance.container.getShape(relativePosition[0], relativePosition[1])
|
||||
// 图片单元格,表头排序图标点击放大图片
|
||||
if (shape.cfg?.type === 'image') {
|
||||
return
|
||||
}
|
||||
const callback = () => {
|
||||
const canvasPosition = canvas.getBoundingClientRect()
|
||||
const touchPosition = [e.changedTouches[0].pageX, e.changedTouches[0].pageY]
|
||||
const relativePosition = [
|
||||
touchPosition[0] - canvasPosition.x,
|
||||
touchPosition[1] - canvasPosition.y
|
||||
]
|
||||
const shape = s2Instance.container.getShape(relativePosition[0], relativePosition[1])
|
||||
// 图片单元格点击放大图片
|
||||
if (shape.cfg?.parent.constructor.name === 'ImageCell') {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (shape) {
|
||||
|
Loading…
Reference in New Issue
Block a user