From 576024af761f8238db51218e9825f80ea8a86813 Mon Sep 17 00:00:00 2001 From: hz4th_coder Date: Wed, 19 Aug 2026 13:19:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8F=8CY=E8=BD=B4=E5=B7=A6=E5=8F=B3?= =?UTF-8?q?=E8=BD=B4=E5=8F=AF=E7=8B=AC=E7=AB=8B=E5=91=BD=E5=90=8D=20+=20?= =?UTF-8?q?=E4=B8=8D=E5=90=8C=E8=BD=B4=E5=8F=AF=E8=AE=BE=E4=B8=8D=E5=90=8C?= =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 双Y轴:左右两个轴都可单独命名(左轴名称/右轴名称输入框) - 修复系列类型下拉不生效的 bug(seriesTypeOverrides 只写不读), 现在每个系列可独立设置柱状/折线,结合轴分配实现'左轴柱状+右轴折线' - 后端 /api/chart 新增 leftAxisName + seriesTypes 参数(POST/GET 均可) --- API.md | 4 +++- README.md | 2 +- app.js | 18 +++++++++++++----- index.html | 10 +++++++--- server.js | 21 ++++++++++++++++----- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/API.md b/API.md index 97012f8..4ee34e7 100644 --- a/API.md +++ b/API.md @@ -47,7 +47,9 @@ Content-Type: application/json | `splitStyle` | string | — | `"solid"` | 分割线样式:`solid` / `dashed` / `dotted` | | `dualYAxis` | boolean | — | `false` | 启用双Y轴(左右量度不同) | | `rightAxisSeries` | array | — | `null` | 右轴系列名列表,如 `["利润"]`(未列出的系列用左轴) | -| `rightAxisName` | string | — | `""` | 右轴名称 | +| `leftAxisName` | string | — | `""` | 左轴名称(如 `"销售额(元)"`) | +| `rightAxisName` | string | — | `""` | 右轴名称(如 `"增长率(%)"`) | +| `seriesTypes` | array | — | `null` | 每系列图表类型,按系列顺序对应,如 `["bar","line"]`(`bar`/`line`/`auto`) | | `width` | number | — | `800` | 图片宽度(px) | | `height` | number | — | `500` | 图片高度(px) | | `pixelRatio` | number | — | `2` | 像素倍率(越大越清晰) | diff --git a/README.md b/README.md index 2078a43..16bf71a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - **柱状图** - 支持单系列/多系列对比 - **折线图** - 支持平滑曲线、面积填充 - **混合图** - 柱状图+折线图组合展示 -- **双Y轴** - 一张图左右两个坐标轴,量度可不同,系列可指定左轴/右轴(含右轴名称) +- **双Y轴** - 一张图左右两个坐标轴,量度可不同,左右轴可独立命名,系列可指定左轴/右轴且每种类型独立设置(柱状/折线) ### 📋 表格功能 - **表格图片生成** - 根据数据生成精美的表格图片 diff --git a/app.js b/app.js index dc38e12..df12f61 100644 --- a/app.js +++ b/app.js @@ -175,6 +175,7 @@ function updateChart() { const smoothLine = document.getElementById('smoothLine').checked; const enableSplit = document.getElementById('enableSplit').checked; const dualAxis = document.getElementById('dualAxis').checked; + const leftAxisName = document.getElementById('leftAxisName').value; const rightAxisName = document.getElementById('rightAxisName').value; // 显示/隐藏分割配置 @@ -191,10 +192,17 @@ function updateChart() { const name = parsedData.seriesNames[origIdx]; const data = parsedData.seriesData[name]; const color = seriesColors[origIdx] || palette[origIdx % palette.length]; - - let type = chartType === 'bar-line' - ? (displayIdx % 2 === 0 ? 'bar' : 'line') - : chartType; + + // 系列类型:优先用系列配置的独立覆盖(支持不同轴不同图表类型) + const override = window.seriesTypeOverrides && window.seriesTypeOverrides[origIdx]; + let type; + if (override && override !== 'auto') { + type = override; + } else if (chartType === 'bar-line') { + type = displayIdx % 2 === 0 ? 'bar' : 'line'; + } else { + type = chartType; + } const seriesItem = { name: name, @@ -391,7 +399,7 @@ function updateChart() { yAxis: dualAxis ? [ { type: 'value', - name: '左轴', + name: leftAxisName || '左轴', nameTextStyle: { color: textColor, fontSize: 11, padding: [0, 0, 0, 4] }, axisLine: { show: false }, axisTick: { show: false }, diff --git a/index.html b/index.html index bb43c81..8bfab17 100644 --- a/index.html +++ b/index.html @@ -105,9 +105,13 @@ C, 20, 30, 40 diff --git a/server.js b/server.js index c1652e0..06631bc 100644 --- a/server.js +++ b/server.js @@ -116,7 +116,9 @@ function buildChartOption(params) { seriesColors: customColors = null, dualYAxis = false, rightAxisSeries = null, - rightAxisName = '' + leftAxisName = '', + rightAxisName = '', + seriesTypes = null } = params; const parsedData = parseData(data); @@ -137,6 +139,11 @@ function buildChartOption(params) { ? (idx % 2 === 0 ? 'bar' : 'line') : chartType; + // 每系列独立类型覆盖(seriesTypes 数组按系列顺序对应) + if (Array.isArray(seriesTypes) && seriesTypes[idx] && seriesTypes[idx] !== 'auto') { + type = seriesTypes[idx]; + } + const seriesItem = { name: name, type: type, @@ -280,7 +287,7 @@ function buildChartOption(params) { yAxis: dualYAxis ? [ { type: 'value', - name: '左轴', + name: leftAxisName || '左轴', nameTextStyle: { color: textColor, fontSize: 11, padding: [0, 0, 0, 4] }, axisLine: { show: false }, axisTick: { show: false }, @@ -402,7 +409,9 @@ app.get('/api/chart', (req, res) => { splitStyle: req.query.splitStyle || 'solid', dualYAxis: req.query.dualYAxis === 'true', rightAxisSeries: req.query.rightAxisSeries ? req.query.rightAxisSeries.split(',') : null, + leftAxisName: req.query.leftAxisName || '', rightAxisName: req.query.rightAxisName || '', + seriesTypes: req.query.seriesTypes ? req.query.seriesTypes.split(',') : null, width: parseInt(req.query.width) || 800, height: parseInt(req.query.height) || 500, format: req.query.format || 'png', @@ -919,7 +928,7 @@ app.get('/api/health', (req, res) => { res.json({ status: 'ok', service: 'data-chart-tool', - version: '1.11.1', + version: '1.12.0', endpoints: { 'POST /api/chart': '生成图表图片(JSON body)', 'GET /api/chart': '生成图表图片(URL 参数)', @@ -934,7 +943,7 @@ app.get('/api/health', (req, res) => { app.get('/api/docs', (req, res) => { res.json({ name: '数据可视化图表生成器 API', - version: '1.11.1', + version: '1.12.0', endpoints: [ { method: 'POST', @@ -962,7 +971,9 @@ app.get('/api/docs', (req, res) => { pixelRatio: { type: 'number', default: 2, description: '像素倍率(清晰度)' }, dualYAxis: { type: 'boolean', default: false, description: '是否启用双Y轴(左右量度不同)' }, rightAxisSeries: { type: 'array', default: null, description: '右轴系列名列表(如 ["利润"],指定哪些系列用右轴)' }, - rightAxisName: { type: 'string', default: '', description: '右轴名称' } + leftAxisName: { type: 'string', default: '', description: '左轴名称' }, + rightAxisName: { type: 'string', default: '', description: '右轴名称' }, + seriesTypes: { type: 'array', default: null, description: '每系列图表类型(如 ["bar","line"],按系列顺序对应,bar/line/auto)' } }, returns: 'image/png', example: {