+import { onMounted, PropType, reactive, watch, ref } from 'vue'
+import { COLOR_PANEL, DEFAULT_MISC } from '@/views/chart/components/editor/util/chart'
+import { useI18n } from '@/hooks/web/useI18n'
+import CustomColorStyleSelect from '@/views/chart/components/editor/editor-style/components/CustomColorStyleSelect.vue'
+import { cloneDeep, defaultsDeep } from 'lodash-es'
+import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
+import { storeToRefs } from 'pinia'
+import {
+ CHART_MIX_DEFAULT_BASIC_STYLE,
+ MixChartBasicStyle
+} from '@/views/chart/components/js/panel/charts/others/chart-mix-common'
+
+const dvMainStore = dvMainStoreWithOut()
+const { batchOptStatus } = storeToRefs(dvMainStore)
+const { t } = useI18n()
+const props = defineProps({
+ chart: {
+ type: Object as PropType
,
+ required: true
+ },
+ themes: {
+ type: String as PropType,
+ default: 'dark'
+ },
+ propertyInner: {
+ type: Array
+ }
+})
+
+const showProperty = prop => props.propertyInner?.includes(prop)
+const predefineColors = COLOR_PANEL
+const state = reactive({
+ basicStyleForm: JSON.parse(JSON.stringify(CHART_MIX_DEFAULT_BASIC_STYLE)) as MixChartBasicStyle,
+ miscForm: JSON.parse(JSON.stringify(DEFAULT_MISC)) as ChartMiscAttr,
+ customColor: null,
+ colorIndex: 0,
+ fieldColumnWidth: {
+ fieldId: '',
+ width: 0
+ }
+})
+watch(
+ [
+ () => props.chart.customAttr.basicStyle,
+ () => props.chart.customAttr.misc,
+ () => props.chart.customAttr.tableHeader,
+ () => props.chart.xAxis,
+ () => props.chart.yAxis
+ ],
+ () => {
+ init()
+ },
+ { deep: true }
+)
+const emit = defineEmits(['onBasicStyleChange', 'onMiscChange'])
+const changeBasicStyle = (prop?: string, requestData = false) => {
+ emit('onBasicStyleChange', { data: state.basicStyleForm, requestData }, prop)
+}
+const onAlphaChange = v => {
+ const _v = parseInt(v)
+ if (_v >= 0 && _v <= 100) {
+ state.basicStyleForm.alpha = _v
+ } else if (_v < 0) {
+ state.basicStyleForm.alpha = 0
+ } else if (_v > 100) {
+ state.basicStyleForm.alpha = 100
+ } else {
+ const basicStyle = cloneDeep(props.chart.customAttr.basicStyle)
+ const oldForm = defaultsDeep(
+ basicStyle,
+ cloneDeep(CHART_MIX_DEFAULT_BASIC_STYLE)
+ ) as ChartBasicStyle
+ state.basicStyleForm.alpha = oldForm.alpha
+ }
+ changeBasicStyle('alpha')
+}
+const onSubAlphaChange = v => {
+ const _v = parseInt(v)
+ if (_v >= 0 && _v <= 100) {
+ state.basicStyleForm.subAlpha = _v
+ } else if (_v < 0) {
+ state.basicStyleForm.subAlpha = 0
+ } else if (_v > 100) {
+ state.basicStyleForm.subAlpha = 100
+ } else {
+ const basicStyle = cloneDeep(props.chart.customAttr.basicStyle)
+ const oldForm = defaultsDeep(
+ basicStyle,
+ cloneDeep(CHART_MIX_DEFAULT_BASIC_STYLE)
+ ) as MixChartBasicStyle
+ state.basicStyleForm.subAlpha = oldForm.subAlpha
+ }
+ changeBasicStyle('alpha')
+}
+
+const init = () => {
+ const basicStyle = cloneDeep(props.chart.customAttr.basicStyle)
+ const miscStyle = cloneDeep(props.chart.customAttr.misc)
+ configCompat(basicStyle)
+ state.basicStyleForm = defaultsDeep(
+ basicStyle,
+ cloneDeep(CHART_MIX_DEFAULT_BASIC_STYLE)
+ ) as MixChartBasicStyle
+ state.miscForm = defaultsDeep(miscStyle, cloneDeep(DEFAULT_MISC)) as ChartMiscAttr
+ if (!state.customColor) {
+ state.customColor = state.basicStyleForm.colors[0]
+ state.colorIndex = 0
+ }
+}
+const configCompat = (basicStyle: ChartBasicStyle) => {
+ // 悬浮改为图例和缩放按钮
+ if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
+ basicStyle.showZoom = false
+ }
+}
+const symbolOptions = [
+ { name: t('chart.line_symbol_circle'), value: 'circle' },
+ { name: t('chart.line_symbol_rect'), value: 'square' },
+ { name: t('chart.line_symbol_triangle'), value: 'triangle' },
+ { name: t('chart.line_symbol_diamond'), value: 'diamond' }
+]
+
+const activeName = ref<'left' | 'right'>('left')
+
+onMounted(() => {
+ init()
+})
+
+
+
+
+
+
+ changeBasicStyle(prop)"
+ />
+
+
+
+
+ {{ $t('chart.gradient') }}{{ $t('chart.color') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %
+
+
+
+
+
+
+
+
+ {{ t('chart.rightAngle') }}
+ {{ t('chart.roundAngle') }}
+
+
+
+
+
+ changeBasicStyle(prop)"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('chart.line_smooth') }}
+
+
+
+
+
+
+
diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix-common.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix-common.ts
index eef7cc0c90..ac6b0d8d35 100644
--- a/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix-common.ts
+++ b/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix-common.ts
@@ -1,6 +1,8 @@
+import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart'
+
export const CHART_MIX_EDITOR_PROPERTY: EditorProperty[] = [
'background-overall-component',
- 'basic-style-selector',
+ 'dual-basic-style-selector',
'x-axis-selector',
'dual-y-axis-selector',
'title-selector',
@@ -16,7 +18,7 @@ export const CHART_MIX_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
'background-overall-component': ['all'],
'label-selector': ['fontSize', 'color'],
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'show'],
- 'basic-style-selector': [
+ 'dual-basic-style-selector': [
'colors',
'alpha',
'gradient',
@@ -24,7 +26,8 @@ export const CHART_MIX_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
'lineSymbol',
'lineSymbolSize',
'lineSmooth',
- 'radiusColumnBar'
+ 'radiusColumnBar',
+ 'subSeriesColor'
],
'x-axis-selector': [
'name',
@@ -69,3 +72,40 @@ export const CHART_MIX_AXIS_TYPE: AxisType[] = [
'extLabel',
'extTooltip'
]
+
+export const CHART_MIX_DEFAULT_BASIC_STYLE = {
+ ...DEFAULT_BASIC_STYLE,
+ subAlpha: 100,
+ subColorScheme: 'fast',
+ subSeriesColor: [],
+ subColors: [
+ '#fae800',
+ '#00c039',
+ '#0482dc',
+ '#bb9581',
+ '#ff7701',
+ '#9c5ec3',
+ '#00ccdf',
+ '#00c039',
+ '#ff7701'
+ ]
+}
+
+export interface MixChartBasicStyle extends ChartBasicStyle {
+ subAlpha: number
+ subColors: string[]
+ subSeriesColor: {
+ /**
+ * 序列识别id,多指标就是轴id,分组或者堆叠就是类别值
+ */
+ id: string
+ /**
+ * 显示名称
+ */
+ name: string
+ /**
+ * 序列颜色
+ */
+ color: string
+ }[]
+}
diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts
index ec92c65fc6..764cb46edc 100644
--- a/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts
+++ b/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts
@@ -12,16 +12,19 @@ import {
setGradientColor
} from '../../common/common_antv'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
-import { cloneDeep, isEmpty, defaultTo, map, filter, union, slice } from 'lodash-es'
+import { cloneDeep, isEmpty, defaultTo, map, filter, union, defaultsDeep } from 'lodash-es'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import {
CHART_MIX_AXIS_TYPE,
+ CHART_MIX_DEFAULT_BASIC_STYLE,
CHART_MIX_EDITOR_PROPERTY,
- CHART_MIX_EDITOR_PROPERTY_INNER
+ CHART_MIX_EDITOR_PROPERTY_INNER,
+ MixChartBasicStyle
} from './chart-mix-common'
import { Datum } from '@antv/g2plot/esm/types/common'
import { useI18n } from '@/hooks/web/useI18n'
import { DEFAULT_LABEL } from '@/views/chart/components/editor/util/chart'
+import { Options } from '@antv/g2plot/esm'
const { t } = useI18n()
const DEFAULT_DATA = []
@@ -74,8 +77,8 @@ export class ColumnLineMix extends G2PlotChartView {
const isGroup = this.name === 'chart-mix-group' && chart.xAxisExt?.length > 0
const isStack = this.name === 'chart-mix-stack' && chart.extStack?.length > 0
- const seriesField = isGroup ? 'category' : isStack ? 'category' : undefined
- const seriesField2 = chart.extBubble?.length > 0 ? 'category' : undefined
+ const seriesField = 'category'
+ const seriesField2 = 'category'
const data1 = defaultTo(left[0]?.data, [])
const data2 = map(defaultTo(right[0]?.data, []), d => {
@@ -85,29 +88,6 @@ export class ColumnLineMix extends G2PlotChartView {
}
})
- // custom color
- const customAttr = parseJson(chart.customAttr)
- let color = customAttr.basicStyle.colors
-
- const colorSize = color.length
-
- color = color.map(ele => {
- const tmp = hexColorToRGBA(ele, customAttr.basicStyle.alpha)
- if (customAttr.basicStyle.gradient) {
- return setGradientColor(tmp, true, 270)
- } else {
- return tmp
- }
- })
-
- const color2StartNum = defaultTo(left[0]?.categories?.length, 1)
- const color2StartIndex = color2StartNum % colorSize
-
- const color2 =
- color2StartIndex === 0
- ? cloneDeep(color)
- : union(slice(color, color2StartIndex), slice(color, 0, color2StartIndex))
-
// options
const initOptions: DualAxesOptions = {
data: [data1, data2],
@@ -117,15 +97,14 @@ export class ColumnLineMix extends G2PlotChartView {
geometryOptions: [
{
geometry: data1Type,
- color: isGroup || isStack ? color : color[0],
-
+ color: [],
isGroup: isGroup,
isStack: isStack,
seriesField: seriesField
},
{
geometry: data2Type,
- color: seriesField2 ? color2 : color2[0],
+ color: [],
seriesField: seriesField2
}
],
@@ -295,12 +274,108 @@ export class ColumnLineMix extends G2PlotChartView {
}
protected configCustomColors(chart: Chart, options: DualAxesOptions): DualAxesOptions {
- const basicStyle = parseJson(chart.customAttr).basicStyle
- const color = basicStyle.colors.map(item => hexColorToRGBA(item, basicStyle.alpha))
- return {
- ...options,
- color
+ const tempOption = {
+ ...options
}
+ const basicStyle = parseJson(chart.customAttr).basicStyle as MixChartBasicStyle
+ //左轴
+ const color = basicStyle.colors.map(ele => {
+ const tmp = hexColorToRGBA(ele, basicStyle.alpha)
+ if (basicStyle.gradient) {
+ return setGradientColor(tmp, true, 270)
+ } else {
+ return tmp
+ }
+ })
+ tempOption.geometryOptions[0].color = color
+
+ return tempOption
+ }
+
+ protected configSubCustomColors(chart: Chart, options: DualAxesOptions): DualAxesOptions {
+ const tempOption = {
+ ...options
+ }
+ const basicStyle = defaultsDeep(
+ parseJson(chart.customAttr).basicStyle as MixChartBasicStyle,
+ cloneDeep(CHART_MIX_DEFAULT_BASIC_STYLE)
+ )
+ //右轴
+ const { subSeriesColor } = basicStyle
+ if (subSeriesColor?.length) {
+ const { yAxisExt, extBubble } = chart
+ const seriesMap = subSeriesColor.reduce((p, n) => {
+ p[n.id] = n
+ return p
+ }, {})
+ const { data } = options as unknown as Options
+ if (extBubble?.length) {
+ const seriesSet = new Set()
+ data[1]?.forEach(d => d.category !== null && seriesSet.add(d.category))
+ const tmp = [...seriesSet]
+ tmp.forEach((c, i) => {
+ const curAxisColor = seriesMap[c as string]
+ if (curAxisColor) {
+ if (i + 1 > basicStyle.subColors.length) {
+ basicStyle.subColors.push(curAxisColor.color)
+ } else {
+ basicStyle.subColors[i] = curAxisColor.color
+ }
+ }
+ })
+ } else {
+ yAxisExt?.forEach((axis, index) => {
+ const curAxisColor = seriesMap[axis.id]
+ if (curAxisColor) {
+ if (index + 1 > basicStyle.subColors.length) {
+ basicStyle.subColors.push(curAxisColor.color)
+ } else {
+ basicStyle.subColors[index] = curAxisColor.color
+ }
+ }
+ })
+ }
+ }
+ const subColor = basicStyle.subColors.map(c => {
+ const cc = hexColorToRGBA(c, basicStyle.subAlpha)
+ return cc
+ })
+ tempOption.geometryOptions[1].color = subColor
+
+ return tempOption
+ }
+
+ public setupSubSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
+ const result: ChartBasicStyle['seriesColor'] = []
+ const seriesSet = new Set()
+ const colors = chart.customAttr.basicStyle.subColors ?? chart.customAttr.basicStyle.colors
+ const { yAxisExt, extBubble } = chart
+ if (extBubble?.length) {
+ data?.forEach(d => {
+ if (d.value === null || d.category === null || seriesSet.has(d.category)) {
+ return
+ }
+ seriesSet.add(d.category)
+ result.push({
+ id: d.category,
+ name: d.category,
+ color: colors[(seriesSet.size - 1) % colors.length]
+ })
+ })
+ } else {
+ yAxisExt?.forEach(axis => {
+ if (seriesSet.has(axis.id)) {
+ return
+ }
+ seriesSet.add(axis.id)
+ result.push({
+ id: axis.id,
+ name: axis.chartShowName ?? axis.name,
+ color: colors[(seriesSet.size - 1) % colors.length]
+ })
+ })
+ }
+ return result
}
protected configYAxis(chart: Chart, options: DualAxesOptions): DualAxesOptions {
@@ -473,6 +548,7 @@ export class ColumnLineMix extends G2PlotChartView {
this.configTooltip,
this.configBasicStyle,
this.configCustomColors,
+ this.configSubCustomColors,
this.configLegend,
this.configXAxis,
this.configYAxis,
@@ -489,6 +565,18 @@ export class ColumnLineMix extends G2PlotChartView {
export class GroupColumnLineMix extends ColumnLineMix {
axis: AxisType[] = [...this['axis'], 'xAxisExt']
+ propertyInner = {
+ ...CHART_MIX_EDITOR_PROPERTY_INNER,
+ 'dual-basic-style-selector': [
+ ...CHART_MIX_EDITOR_PROPERTY_INNER['dual-basic-style-selector'],
+ 'seriesColor'
+ ],
+ 'label-selector': ['vPosition', 'seriesLabelFormatter'],
+ 'tooltip-selector': [
+ ...CHART_MIX_EDITOR_PROPERTY_INNER['tooltip-selector'],
+ 'seriesTooltipFormatter'
+ ]
+ }
axisConfig = {
...this['axisConfig'],
yAxis: {
@@ -497,12 +585,113 @@ export class GroupColumnLineMix extends ColumnLineMix {
type: 'q'
}
}
+
+ protected configCustomColors(chart: Chart, options: DualAxesOptions): DualAxesOptions {
+ const tempOption = {
+ ...options
+ }
+ const basicStyle = parseJson(chart.customAttr).basicStyle as MixChartBasicStyle
+
+ const { seriesColor } = basicStyle
+ if (seriesColor?.length) {
+ const seriesMap = seriesColor.reduce((p, n) => {
+ p[n.id] = n
+ return p
+ }, {})
+ const { yAxis, xAxisExt } = chart
+ const { data } = options as unknown as Options
+ if (xAxisExt?.length) {
+ const seriesSet = new Set()
+ data[0]?.forEach(d => d.category !== null && seriesSet.add(d.category))
+ const tmp = [...seriesSet]
+ tmp.forEach((c, i) => {
+ const curAxisColor = seriesMap[c as string]
+ if (curAxisColor) {
+ if (i + 1 > basicStyle.colors.length) {
+ basicStyle.colors.push(curAxisColor.color)
+ } else {
+ basicStyle.colors[i] = curAxisColor.color
+ }
+ }
+ })
+ } else {
+ yAxis?.forEach((axis, index) => {
+ const curAxisColor = seriesMap[axis.id]
+ if (curAxisColor) {
+ if (index + 1 > basicStyle.colors.length) {
+ basicStyle.colors.push(curAxisColor.color)
+ } else {
+ basicStyle.colors[index] = curAxisColor.color
+ }
+ }
+ })
+ }
+ }
+ //左轴
+ const color = basicStyle.colors.map(ele => {
+ const tmp = hexColorToRGBA(ele, basicStyle.alpha)
+ if (basicStyle.gradient) {
+ return setGradientColor(tmp, true, 270)
+ } else {
+ return tmp
+ }
+ })
+ tempOption.geometryOptions[0].color = color
+
+ return tempOption
+ }
+
+ public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
+ const result: ChartBasicStyle['seriesColor'] = []
+ const seriesSet = new Set()
+ const colors = chart.customAttr.basicStyle.colors
+ const { yAxis, xAxisExt } = chart
+ if (xAxisExt?.length) {
+ data?.forEach(d => {
+ if (d.value === null || d.category === null || seriesSet.has(d.category)) {
+ return
+ }
+ seriesSet.add(d.category)
+ result.push({
+ id: d.category,
+ name: d.category,
+ color: colors[(seriesSet.size - 1) % colors.length]
+ })
+ })
+ } else {
+ yAxis?.forEach(axis => {
+ if (seriesSet.has(axis.id)) {
+ return
+ }
+ seriesSet.add(axis.id)
+ result.push({
+ id: axis.id,
+ name: axis.chartShowName ?? axis.name,
+ color: colors[(seriesSet.size - 1) % colors.length]
+ })
+ })
+ }
+ return result
+ }
+
constructor(name = 'chart-mix-group') {
super(name)
}
}
export class StackColumnLineMix extends ColumnLineMix {
axis: AxisType[] = [...this['axis'], 'extStack']
+ propertyInner = {
+ ...CHART_MIX_EDITOR_PROPERTY_INNER,
+ 'dual-basic-style-selector': [
+ ...CHART_MIX_EDITOR_PROPERTY_INNER['dual-basic-style-selector'],
+ 'seriesColor'
+ ],
+ 'label-selector': ['vPosition', 'seriesLabelFormatter'],
+ 'tooltip-selector': [
+ ...CHART_MIX_EDITOR_PROPERTY_INNER['tooltip-selector'],
+ 'seriesTooltipFormatter'
+ ]
+ }
axisConfig = {
...this['axisConfig'],
yAxis: {
@@ -511,6 +700,95 @@ export class StackColumnLineMix extends ColumnLineMix {
type: 'q'
}
}
+
+ protected configCustomColors(chart: Chart, options: DualAxesOptions): DualAxesOptions {
+ const tempOption = {
+ ...options
+ }
+ const basicStyle = parseJson(chart.customAttr).basicStyle as MixChartBasicStyle
+
+ const { seriesColor } = basicStyle
+ if (seriesColor?.length) {
+ const seriesMap = seriesColor.reduce((p, n) => {
+ p[n.id] = n
+ return p
+ }, {})
+ const { yAxis, extStack } = chart
+ const { data } = options as unknown as Options
+ if (extStack?.length) {
+ const seriesSet = new Set()
+ data[0]?.forEach(d => d.category !== null && seriesSet.add(d.category))
+ const tmp = [...seriesSet]
+ tmp.forEach((c, i) => {
+ const curAxisColor = seriesMap[c as string]
+ if (curAxisColor) {
+ if (i + 1 > basicStyle.colors.length) {
+ basicStyle.colors.push(curAxisColor.color)
+ } else {
+ basicStyle.colors[i] = curAxisColor.color
+ }
+ }
+ })
+ } else {
+ yAxis?.forEach((axis, index) => {
+ const curAxisColor = seriesMap[axis.id]
+ if (curAxisColor) {
+ if (index + 1 > basicStyle.colors.length) {
+ basicStyle.colors.push(curAxisColor.color)
+ } else {
+ basicStyle.colors[index] = curAxisColor.color
+ }
+ }
+ })
+ }
+ }
+ //左轴
+ const color = basicStyle.colors.map(ele => {
+ const tmp = hexColorToRGBA(ele, basicStyle.alpha)
+ if (basicStyle.gradient) {
+ return setGradientColor(tmp, true, 270)
+ } else {
+ return tmp
+ }
+ })
+ tempOption.geometryOptions[0].color = color
+
+ return tempOption
+ }
+
+ public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
+ const result: ChartBasicStyle['seriesColor'] = []
+ const seriesSet = new Set()
+ const colors = chart.customAttr.basicStyle.colors
+ const { yAxis, extStack } = chart
+ if (extStack?.length) {
+ data?.forEach(d => {
+ if (d.value === null || d.category === null || seriesSet.has(d.category)) {
+ return
+ }
+ seriesSet.add(d.category)
+ result.push({
+ id: d.category,
+ name: d.category,
+ color: colors[(seriesSet.size - 1) % colors.length]
+ })
+ })
+ } else {
+ yAxis?.forEach(axis => {
+ if (seriesSet.has(axis.id)) {
+ return
+ }
+ seriesSet.add(axis.id)
+ result.push({
+ id: axis.id,
+ name: axis.chartShowName ?? axis.name,
+ color: colors[(seriesSet.size - 1) % colors.length]
+ })
+ })
+ }
+ return result
+ }
+
constructor(name = 'chart-mix-stack') {
super(name)
}
diff --git a/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts b/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts
index fa2c865133..5bc5b91243 100644
--- a/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts
+++ b/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts
@@ -165,6 +165,10 @@ export abstract class G2PlotChartView<
return setupSeriesColor(chart, data)
}
+ public setupSubSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
+ return undefined
+ }
+
/**
* 流式配置公共参数,处理常用的配置,后续如果有其他通用配置也可以放进来,需要单独配置的属性在各个图表自行实现。
* @param chart 数据库图表对象。