feat: 新增饼图配制

This commit is contained in:
奔跑的面条 2025-06-15 16:36:31 +08:00
parent b3a8c23a47
commit cfb2a667bd
18 changed files with 228 additions and 141 deletions

View File

@ -197,7 +197,7 @@ const createOrUpdateChart = (
} }
) => { ) => {
if (vChartRef.value && !chart) { if (vChartRef.value && !chart) {
const spec = transformHandler[chartProps.category](chartProps) const spec = transformHandler[chartProps.category || '']?.(chartProps)
chart = new VChart( chart = new VChart(
{ ...spec, data: chartProps.dataset }, { ...spec, data: chartProps.dataset },
{ {
@ -208,7 +208,7 @@ const createOrUpdateChart = (
chart.renderSync() chart.renderSync()
return true return true
} else if (chart) { } else if (chart) {
const spec = transformHandler[chartProps.category](chartProps) const spec = transformHandler[chartProps.category || '']?.(chartProps)
chart.updateSpec({ ...spec, data: toRaw(chartProps.dataset), dataset: undefined }) chart.updateSpec({ ...spec, data: toRaw(chartProps.dataset), dataset: undefined })
return true return true
} }

View File

@ -1,15 +1,10 @@
import { Datum } from "@visactor/vchart/esm/typings" import { Datum } from '@visactor/vchart/esm/typings'
import { cloneDeep } from "lodash" import { cloneDeep } from 'lodash'
const INNER_RADIUS = 0.75
const OUTER_RADIUS = 0.68
export default (chartProps: any) => { export default (chartProps: any) => {
const spec = cloneDeep(chartProps) const spec = cloneDeep(chartProps)
delete spec.category delete spec.category
spec.innerRadius = INNER_RADIUS
spec.outerRadius = OUTER_RADIUS
// tooltip // tooltip
const keyFill = spec.tooltip.style.keyLabel.fill const keyFill = spec.tooltip.style.keyLabel.fill
const valueFill = spec.tooltip.style.valueLabel.fill const valueFill = spec.tooltip.style.valueLabel.fill
@ -21,6 +16,7 @@ export default (chartProps: any) => {
spec.tooltip.style.valueLabel.fontColor = valueFill spec.tooltip.style.valueLabel.fontColor = valueFill
spec.tooltip.style.titleLabel.fontColor = titleFill spec.tooltip.style.titleLabel.fontColor = titleFill
if (spec.extensionMark) {
// extensionMark // extensionMark
spec.extensionMark = [ spec.extensionMark = [
{ {
@ -30,29 +26,27 @@ export default (chartProps: any) => {
style: { style: {
interactive: false, interactive: false,
startAngle: (datum: Datum) => { startAngle: (datum: Datum) => {
console.log('startAngle', datum) return datum['__VCHART_ARC_START_ANGLE']
return datum['__VCHART_ARC_START_ANGLE'];
}, },
endAngle: (datum: Datum) => { endAngle: (datum: Datum) => {
return datum['__VCHART_ARC_END_ANGLE']; return datum['__VCHART_ARC_END_ANGLE']
}, },
innerRadius: (datum: Datum, context: any) => { innerRadius: (datum: Datum, context: any) => {
return context.getLayoutRadius() * spec.innerRadius - 30; return context.getLayoutRadius() * spec.innerRadius - 30
}, },
outerRadius: (datum: Datum, context: any) => { outerRadius: (datum: Datum, context: any) => {
return context.getLayoutRadius() * spec.innerRadius; return context.getLayoutRadius() * spec.innerRadius
}, },
fillOpacity: 0.3, fillOpacity: 0.3,
fill: (datum: Datum, context: any) => { fill: (datum: Datum, context: any) => {
console.log('context', context.seriesColor(datum[spec.seriesField])) return context.seriesColor(datum[spec.seriesField])
return context.seriesColor(datum[spec.seriesField]);
}, },
visible: true, visible: true,
x: (datum: Datum, context: any) => { x: (datum: Datum, context: any) => {
return context.getCenter().x(); return context.getCenter().x()
}, },
y: (datum: Datum, context: any) => { y: (datum: Datum, context: any) => {
return context.getCenter().y(); return context.getCenter().y()
} }
} }
}, },
@ -63,7 +57,7 @@ export default (chartProps: any) => {
style: { style: {
interactive: false, interactive: false,
size: (datum: Datum, context: any) => { size: (datum: Datum, context: any) => {
return context.getLayoutRadius() * 2 * spec.innerRadius - 100; return context.getLayoutRadius() * 2 * spec.innerRadius - 100
}, },
fillOpacity: 0, fillOpacity: 0,
lineWidth: 1, lineWidth: 1,
@ -87,10 +81,10 @@ export default (chartProps: any) => {
}, },
visible: true, visible: true,
x: (datum: Datum, context: any) => { x: (datum: Datum, context: any) => {
return context.getCenter().x(); return context.getCenter().x()
}, },
y: (datum: Datum, context: any) => { y: (datum: Datum, context: any) => {
return context.getCenter().y(); return context.getCenter().y()
} }
} }
}, },
@ -101,7 +95,7 @@ export default (chartProps: any) => {
style: { style: {
interactive: false, interactive: false,
size: (datum: Datum, context: any) => { size: (datum: Datum, context: any) => {
return context.getLayoutRadius() * 2 * spec.outerRadius + 50; return context.getLayoutRadius() * 2 * spec.outerRadius + 50
}, },
fillOpacity: 0, fillOpacity: 0,
lineWidth: 1, lineWidth: 1,
@ -125,15 +119,14 @@ export default (chartProps: any) => {
}, },
visible: true, visible: true,
x: (datum: Datum, context: any) => { x: (datum: Datum, context: any) => {
return context.getCenter().x(); return context.getCenter().x()
}, },
y: (datum: Datum, context: any) => { y: (datum: Datum, context: any) => {
return context.getCenter().y(); return context.getCenter().y()
} }
} }
} }
] ]
}
// console.log('spec-pie-transform', spec)
return spec return spec
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<collapse-item v-model:name="axis.name"> <collapse-item :name="axis.name">
<template #header> <template #header>
<n-switch v-model:value="axis.visible" size="small"></n-switch> <n-switch v-model:value="axis.visible" size="small"></n-switch>
</template> </template>

View File

@ -26,14 +26,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, toRefs } from 'vue' import { PropType } from 'vue'
import { fontStyleConfig } from '@/packages/chartConfiguration/vcharts/index' import { fontStyleConfig } from '@/packages/chartConfiguration/vcharts/index'
import { FontType } from '@/settings/vchartThemes/index' import { FontType } from '@/settings/vchartThemes/index'
import { SettingItem } from '@/components/Pages/ChartItemSetting' import { SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({ defineProps({
style: { style: {
type: Object as PropType<FontType>, type: Object as PropType<any>,
required: true required: true
} }
}) })

View File

@ -1 +1,2 @@
export * from './legends' export * from './legends'
export * from './label'

View File

@ -0,0 +1,24 @@
export const labelConfig = {
position: [
{
label: '外部',
value: 'outside'
},
{
label: '内部',
value: 'inside'
},
{
label: '内部-外',
value: 'inside-outer'
},
{
label: '内部-里',
value: 'inside-inner'
},
{
label: '内部-居中',
value: 'inside-center'
}
]
}

View File

@ -66,7 +66,7 @@
:options="labelConfig.fontWeight" :options="labelConfig.fontWeight"
/> />
</SettingItem> </SettingItem>
<setting-item name="文字边框大小" v-if="optionData.series[0].label.textBorderWidth"> <setting-item name="文字边框大小" v-if="optionData.series[0].label.textBorderWidth > -1">
<n-input-number <n-input-number
v-model:value="optionData.series[0].label.textBorderWidth" v-model:value="optionData.series[0].label.textBorderWidth"
size="small" size="small"

View File

@ -5,7 +5,7 @@ export const VChartBarCommonConfig: ConfigType = {
key: 'VChartBarCommon', key: 'VChartBarCommon',
chartKey: 'VVChartBarCommon', chartKey: 'VVChartBarCommon',
conKey: 'VCVChartBarCommon', conKey: 'VCVChartBarCommon',
title: 'VChart并列柱状图', title: '并列柱状图-VChart',
category: ChatCategoryEnum.BAR, category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR, categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -5,7 +5,7 @@ export const VChartBarCrossrangeConfig: ConfigType = {
key: 'VChartBarCrossrange', key: 'VChartBarCrossrange',
chartKey: 'VVChartBarCrossrange', chartKey: 'VVChartBarCrossrange',
conKey: 'VCVChartBarCrossrange', conKey: 'VCVChartBarCrossrange',
title: 'VChart并列柱状图', title: '并列柱状图-VChart',
category: ChatCategoryEnum.BAR, category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR, categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -5,7 +5,7 @@ export const VChartBarStackConfig: ConfigType = {
key: 'VChartBarStack', key: 'VChartBarStack',
chartKey: 'VVChartBarStack', chartKey: 'VVChartBarStack',
conKey: 'VCVChartBarStack', conKey: 'VCVChartBarStack',
title: 'VChart堆叠柱状图', title: '堆叠柱状图-VChart',
category: ChatCategoryEnum.BAR, category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR, categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -5,7 +5,7 @@ export const VChartFunnelConfig: ConfigType = {
key: 'VChartFunnel', key: 'VChartFunnel',
chartKey: 'VVChartFunnel', chartKey: 'VVChartFunnel',
conKey: 'VCVChartFunnel', conKey: 'VCVChartFunnel',
title: 'VChart漏斗图', title: '漏斗图-VChart',
category: ChatCategoryEnum.FUNNEL, category: ChatCategoryEnum.FUNNEL,
categoryName: ChatCategoryEnumName.FUNNEL, categoryName: ChatCategoryEnumName.FUNNEL,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -5,7 +5,7 @@ export const VChartLineConfig: ConfigType = {
key: 'VChartLine', key: 'VChartLine',
chartKey: 'VVChartLine', chartKey: 'VVChartLine',
conKey: 'VCVChartLine', conKey: 'VCVChartLine',
title: 'VChart折线图', title: '折线图-VChart',
category: ChatCategoryEnum.LINE, category: ChatCategoryEnum.LINE,
categoryName: ChatCategoryEnumName.LINE, categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -4,7 +4,8 @@ import { CreateComponentType } from '@/packages/index.d'
import { vChartOptionPrefixHandle } from '@/packages/public/vChart' import { vChartOptionPrefixHandle } from '@/packages/public/vChart'
import data from './data.json' import data from './data.json'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import { IPieOption } from '../../index.d' import type { ChatCategoryEnum, IPieOption } from '../../index.d'
import axisThemeJson from '@/settings/vchartThemes/axis.theme.json'
export const includes = ['legends', 'tooltip'] export const includes = ['legends', 'tooltip']
export const option: IPieOption & { dataset?: any } = { export const option: IPieOption & { dataset?: any } = {
@ -14,8 +15,25 @@ export const option: IPieOption & { dataset?: any } = {
categoryField: 'year', categoryField: 'year',
valueField: 'value', valueField: 'value',
seriesField: 'year', seriesField: 'year',
// 中心
centerX: '50%',
centerY: '50%',
innerRadius: 0.68,
outerRadius: 0.75,
label: {
visible: true,
position: 'outside',
style: {
fontSize: 12,
fill: '#B9B8CE',
fontFamily: 'SimSun',
fontWeight: 'normal',
angle: 0
}
},
// 业务配置后续会被转换为图表spec) // 业务配置后续会被转换为图表spec)
category: VChartPieConfig.category, category: VChartPieConfig.category as ChatCategoryEnum.PIE,
extensionMark: []
} }
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@ -1,17 +1,68 @@
<template> <template>
<!-- vCharts 全局设置 --> <!-- vCharts 全局设置 -->
<VChartGlobalSetting :optionData="optionData"></VChartGlobalSetting> <VChartGlobalSetting :optionData="optionData"></VChartGlobalSetting>
<!-- 饼图配制 -->
<collapse-item name="饼图" expanded>
<SettingItemBox name="图形">
<setting-item name="内圈范围">
<n-input-number v-model:value="optionData.innerRadius" :step="0.1" :min="0" size="small"></n-input-number>
</setting-item>
<setting-item name="外圈范围">
<n-input-number v-model:value="optionData.outerRadius" :step="0.1" :min="0" size="small"></n-input-number>
</setting-item>
<setting-item name="中心轴X">
<n-input v-model:value="optionData.centerX" :step="1" :min="0" size="small"></n-input>
</setting-item>
<setting-item name="中心轴Y">
<n-input v-model:value="optionData.centerY" :step="1" :min="0" size="small"></n-input>
</setting-item>
</SettingItemBox>
<SettingItemBox name="标签">
<SettingItem>
<n-space>
<n-switch v-model:value="optionData.label.visible" size="small"></n-switch>
<n-text>展示标签</n-text>
</n-space>
</SettingItem>
<SettingItem name="位置">
<n-select v-model:value="optionData.label.position" :options="labelConfig.position" size="small" />
</SettingItem>
<FontStyle :style="toRefs(optionData.label.style)"></FontStyle>
</SettingItemBox>
<setting-item-box name="内环形">
<setting-item name="可见性">
<n-space>
<n-switch v-model:value="extensionMarkRef" size="small" @update:value="markerHandle"></n-switch>
</n-space>
</setting-item>
</setting-item-box>
</collapse-item>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { PropType, ref, toRefs } from 'vue'
import { VChartGlobalSetting } from '@/components/Pages/VChartItemSetting' import { VChartGlobalSetting } from '@/components/Pages/VChartItemSetting'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index' import FontStyle from '@/components/Pages/VChartItemSetting/common/FontStyle.vue'
import type { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { labelConfig } from '@/packages/chartConfiguration/vcharts/index'
defineProps({ const props = defineProps({
optionData: { optionData: {
type: Object as PropType<vChartGlobalThemeJsonType>, type: Object as PropType<vChartGlobalThemeJsonType>,
required: true required: true
} }
}) })
const a = toRefs(props.optionData.label.style)
const extensionMarkRef = ref(!!props.optionData?.extensionMark)
const markerHandle = (value: boolean) => {
if (value) {
props.optionData.extensionMark = []
} else {
delete props.optionData.extensionMark
}
}
</script> </script>

View File

@ -5,7 +5,7 @@ export const VChartPieConfig: ConfigType = {
key: 'VChartPie', key: 'VChartPie',
chartKey: 'VVChartPie', chartKey: 'VVChartPie',
conKey: 'VCVChartPie', conKey: 'VCVChartPie',
title: 'VChart饼图', title: '饼图多欢-VChart',
category: ChatCategoryEnum.PIE, category: ChatCategoryEnum.PIE,
categoryName: ChatCategoryEnumName.PIE, categoryName: ChatCategoryEnumName.PIE,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -5,7 +5,7 @@ export const VChartScatterConfig: ConfigType = {
key: 'VChartScatter', key: 'VChartScatter',
chartKey: 'VVChartScatter', chartKey: 'VVChartScatter',
conKey: 'VCVChartScatter', conKey: 'VCVChartScatter',
title: 'VChart散点图', title: '散点图-VChart',
category: ChatCategoryEnum.SCATTER, category: ChatCategoryEnum.SCATTER,
categoryName: ChatCategoryEnumName.SCATTER, categoryName: ChatCategoryEnumName.SCATTER,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -5,7 +5,7 @@ export const VChartWordCloudConfig: ConfigType = {
key: 'VChartWordCloud', key: 'VChartWordCloud',
chartKey: 'VVChartWordCloud', chartKey: 'VVChartWordCloud',
conKey: 'VCVChartWordCloud', conKey: 'VCVChartWordCloud',
title: 'VChart词云图', title: '词云图-VChart',
category: ChatCategoryEnum.WORDCLOUD, category: ChatCategoryEnum.WORDCLOUD,
categoryName: ChatCategoryEnumName.WORDCLOUD, categoryName: ChatCategoryEnumName.WORDCLOUD,
package: PackagesCategoryEnum.VCHART, package: PackagesCategoryEnum.VCHART,

View File

@ -56,7 +56,7 @@ export interface IAreaOption extends Omit<IAreaChartSpec, 'axes'> {
} }
export interface IPieOption extends IPieChartSpec { export interface IPieOption extends IPieChartSpec {
category: ChatCategoryEnum.PIE category?: ChatCategoryEnum.PIE
type: 'pie' type: 'pie'
} }