forked from github/dataease
feat(图表): 仪表盘支持隐藏刻度标签和显示数值格式的标签 #9510
This commit is contained in:
parent
18965a389e
commit
57935c4016
@ -1165,7 +1165,9 @@ export default {
|
||||
top_n_input_2: ', 其余合并至其他',
|
||||
top_n_label: '其他项名称',
|
||||
progress_target: '目标值',
|
||||
progress_current: '实际值'
|
||||
progress_current: '实际值',
|
||||
gauge_axis_label: '显示刻度',
|
||||
gauge_percentage_tick: '百分比刻度'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: '仅编辑时生效',
|
||||
|
@ -104,6 +104,14 @@ declare interface ChartBasicStyle {
|
||||
* 仪表盘样式
|
||||
*/
|
||||
gaugeStyle: string
|
||||
/**
|
||||
* 仪表盘刻度显示
|
||||
*/
|
||||
gaugeAxisLine: boolean
|
||||
/**
|
||||
* 仪表盘百分比刻度
|
||||
*/
|
||||
gaugePercentLabel: boolean
|
||||
/**
|
||||
* 配色方案
|
||||
*/
|
||||
|
@ -231,7 +231,12 @@ init()
|
||||
<div @keydown.stop @keyup.stop style="width: 100%; margin-bottom: 16px">
|
||||
<!--仪表盘-->
|
||||
<el-col v-show="showProperty('gaugeThreshold')">
|
||||
<el-form ref="thresholdForm" :model="state.thresholdForm" label-position="top">
|
||||
<el-form
|
||||
:model="state.thresholdForm"
|
||||
ref="thresholdForm"
|
||||
label-position="top"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item
|
||||
:label="t('chart.threshold_range') + '(%)'"
|
||||
class="form-item"
|
||||
@ -261,7 +266,12 @@ init()
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col v-show="showProperty('liquidThreshold')">
|
||||
<el-form ref="thresholdForm" :model="state.thresholdForm" label-position="top">
|
||||
<el-form
|
||||
:model="state.thresholdForm"
|
||||
ref="thresholdForm"
|
||||
label-position="top"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item
|
||||
:label="t('chart.threshold_range') + '(%)'"
|
||||
class="form-item"
|
||||
|
@ -777,6 +777,34 @@ onMounted(() => {
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="showProperty('gaugeAxisLine')"
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-checkbox
|
||||
v-model="state.basicStyleForm.gaugeAxisLine"
|
||||
:effect="themes"
|
||||
size="small"
|
||||
@change="changeBasicStyle('gaugeAxisLine')"
|
||||
>
|
||||
{{ t('chart.gauge_axis_label') }}</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="showProperty('gaugePercentLabel') && state.basicStyleForm.gaugeAxisLine"
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-checkbox
|
||||
v-model="state.basicStyleForm.gaugePercentLabel"
|
||||
:effect="themes"
|
||||
size="small"
|
||||
@change="changeBasicStyle('gaugePercentLabel')"
|
||||
>
|
||||
{{ t('chart.gauge_percentage_tick') }}</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
<!--gauge end-->
|
||||
<!--bar start-->
|
||||
<el-form-item
|
||||
|
@ -3291,7 +3291,7 @@ span {
|
||||
}
|
||||
|
||||
:deep(.ed-tabs__content) {
|
||||
height: calc(100% - 33px);
|
||||
height: calc(100% - 35px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
@ -1435,7 +1435,9 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
tableLayoutMode: 'grid',
|
||||
calcTopN: false,
|
||||
topN: 5,
|
||||
topNLabel: '其他'
|
||||
topNLabel: '其他',
|
||||
gaugeAxisLine: true,
|
||||
gaugePercentLabel: true
|
||||
}
|
||||
|
||||
export const BASE_VIEW_CONFIG = {
|
||||
|
@ -95,7 +95,8 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
// 禁用线上地图数据
|
||||
customFetchGeoData: () => null
|
||||
}
|
||||
options = this.setupOptions(chart, options, drawOption, geoJson)
|
||||
const context = { drawOption, geoJson }
|
||||
options = this.setupOptions(chart, options, context)
|
||||
const view = new Choropleth(container, options)
|
||||
const dotLayer = this.getDotLayer(chart, geoJson, drawOption)
|
||||
this.configZoomButton(chart, view)
|
||||
@ -170,10 +171,10 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
private configBasicStyle(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
extra: any[]
|
||||
context: Record<string, any>
|
||||
): ChoroplethOptions {
|
||||
const { areaId }: L7PlotDrawOptions<any> = extra[0]
|
||||
const geoJson: FeatureCollection = extra[1]
|
||||
const { areaId }: L7PlotDrawOptions<any> = context.drawOption
|
||||
const geoJson: FeatureCollection = context.geoJson
|
||||
const { basicStyle, label } = parseJson(chart.customAttr)
|
||||
const senior = parseJson(chart.senior)
|
||||
const curAreaNameMapping = senior.areaMapping?.[areaId]
|
||||
@ -208,7 +209,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
protected setupOptions(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
...extra: any[]
|
||||
context: Record<string, any>
|
||||
): ChoroplethOptions {
|
||||
return flow(
|
||||
this.configEmptyDataStrategy,
|
||||
@ -216,6 +217,6 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
this.configStyle,
|
||||
this.configTooltip,
|
||||
this.configBasicStyle
|
||||
)(chart, options, extra)
|
||||
)(chart, options, context)
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,8 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
// 禁用线上地图数据
|
||||
customFetchGeoData: () => null
|
||||
}
|
||||
options = this.setupOptions(chart, options, drawOption, geoJson)
|
||||
const context = { drawOption, geoJson }
|
||||
options = this.setupOptions(chart, options, context)
|
||||
const view = new Choropleth(container, options)
|
||||
this.configZoomButton(chart, view)
|
||||
view.once('loaded', () => {
|
||||
@ -120,10 +121,10 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
private configBasicStyle(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
extra: any[]
|
||||
context: Record<string, any>
|
||||
): ChoroplethOptions {
|
||||
const { areaId }: L7PlotDrawOptions<any> = extra[0]
|
||||
const geoJson: FeatureCollection = extra[1]
|
||||
const { areaId }: L7PlotDrawOptions<any> = context.drawOption
|
||||
const geoJson: FeatureCollection = context.geoJson
|
||||
const { basicStyle, label } = parseJson(chart.customAttr)
|
||||
const senior = parseJson(chart.senior)
|
||||
const curAreaNameMapping = senior.areaMapping?.[areaId]
|
||||
@ -176,7 +177,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
protected setupOptions(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
...extra: any[]
|
||||
context: Record<string, any>
|
||||
): ChoroplethOptions {
|
||||
return flow(
|
||||
this.configEmptyDataStrategy,
|
||||
@ -185,6 +186,6 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
this.configTooltip,
|
||||
this.configBasicStyle,
|
||||
this.configLegend
|
||||
)(chart, options, extra)
|
||||
)(chart, options, context)
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { merge } from 'lodash-es'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -28,7 +29,7 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
]
|
||||
propertyInner: EditorPropertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
'basic-style-selector': ['colors', 'alpha', 'gaugeStyle', 'gradient'],
|
||||
'basic-style-selector': ['colors', 'alpha', 'gradient', 'gaugeAxisLine', 'gaugePercentLabel'],
|
||||
'label-selector': ['fontSize', 'color', 'labelFormatter'],
|
||||
'title-selector': [
|
||||
'title',
|
||||
@ -77,10 +78,6 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
label: {
|
||||
style: {
|
||||
fontSize: getScaleValue(12, scale) // 刻度值字体大小
|
||||
},
|
||||
formatter: function (v) {
|
||||
const r = parseFloat(v)
|
||||
return v === '0' || !r ? v : r * 100 + '%'
|
||||
}
|
||||
},
|
||||
tickLine: {
|
||||
@ -98,11 +95,15 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
}
|
||||
}
|
||||
}
|
||||
const options = this.setupOptions(chart, initOptions, scale)
|
||||
const options = this.setupOptions(chart, initOptions, { scale })
|
||||
return new G2Gauge(container, options)
|
||||
}
|
||||
|
||||
protected configMisc(chart: Chart, options: GaugeOptions): GaugeOptions {
|
||||
protected configMisc(
|
||||
chart: Chart,
|
||||
options: GaugeOptions,
|
||||
context: Record<string, any>
|
||||
): GaugeOptions {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const data = chart.data.series[0].data[0]
|
||||
let min, max, startAngle, endAngle
|
||||
@ -123,6 +124,8 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
}
|
||||
startAngle = (misc.gaugeStartAngle * Math.PI) / 180
|
||||
endAngle = (misc.gaugeEndAngle * Math.PI) / 180
|
||||
context.min = min
|
||||
context.max = max
|
||||
}
|
||||
const percent = (parseFloat(data) - parseFloat(min)) / (parseFloat(max) - parseFloat(min))
|
||||
const tmp = {
|
||||
@ -133,8 +136,12 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
return { ...options, ...tmp }
|
||||
}
|
||||
|
||||
private configRange(chart: Chart, options: GaugeOptions, extra: any[]): GaugeOptions {
|
||||
const [scale] = extra
|
||||
private configRange(
|
||||
chart: Chart,
|
||||
options: GaugeOptions,
|
||||
context: Record<string, any>
|
||||
): GaugeOptions {
|
||||
const { scale } = context
|
||||
const range = [0]
|
||||
let index = 0
|
||||
let flag = false
|
||||
@ -216,36 +223,55 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
return { ...options, ...rangOptions }
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: GaugeOptions): GaugeOptions {
|
||||
protected configLabel(
|
||||
chart: Chart,
|
||||
options: GaugeOptions,
|
||||
context?: Record<string, any>
|
||||
): GaugeOptions {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const data = chart.data.series[0].data[0]
|
||||
let labelContent
|
||||
if (customAttr.label) {
|
||||
const label = customAttr.label
|
||||
const labelFormatter = label.labelFormatter ?? DEFAULT_LABEL.labelFormatter
|
||||
if (label.show) {
|
||||
labelContent = {
|
||||
style: () => ({
|
||||
fontSize: label.fontSize,
|
||||
color: label.color
|
||||
}),
|
||||
formatter: function () {
|
||||
let value
|
||||
if (labelFormatter.type === 'percent') {
|
||||
value = options.percent
|
||||
} else {
|
||||
value = data
|
||||
}
|
||||
return valueFormatter(value, labelFormatter)
|
||||
let labelContent: GaugeOptions['statistic']['content'] = false
|
||||
const label = customAttr.label
|
||||
const labelFormatter = label.labelFormatter ?? DEFAULT_LABEL.labelFormatter
|
||||
if (label.show) {
|
||||
labelContent = {
|
||||
style: {
|
||||
fontSize: `${label.fontSize}`,
|
||||
color: label.color
|
||||
},
|
||||
formatter: function () {
|
||||
let value
|
||||
if (labelFormatter.type === 'percent') {
|
||||
value = options.percent
|
||||
} else {
|
||||
value = data
|
||||
}
|
||||
return valueFormatter(value, labelFormatter)
|
||||
}
|
||||
} else {
|
||||
labelContent = false
|
||||
}
|
||||
} as GaugeOptions['statistic']['content']
|
||||
}
|
||||
const statistic = {
|
||||
content: labelContent
|
||||
}
|
||||
const { gaugeAxisLine, gaugePercentLabel } = customAttr.basicStyle
|
||||
const { min, max } = context
|
||||
const tmp = {
|
||||
axis: {
|
||||
label: {
|
||||
formatter: v => {
|
||||
if (gaugeAxisLine === false) {
|
||||
return ''
|
||||
}
|
||||
if (gaugePercentLabel === false) {
|
||||
const val = v === '0' ? min : v === '1' ? max : min + (max - min) * v
|
||||
return valueFormatter(val, labelFormatter)
|
||||
}
|
||||
return v === '0' ? v : v * 100 + '%'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
options = merge(options, tmp)
|
||||
return { ...options, statistic }
|
||||
}
|
||||
|
||||
@ -263,13 +289,17 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
|
||||
return chart
|
||||
}
|
||||
|
||||
protected setupOptions(chart: Chart, options: GaugeOptions, ...extra: any[]): GaugeOptions {
|
||||
protected setupOptions(
|
||||
chart: Chart,
|
||||
options: GaugeOptions,
|
||||
context: Record<string, any>
|
||||
): GaugeOptions {
|
||||
return flow(
|
||||
this.configTheme,
|
||||
this.configMisc,
|
||||
this.configLabel,
|
||||
this.configRange
|
||||
)(chart, options, extra)
|
||||
)(chart, options, context)
|
||||
}
|
||||
constructor() {
|
||||
super('gauge', DEFAULT_DATA)
|
||||
|
@ -139,7 +139,7 @@ export abstract class G2PlotChartView<
|
||||
* @param chart 数据库图表对象。
|
||||
* @param options 各个图表的参数,泛化的 Options,可以自行扩展,比如加个扩展 X 轴或者扩展 Y 轴字段。
|
||||
*/
|
||||
protected abstract setupOptions(chart: Chart, options: O): O
|
||||
protected abstract setupOptions(chart: Chart, options: O, context?: Record<string, any>): O
|
||||
protected constructor(name: string, defaultData: any[]) {
|
||||
super(ChartLibraryType.G2_PLOT, name, defaultData)
|
||||
}
|
||||
|
@ -81,5 +81,5 @@ export abstract class L7PlotChartView<
|
||||
super(ChartLibraryType.L7_PLOT, name)
|
||||
this.defaultData = defaultData
|
||||
}
|
||||
protected abstract setupOptions(chart: Chart, options: O): O
|
||||
protected abstract setupOptions(chart: Chart, options: O, context?: Record<string, any>): O
|
||||
}
|
||||
|
@ -388,12 +388,12 @@ export function parseJson<T>(str: T | JSONString<T>): T {
|
||||
return JSON.parse(str) as T
|
||||
}
|
||||
|
||||
type FlowFunction<P, R> = (param: P, result: R, extra?: any[]) => R
|
||||
type FlowFunction<P, R> = (param: P, result: R, context?: Record<string, any>) => R
|
||||
|
||||
export function flow<P, R>(...flows: FlowFunction<P, R>[]): FlowFunction<P, R> {
|
||||
return (param: P, result: R, extra?: any[]) => {
|
||||
return (param: P, result: R, context?: Record<string, any>) => {
|
||||
return flows.reduce((result: R, flow: FlowFunction<P, R>) => {
|
||||
return flow(param, result, extra)
|
||||
return flow(param, result, context)
|
||||
}, result)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user