feat: 新增饼图/雷达图图表类型
- 单图模式图表类型新增:饼图(环形占比,第一列=名称/第一系列=数值)、雷达图(多维度对比,第一列=维度/每系列=多边形) - 多图合并的每张图也可选饼图/雷达图 - 后端 /api/chart 与 /api/combine 的 chartType 支持 pie/radar - 饼图/雷达图自动隐藏坐标轴/网格/双轴等不适用配置
This commit is contained in:
@@ -130,6 +130,72 @@ function buildChartOption(params) {
|
||||
const textColor = theme === 'dark' ? '#e0e0e0' : '#333333';
|
||||
const axisLineColor = theme === 'dark' ? '#444' : '#ddd';
|
||||
|
||||
// 饼图/雷达图:专用构建逻辑(无坐标轴/网格)
|
||||
if (chartType === 'pie' || chartType === 'radar') {
|
||||
const bgC = theme === 'dark' ? '#1a1a2e' : '#ffffff';
|
||||
const txtC = theme === 'dark' ? '#e0e0e0' : '#333333';
|
||||
const tTitle = title ? { text: title, left: 'center', top: 15, textStyle: { color: txtC, fontSize: 18, fontWeight: 600 } } : undefined;
|
||||
if (chartType === 'pie') {
|
||||
// 饼图:第一列=名称,第一个系列=数值
|
||||
const sName = parsedData.seriesNames[0];
|
||||
const data = parsedData.seriesData[sName];
|
||||
const pieData = parsedData.categories.map((c, i) => ({ name: c, value: data[i] || 0 }));
|
||||
return {
|
||||
backgroundColor: bgC,
|
||||
title: tTitle,
|
||||
tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
|
||||
legend: showLegend ? { orient: 'vertical', left: 'left', top: title ? 50 : 20, textStyle: { color: txtC, fontSize: 12 } } : { show: false },
|
||||
color: seriesColorsArr,
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['38%', '68%'],
|
||||
center: ['52%', '55%'],
|
||||
itemStyle: { borderRadius: 6, borderColor: bgC, borderWidth: 2 },
|
||||
label: { show: showLabel, formatter: '{b}: {d}%', color: txtC },
|
||||
labelLine: { show: showLabel },
|
||||
data: pieData
|
||||
}],
|
||||
animation: false
|
||||
};
|
||||
} else {
|
||||
// 雷达图:第一列=维度名,每个系列=一个雷达多边形
|
||||
const indicator = parsedData.categories.map(c => {
|
||||
let max = 0;
|
||||
parsedData.seriesNames.forEach(n => { parsedData.seriesData[n].forEach(v => { if (v > max) max = v; }); });
|
||||
return { name: c, max: Math.ceil(max * 1.2) || 100 };
|
||||
});
|
||||
return {
|
||||
backgroundColor: bgC,
|
||||
title: tTitle,
|
||||
tooltip: { trigger: 'item' },
|
||||
legend: showLegend ? { orient: 'horizontal', left: 'center', top: title ? 48 : 15, textStyle: { color: txtC, fontSize: 12 } } : { show: false },
|
||||
color: seriesColorsArr,
|
||||
radar: {
|
||||
indicator,
|
||||
radius: '62%',
|
||||
center: ['50%', '55%'],
|
||||
splitNumber: 5,
|
||||
axisName: { color: txtC, fontSize: 12 },
|
||||
splitLine: { lineStyle: { color: theme === 'dark' ? '#444' : '#ddd' } },
|
||||
splitArea: {
|
||||
areaStyle: {
|
||||
color: theme === 'dark' ? ['rgba(79,195,247,0.03)', 'rgba(79,195,247,0.06)'] : ['rgba(79,70,229,0.03)', 'rgba(79,70,229,0.06)']
|
||||
}
|
||||
},
|
||||
axisLine: { lineStyle: { color: theme === 'dark' ? '#444' : '#ddd' } }
|
||||
},
|
||||
series: parsedData.seriesNames.map(n => ({
|
||||
type: 'radar',
|
||||
name: n,
|
||||
data: [{ value: parsedData.seriesData[n], name: n }],
|
||||
symbolSize: 4,
|
||||
areaStyle: { opacity: 0.15 }
|
||||
})),
|
||||
animation: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 构建系列
|
||||
const series = parsedData.seriesNames.map((name, idx) => {
|
||||
const dataArr = parsedData.seriesData[name];
|
||||
@@ -928,7 +994,7 @@ app.get('/api/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'ok',
|
||||
service: 'data-chart-tool',
|
||||
version: '1.13.1',
|
||||
version: '1.14.0',
|
||||
endpoints: {
|
||||
'POST /api/chart': '生成图表图片(JSON body)',
|
||||
'GET /api/chart': '生成图表图片(URL 参数)',
|
||||
@@ -943,7 +1009,7 @@ app.get('/api/health', (req, res) => {
|
||||
app.get('/api/docs', (req, res) => {
|
||||
res.json({
|
||||
name: '数据可视化图表生成器 API',
|
||||
version: '1.13.1',
|
||||
version: '1.14.0',
|
||||
endpoints: [
|
||||
{
|
||||
method: 'POST',
|
||||
@@ -952,7 +1018,7 @@ app.get('/api/docs', (req, res) => {
|
||||
'Content-Type': 'application/json',
|
||||
params: {
|
||||
data: { type: 'string', required: true, description: 'CSV 格式数据(第一行表头,第一列横坐标)' },
|
||||
chartType: { type: 'string', default: 'bar', options: ['bar', 'line', 'bar-line'], description: '图表类型' },
|
||||
chartType: { type: 'string', default: 'bar', options: ['bar', 'line', 'bar-line', 'pie', 'radar'], description: '图表类型' },
|
||||
title: { type: 'string', default: '', description: '图表标题' },
|
||||
theme: { type: 'string', default: 'default', options: ['default', 'dark', 'macarons', 'gradient', 'retro', 'ocean', 'forest', 'sunset', 'lavender', 'minimal', 'cherry', 'midnight', 'gold', 'coral', 'mint'], description: '主题风格' },
|
||||
showLegend: { type: 'boolean', default: true, description: '是否显示图例' },
|
||||
|
||||
Reference in New Issue
Block a user