feat: add 新增自定义排行榜组件RankChart

This commit is contained in:
young 2025-12-12 14:21:54 +08:00
parent 7b565a5ad6
commit 13154d2c87
9 changed files with 393 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,196 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { RankChartConfig } from './index'
// 深拷贝
import cloneDeep from 'lodash/cloneDeep'
// 默认数据
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'grid']
const barName = "检测任务数";
export const seriesItem = {
name: barName,
type: "bar",
barWidth: 10, // 柱子宽度
MaxSize: 0,
showBackground: true,
backgroundStyle: {
color: "#fff",
borderRadius: 5, //设置背景的圆角
},
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 1,
color: "#036afaff", // 0% 处的颜色
},
{
offset: 0.5,
color: "#034299ff"
},
{
offset: 0,
color: "#01142eff", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
label: {
show: true,
offset: [10, -15], // 标签偏移量
color: "#050505f6",
fontSize: 15,
fontWeight: 500,
position: "left",
align: "left",
formatter: function (params:any) {
// console.log(params);
return params.data.name;
},
},
};
const rankIcons = {
icon1: "https://goviewpro.goviewlink.com/cloudStorageStatic/13190/rank1.png",
icon2: "https://goviewpro.goviewlink.com/cloudStorageStatic/13190/rank2.png",
icon3: "https://goviewpro.goviewlink.com/cloudStorageStatic/13190/rank3.png",
icon: "https://goviewpro.goviewlink.com/cloudStorageStatic/13190/rank.png",
};
export const option = {
backgroundColor: "transparent",
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
grid: {
left: "5%",
right: "5%",
top: "5%",
bottom: "5%",
containLabel: true,
},
xAxis: {
type: "value",
show: false,
},
yAxis: [
{
type: "category",
splitLine: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
inverse: true,
axisLabel: {
color: "#333",
fontSize: 16,
margin: 10,
formatter: (name: any, index: number) => {
const id = index + 1;
if (id == 1) {
return `{rank1|${id}}`;
} else if (id == 2) {
return `{rank2|${id}}`;
} else if (id == 3) {
return `{rank3|${id}}`;
} else {
return `{rank|${id}}`;
}
},
rich: {
rank1: {
width: 25,
height: 25,
lineHeight: 25,
fontSize: 16,
align: "center",
color: "#ffffff",
padding: [0, 10, 0, 0],
backgroundColor: {
image: rankIcons.icon1,
},
},
rank2: {
width: 25,
height: 25,
lineHeight: 25,
fontSize: 16,
align: "center",
color: "#ffffff",
padding: [0, 10, 0, 0],
backgroundColor: {
image: rankIcons.icon2,
},
},
rank3: {
width: 25,
height: 25,
lineHeight: 25,
fontSize: 16,
align: "center",
color: "#ffffff",
padding: [0, 10, 0, 0],
backgroundColor: {
image: rankIcons.icon3,
},
},
rank: {
width: 25,
height: 25,
lineHeight: 25,
fontSize: 16,
align: "center",
color: "#ffffff",
padding: [0, 10, 0, 0],
backgroundColor: {
image: rankIcons.icon,
},
},
},
},
},
{
type: "category",
inverse: true,
axisTick: "none",
axisLine: "none",
show: true,
axisLabel: {
textStyle: {
// color: "#000000fd",
color: "#333", // 文字颜色
fontSize: 16,
},
formatter: function (value: any) {
return value + "个";
},
},
data: dataJson.source.map((item) => item.value),
},
],
series: [ seriesItem ],
dataset: { ...dataJson }, // 数据集
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = RankChartConfig.key
public chartConfig = cloneDeep(RankChartConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -0,0 +1,27 @@
<template>
<!-- 遍历 seriesList -->
<global-setting :optionData="optionData" :in-chart="true"></global-setting>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
//
import {
GlobalSetting
} from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
// optionsyAxis
const optionData = computed(() => {
const { yAxis, ...rest } = props.optionData
return rest
})
</script>

View File

@ -0,0 +1,48 @@
{
"dimensions": [
"name",
"value"
],
"source": [
{
"name": "蔡洲",
"value": 691
},
{
"name": "孙磊",
"value": 544
},
{
"name": "张伟",
"value": 522
},
{
"name": "王文峰",
"value": 502
},
{
"name": "李强",
"value": 488
},
{
"name": "刘敏涛",
"value": 461
},
{
"name": "杨其",
"value": 395
},
{
"name": "王若娥",
"value": 389
},
{
"name": "童天宇",
"value": 335
},
{
"name": "杨欧鹏",
"value": 298
}
]
}

View File

@ -0,0 +1,16 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
import image from '@/assets/images/chart/charts/rank-chart.png'
export const RankChartConfig: ConfigType = {
key: 'RankChart',
chartKey: 'VRankChart',
conKey: 'VCRankChart',
title: '排行榜',
category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: image,
}

View File

@ -0,0 +1,102 @@
<template>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { ref, nextTick, computed, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart } from 'echarts/charts'
import config, { includes, seriesItem } from './config'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
import cloneDeep from 'lodash/cloneDeep'
// themeSettingthemeColorchartConfig
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
// ECharts
use([DatasetComponent, CanvasRenderer, BarChart, GridComponent, TooltipComponent, LegendComponent])
const replaceMergeArr = ref<string[]>()
// option
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
// dataset
watch(
() => props.chartConfig.option.dataset,
(newData: { dimensions: any }, oldData) => {
try {
if (!isObject(newData) || !('dimensions' in newData)) return
if (Array.isArray(newData?.dimensions)) {
const seriesArr = []
// oldData
// dimensionsYdimensions.length011X
const oldDimensions = Array.isArray(oldData?.dimensions)&&oldData.dimensions.length >= 1 ? oldData.dimensions.length : 1;
const newDimensions = newData.dimensions.length >= 1 ? newData.dimensions.length : 1;
const dimensionsGap = newDimensions - oldDimensions;
if (dimensionsGap < 0) {
props.chartConfig.option.series.splice(newDimensions - 1)
} else if (dimensionsGap > 0) {
if(!oldData || !oldData?.dimensions || !Array.isArray(oldData?.dimensions) || !oldData?.dimensions.length ) {
props.chartConfig.option.series=[]
}
for (let i = 0; i < dimensionsGap; i++) {
seriesArr.push(cloneDeep(seriesItem))
}
props.chartConfig.option.series.push(...seriesArr)
}
replaceMergeArr.value = ['series']
nextTick(() => {
replaceMergeArr.value = []
})
}
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
props.chartConfig.option.dataset = newData
})
</script>

View File

@ -2,5 +2,6 @@ import { BarCommonConfig } from './BarCommon/index'
import { BarCrossrangeConfig } from './BarCrossrange/index'
import { CapsuleChartConfig } from './CapsuleChart/index'
import { BarLineConfig } from './BarLine/index'
import { RankChartConfig } from './RankChart'
export default [BarCommonConfig, BarCrossrangeConfig, BarLineConfig, CapsuleChartConfig]
export default [BarCommonConfig, BarCrossrangeConfig, BarLineConfig, CapsuleChartConfig, RankChartConfig]

View File

@ -2,7 +2,8 @@ import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { ImageConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
import logo from '@/assets/logo.png'
// import logo from '@/assets/logo.png'
import logo from '@/assets/images/chart/informations/richeng.png'
export const option = {
// 图片路径