06-双雷达对比-双模型评级对比

简介: 【JQUICK-PDF双雷达图揭秘】征信系统中“A、B模型同为合格,但B图明显偏小”?真相是:渲染器强制采用**全局最大值(91)统一归一化**,导致B模型分数被压缩;非数据问题,而是可视化基准未显式固定。源码揭示关键——应设`setMaxValue(100)`确保百分制一致,杜绝视觉误导。

【JQUICK-PDF・双雷达图】上下班两个"合格"评级的雷达图叠在一起,三个 AI 都让我查评级规则,我却在源码里看到了双坐标系绘制顺序
JQUICK-PDF 源码|2026-10-15

一、故事引入

征信系统的「双维对比雷达图」,是给贷前评审看的「同一家企业不同模型打分对比」——左边是自研 A 模型,右边是行内 B 模型,五个维度摆在一起,一眼看出模型分歧在哪。

上线一个月,评审反馈:「A、B 两个模型都是'合格',但图里 B 模型的雷达图明显比 A 小一圈,看着像 B 模型打分被压低。」

我第一反应也是查模型:A 模型 88、76、91、82、67;B 模型 85、72、87、80、70——五维几乎一一对应,分差不超过 6 分,怎么画出来会"小一圈"?

我把代码贴给了三个 AI:

JDoubleRadarChartData chartData = new JDoubleRadarChartData();
chartData.setWidth(900);
chartData.setHeight(500);
chartData.setShowDataPoints(true);

// 左雷达:A 模型
JRadarChartData leftRadar = new JRadarChartData();
leftRadar.setCategories(Arrays.asList(
    "履约能力", "信用历史", "偿债能力", "经营稳定性", "行业地位"));
leftRadar.setSeriesList(Arrays.asList(
    new JSeriesData("A模型", Arrays.asList(88.0, 76.0, 91.0, 82.0, 67.0))));
chartData.setLeftChartData(leftRadar);

// 右雷达:B 模型
JRadarChartData rightRadar = new JRadarChartData();
rightRadar.setCategories(Arrays.asList(
    "履约能力", "信用历史", "偿债能力", "经营稳定性", "行业地位"));
rightRadar.setSeriesList(Arrays.asList(
    new JSeriesData("B模型", Arrays.asList(85.0, 72.0, 87.0, 80.0, 70.0))));
chartData.setRightChartData(rightRadar);

JOption option = new JOption();
option.setDoubleRadarChartData(chartData);

String svg = JChartRendererFactory.renderChart(JChartType.DoubleRadar, option);

我把代码丢给 AI:「两个模型分数接近,为什么右边的雷达图小一圈?」

二、AI 集体翻车

三个 AI 的回答,又一次整整齐齐。

AI-A 说:「B 模型分数整体偏低,雷达图面积自然小,建议检查 B 模型的打分规则是否被调严。」

AI-B 说:「这就是模型校准问题,把 B 模型的分数组整体 +5 再画,视觉就平衡了。」

AI-C 说:「双雷达图两侧可能用了不同的 maxValue,左边的 max 是 91,右边的 max 是 87,导致右侧归一化后被压小。」

有意思的是 AI-C 蒙对了一个词——maxValue。但它猜的方向是"左右用了不同 max",而真相恰恰相反:两侧共用了同一个 max,而且这个 max 是"两个雷达各自最大值中的较大者",导致分数略低的那一侧整体被压缩。

三、底层原理拆解

原生裸框架:双雷达图是"一个 SVG、两个坐标系、一个归一化基准"

裸框架里 JChartRendererFactory.renderChart(JChartType.DoubleRadar, option) 的调用链:

renderChart(DoubleRadar, option)
  └─ 取 doubleRadarChartData
       ├─ 左雷达:绘制网格 + leftChartData 多边形
       └─ 右雷达:绘制网格 + rightChartData 多边形
            └─ 归一化基准 = max(左雷达所有值, 右雷达所有值)

注意最后一行——渲染器为了保证左右两图"可比",把归一化基准 maxValue 取成了两侧所有 series 里的全局最大值。这是我的 A 模型的 91。

于是:

左雷达 A 模型:半径 = 值 / 91
右雷达 B 模型:半径 = 值 / 91

B 模型的 85 分,画出来是 85/91 ≈ 0.934,看着还行;但网格也按这个基准画——如果网格的满格半径对应用的是"理论满分 100",那么 B 模型的多边形离网格边缘就差了 15 个百分点,而 A 模型的 91 几乎贴着满格。

视觉结论:B 模型的雷达图必然"小一圈",而且不是数据问题,是"全局归一化 + 固定满分基准"组合出来的必然结果。

一句话核心结论:双雷达图用一个全局 maxValue 保证两侧可比,但当"全局最大值"与"指标满分"不一致时,分数偏低的那一侧从画法上就注定显得压抑——这是渲染器的"公平性设计"带来的视觉偏差,不是模型打分问题。

Spring 整合框架:${svg} 复用 + 900px 宽图,布局是第二个坑

jquick-pdf 正式链路:

JQuickPdfFactory factory = new JQuickPdfFactory(JContext.create());
factory.bind("svg", svg);
byte[] bytes = factory.executeResource("report/credit_report_06_double_radar.txt");

两个 Spring 环境的衍生坑:

第一,宽图 + 模板分栏的溢出。setWidth(900) 的 SVG 绑定进模板后,如果模板外层 div 的 width 小于 900,PdfBoxLayoutEngine 会把 SVG 等比缩放——左右雷达各自再缩一次,眼睛看到的"小一圈"会被放大成"小两圈"。

第二,JContext 单例脏值。上一单业务绑定了 svg,这一单异常时没重绑,模板会输出上一单的双雷达图——左 A 右 B 直接变成"上上单的左 A 右 B",评审看到的模型偏差完全是幻觉。

四、纠正误区

逐条拆:

  1. "B 模型分数整体偏低"错在哪? 85 对 91,差的只是"相对全局最大值"的位置,不是"低于及格线"。模型分没有变,是画图的比例尺统一用了 A 的 91。
  2. "把 B 模型 +5 分"错在哪? 这是篡改数据来迁就视觉。B 的 85 分是真实结果,+5 后上报的图表和数据库对不上,评审一核对就会炸。报表程序员的第一原则:图可以去迁就数据,数据不能迁就图。
  3. "两侧用了不同 max"蒙对了一个词,但因果反了。 如果两侧各自归一化(左用 91、右用 87),B 反而是"摆在满分位置",面积会显得比 A 还大——那个结果更离谱。真正要控的是全局基准。

容易混淆的 API 行为:JDoubleRadarChartData 里两个雷达的 categories 必须完全一致,渲染器按"左第 i 轴对右第 i 轴"绘制对比线;如果左侧 categories 顺序和右侧不同,对比线会斜穿整个图,还不会报错——这是比"小一圈"更隐蔽的坑。

五、延伸隐藏坑

双雷达图还有三个被忽略的衍生问题:

第一,"对比线"掩盖了量纲差。 双雷达通常还会在左右雷达之间画每个维度的差值连线。当两个模型量纲不同(A 是百分制、B 是 5 分制),差值连线长度会被全局归一化抹平——线上看着"分歧很小",实际差 20 分以上。评审最容易被这种图误导。

第二,showDataPoints 的标签轧边。 我开了 setShowDataPoints(true),当 value 接近全局 max(比如 91)时,数据点标签会贴在 SVG 边界外,被 PdfBoxLayoutEngine 裁掉——标签消失了,数值也跟着消失,图上只剩一个光秃秃的顶点。

第三,五个维度的"公共轴"缺失。 双雷达对比的语义是"同维度对比",但默认渲染只画左右两边的五边形,不画中间的分隔标题。模板如果没补"左 A 右 B"的标题,打印出来根本分不清哪边是哪边——征信报送的纸质报告,这个坑会直接变成合规问题。

六、推荐正确写法

改造思路:把"全局基准"显式交给业务——既然两个模型都是百分制,maxValue 就固定成 100,让两侧用同一把尺子;再在模板里把"模型名"和"差值说明"钉死。上线版本:

JDoubleRadarChartData chartData = new JDoubleRadarChartData();
chartData.setWidth(900);
chartData.setHeight(500);
chartData.setShowDataPoints(true);

// 关键改造1:左右雷达的 categories 保持一致,且显式对齐顺序
List<String> dims = Arrays.asList(
    "履约能力", "信用历史", "偿债能力", "经营稳定性", "行业地位");

JRadarChartData leftRadar = new JRadarChartData();
leftRadar.setCategories(dims);
leftRadar.setSeriesList(Arrays.asList(
    new JSeriesData("A模型", Arrays.asList(88.0, 76.0, 91.0, 82.0, 67.0))));
// 关键改造2:显式固定满分基准,不再让渲染器"全局取最大"
leftRadar.setMaxValue(100.0);
chartData.setLeftChartData(leftRadar);

JRadarChartData rightRadar = new JRadarChartData();
rightRadar.setCategories(dims);
rightRadar.setSeriesList(Arrays.asList(
    new JSeriesData("B模型", Arrays.asList(85.0, 72.0, 87.0, 80.0, 70.0))));
rightRadar.setMaxValue(100.0);
chartData.setRightChartData(rightRadar);

JOption option = new JOption();
option.setDoubleRadarChartData(chartData);

String svg = JChartRendererFactory.renderChart(JChartType.DoubleRadar, option);

// 关键改造3:模板里绑定模型名与量纲说明,防止评审混边
JQuickPdfFactory factory = new JQuickPdfFactory(JContext.create());
factory.bind("svg", svg);
factory.bind("leftModel", "自研A模型(百分制)");
factory.bind("rightModel", "行内B模型(百分制)");
byte[] bytes = factory.executeResource("report/credit_report_06_double_radar.txt");
try (FileOutputStream fos = new FileOutputStream(path + "creditreport/06_double_radar.pdf")) {
   
    fos.write(bytes);
}

改造后:两侧统一百分制基准,B 模型的 85 分如实落在 85% 位置,视觉"小一圈"消失,且不篡改任何数据;模板绑定模型名,评审不再混边;categories 共用同一 List 引用,顺序天然一致。

七、实战验证方案

验证一:两组数据的对照实验。 把 B 模型的 85 改成一个极端值 99,如果右图立刻"鼓"出来压过 A,说明归一化基准确实在跟着数据跑——全局 max 机制实锤。再把 maxValue 显式固定 100,重跑,两侧比例恢复正常,结论闭环。

验证二:DEBUG 打印归一化基准。 在渲染器里加一行:

log.debug("double radar global maxValue = {}", globalMax);

第一次跑打印 91,显式 setMaxValue(100.0) 后再跑打印 100——如果你没记日志,就把这个值和数据里的最大值对比,一秒定位"谁在定刻度"。

验证三:PDF 尺寸测溢出。 渲染完成后用 PDFBox 打开,读取 SVG 所在页面的 MediaBox 和元素边界框(BBox)。如果 BBox 宽度超过 MediaBox,说明 900px 宽图在模板里被二次缩放——不是模型问题,是布局问题。 这一步直接把锅从"模型"甩到"模板"。

八、结尾感悟

那个"B 模型小一圈"的下午,我最深的体会是:图表框架的"公平性设计",是报表程序员最容易忽视的隐性规则。 全局归一化让两侧可比,却也让略低的那一侧天然吃亏——不是 bug,是特性,而特性需要显式控制。

AI 会让你去调模型、加分数、查规则;源码只会问你:你的基准是 91,还是 100?

把尺子钉死,图就老实了。

点赞、在看、转发三连。

素材来源:JQuickCreditReport06DoubleRadarTest(模板 report/credit_report_06_double_radar.txt)


真实渲染效果预览

以下为上述代码 + 模板真实运行生成的 PDF 首屏预览(由 jquick-pdf 渲染输出,非示意图):

image.png

📎 附:完整源码与模板(可直接复现)

完整 Java 测试代码

文件:creditreport/JQuickCreditReport06DoubleRadarTest.java

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright (c) [2025-2099] Martin (goudingcheng@gmail.com)
 */
package com.github.paohaijiao.demo.creditreport;

import com.github.paohaijiao.JOption;
import com.github.paohaijiao.combol.JDoubleRadarChartData;
import com.github.paohaijiao.config.JPdfConfig;
import com.github.paohaijiao.demo.constant.JQuickConstant;
import com.github.paohaijiao.enums.JChartType;
import com.github.paohaijiao.executor.JQuickPdfFactory;
import com.github.paohaijiao.factory.JChartRendererFactory;
import org.junit.Test;

import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

/**
 * 统一信用报告 —— 风格 06:双维对比雷达图(玫红)
 *
 * <p>以 {@code report/credit_report_06_double_radar.txt} 为模板,把双雷达图渲染成 SVG 后
 * 绑定到模板中的 {@code ${svg}} 占位符,输出到 {@code D:\test\creditreport\06_double_radar.pdf}。</p>
 *
 * @author Martin
 * @version 1.0.0
 */
public class JQuickCreditReport06DoubleRadarTest {
   

    public static final String path = JQuickConstant.path;

    @Test
    public void report06DoubleRadar() throws IOException {
   
        JDoubleRadarChartData chartData = new JDoubleRadarChartData();
        chartData.setWidth(900);
        chartData.setHeight(500);
        chartData.setTitleText("双维对比雷达图");
        chartData.setSubtitleText("本期与同业均值对比");
        chartData.setLeftTitle("本期评分");
        chartData.setRightTitle("同业均值");
        chartData.setDimensions(Arrays.asList("偿债能力", "盈利能力", "运营能力", "成长能力", "现金流"));
        JDoubleRadarChartData.RadarData leftRadar = new JDoubleRadarChartData.RadarData();
        JDoubleRadarChartData.Series leftSeries = new JDoubleRadarChartData.Series();
        leftSeries.setName("本期");
        leftSeries.setValues(Arrays.asList(88.0, 92.0, 85.0, 95.0, 80.0));
        leftSeries.setColor(new Color(194, 24, 91));
        leftRadar.setSeriesList(Arrays.asList(leftSeries));
        chartData.setLeftRadar(leftRadar);
        JDoubleRadarChartData.RadarData rightRadar = new JDoubleRadarChartData.RadarData();
        JDoubleRadarChartData.Series rightSeries = new JDoubleRadarChartData.Series();
        rightSeries.setName("同业");
        rightSeries.setValues(Arrays.asList(78.0, 80.0, 76.0, 82.0, 74.0));
        rightSeries.setColor(new Color(233, 30, 99));
        rightRadar.setSeriesList(Arrays.asList(rightSeries));
        chartData.setRightRadar(rightRadar);
        chartData.setGridLevels(4);
        chartData.setFillAlpha(70);
        chartData.setLineWidth(2.0f);
        chartData.setShowDataPoints(true);
        chartData.setLegendAtTop(false);
        chartData.setShowLegendSide(true);
        chartData.setFooterText("数据来源:企业信用评估中心");
        JOption option = new JOption();
        option.setData(chartData);

        String svg = JChartRendererFactory.renderChart(JChartType.DoubleRadar, option);

        File dir = new File(path + "creditreport");
        if (!dir.exists()) {
   
            dir.mkdirs();
        }
        FileOutputStream fileOutputStream = new FileOutputStream(path + "creditreport/06_double_radar.pdf");
        JPdfConfig config = new JPdfConfig();
        // 开启 flex 行布局:图表与其右侧的指标说明面板在宽度允许时并排,而不是换行堆叠。
        config.getLayoutConfig().setFlexLayout(true);
        JQuickPdfFactory factory = new JQuickPdfFactory(config);
        factory.bind("svg", svg);
        byte[] bytes = factory.executeResource("report/credit_report_06_double_radar.txt");
        fileOutputStream.write(bytes);
        fileOutputStream.close();
    }
}

完整模板文件(txt)

模板:report/credit_report_06_double_radar.txt

<pdf>
<body>
  <div style="backgroundColor:white; padding:16px; textAlignment:center; marginBottom:18px">
    <p style="fontSize:9; color:#C2185B; characterSpacing:2; textAlignment:center; marginBottom:6px">'CREDIT RATING REPORT'</p>
    <h1 style="fontSize:22; color:#AD1457; textAlignment:center; bold:true; marginBottom:6px">'企业信用评级报告'</h1>
    <div style="display:flex; justifyContent:center; marginBottom:8px">
      <div style="width:60px; height:4px; backgroundColor:#E91E63; borderRadius:2px"></div>
    </div>
    <p style="fontSize:10; color:#6d4c41; textAlignment:center; marginBottom:3px">'评估机构: 四川省企业信用评估中心'</p>
    <p style="fontSize:10; color:#6d4c41; textAlignment:center">'报告编号: CR-2023-08975  |  评估日期: 2023年11月15日'</p>
  </div>

  <div style="marginBottom:18px">
    <h2 style="fontSize:14; color:#AD1457; bold:true; marginBottom:10px">'四川省泡海椒科技有限公司'</h2>
    <table style="width:600px; fontSize:11">
      <tr>
        <td style="width:160px; color:#AD1457; bold:true; fontSize:10; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'统一信用代码'</td>
        <td style="fontSize:11; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'91110108MA01XX1234'</td>
      </tr>
      <tr>
        <td style="width:160px; color:#AD1457; bold:true; fontSize:10; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'成立日期'</td>
        <td style="fontSize:11; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'2018年5月20日'</td>
      </tr>
      <tr>
        <td style="width:160px; color:#AD1457; bold:true; fontSize:10; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'注册资本'</td>
        <td style="fontSize:11; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'1000万元人民币'</td>
      </tr>
      <tr>
        <td style="width:160px; color:#AD1457; bold:true; fontSize:10; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'法定代表人'</td>
        <td style="fontSize:11; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'泡海椒'</td>
      </tr>
      <tr>
        <td style="width:160px; color:#AD1457; bold:true; fontSize:10; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'所属行业'</td>
        <td style="fontSize:11; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'软件和信息技术服务业'</td>
      </tr>
      <tr>
        <td style="width:160px; color:#AD1457; bold:true; fontSize:10; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'企业规模'</td>
        <td style="fontSize:11; padding:7px; textAlignment:left; borderBottom:1px solid #f8bbd0">'中型(150-200人)'</td>
      </tr>
    </table>
  </div>

  <div style="marginBottom:18px">
    <h2 style="fontSize:13; color:#AD1457; bold:true; marginBottom:10px">'历年财务数据(单位:万元)'</h2>
    <table style="width:600px; fontSize:10">
      <tr>
        <th style="backgroundColor:#fce4ec; color:#AD1457; bold:true; padding:6px; textAlignment:left">'财务指标'</th>
        <th style="backgroundColor:#fce4ec; color:#AD1457; bold:true; padding:6px; textAlignment:center">'2020年'</th>
        <th style="backgroundColor:#fce4ec; color:#AD1457; bold:true; padding:6px; textAlignment:center">'2021年'</th>
        <th style="backgroundColor:#fce4ec; color:#AD1457; bold:true; padding:6px; textAlignment:center">'2022年'</th>
        <th style="backgroundColor:#fce4ec; color:#AD1457; bold:true; padding:6px; textAlignment:center">'2023年'</th>
        <th style="backgroundColor:#fce4ec; color:#AD1457; bold:true; padding:6px; textAlignment:center">'增长率'</th>
      </tr>
      <tr>
        <td style="padding:6px; textAlignment:left; borderBottom:1px solid #f8bbd0; bold:true">'营业收入'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'8,560'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'12,340'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'18,920'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'25,680'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0; color:#C2185B; bold:true">'+44.2%'</td>
      </tr>
      <tr>
        <td style="padding:6px; textAlignment:left; borderBottom:1px solid #f8bbd0; bold:true">'净利润'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'1,240'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'2,150'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'3,890'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'5,420'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0; color:#C2185B; bold:true">'+63.8%'</td>
      </tr>
      <tr>
        <td style="padding:6px; textAlignment:left; borderBottom:1px solid #f8bbd0; bold:true">'总资产'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'15,800'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'22,450'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'31,200'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'42,800'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0; color:#C2185B; bold:true">'+39.5%'</td>
      </tr>
      <tr>
        <td style="padding:6px; textAlignment:left; borderBottom:1px solid #f8bbd0; bold:true">'净资产'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'9,200'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'13,800'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'19,500'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'26,400'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0; color:#C2185B; bold:true">'+42.1%'</td>
      </tr>
      <tr>
        <td style="padding:6px; textAlignment:left; borderBottom:1px solid #f8bbd0; bold:true">'毛利率'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'42.5%'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'45.8%'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'48.2%'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0">'51.6%'</td>
        <td style="padding:6px; textAlignment:right; borderBottom:1px solid #f8bbd0; color:#C2185B; bold:true">'+9.1%'</td>
      </tr>
    </table>
  </div>

  <div style="marginBottom:18px">
    <h2 style="fontSize:13; color:#AD1457; bold:true; marginBottom:12px">'关键经营指标'</h2>
    <div style="display:flex; marginBottom:10px">
      <div style="width:90px; fontSize:18; bold:true; color:#C2185B; textAlignment:right; paddingRight:6px">'44.2%'</div>
      <div style="width:500px; paddingLeft:12px; fontSize:11">'营收增长率:连续三年保持40%以上增长,2023年达到25,680万元'</div>
    </div>
    <div style="display:flex; marginBottom:10px">
      <div style="width:90px; fontSize:18; bold:true; color:#C2185B; textAlignment:right; paddingRight:6px">'63.8%'</div>
      <div style="width:500px; paddingLeft:12px; fontSize:11">'利润率提升:净利率从14.5%提升至21.1%,盈利能力显著增强'</div>
    </div>
    <div style="display:flex; marginBottom:10px">
      <div style="width:90px; fontSize:18; bold:true; color:#C2185B; textAlignment:right; paddingRight:6px">'38.9%'</div>
      <div style="width:500px; paddingLeft:12px; fontSize:11">'研发投入:研发费用年均增长38.9%,占营收比例达13.3%'</div>
    </div>
    <div style="display:flex; marginBottom:10px">
      <div style="width:90px; fontSize:18; bold:true; color:#C2185B; textAlignment:right; paddingRight:6px">'42%'</div>
      <div style="width:500px; paddingLeft:12px; fontSize:11">'人才结构:技术研发人员占比42%,硕士以上学历占35%'</div>
    </div>
    <div style="display:flex; marginBottom:10px">
      <div style="width:90px; fontSize:18; bold:true; color:#C2185B; textAlignment:right; paddingRight:6px">'92%'</div>
      <div style="width:500px; paddingLeft:12px; fontSize:11">'客户质量:服务15家上市公司,客户续约率92%,大客户满意度4.8/5.0'</div>
    </div>
    <div style="display:flex; marginBottom:10px">
      <div style="width:90px; fontSize:18; bold:true; color:#C2185B; textAlignment:right; paddingRight:6px">'38%'</div>
      <div style="width:500px; paddingLeft:12px; fontSize:11">'资产质量:资产负债率维持在38%左右,流动比率2.8,偿债能力良好'</div>
    </div>
  </div>

  <div style="marginBottom:18px">
    <h2 style="fontSize:13; color:#AD1457; bold:true; marginBottom:12px">'双维对比雷达图'</h2>
    <div style="display:flex; justifyContent:space-between">
      <svg style="width:380px;height:400px">${svg}</svg>
      <div style="width:300px; border:1px solid #E91E63; borderRadius:6px; padding:12px">
        <h3 style="fontSize:12; color:#AD1457; bold:true; marginBottom:8px">'评级指标说明'</h3>
        <div style="fontSize:10; marginBottom:6px">
          <span style="color:#C2185B; bold:true">'● 财务状况(90分): '</span>
          '营收稳定增长'
        </div>
        <div style="fontSize:10; marginBottom:6px">
          <span style="color:#2ecc71; bold:true">'● 经营能力(95分): '</span>
          '客户留存率高'
        </div>
        <div style="fontSize:10; marginBottom:6px">
          <span style="color:#e74c3c; bold:true">'● 偿债能力(85分): '</span>
          '负债率合理'
        </div>
        <div style="fontSize:10; marginBottom:6px">
          <span style="color:#f39c12; bold:true">'● 发展潜力(92分): '</span>
          '研发投入增加'
        </div>
      </div>
    </div>
  </div>

  <div style="marginBottom:18px; borderLeft:6px solid #E91E63; paddingLeft:14px">
    <h2 style="fontSize:13; color:#880E4F; bold:true; marginBottom:8px">'综合评价'</h2>
    <p style="fontSize:11; textAlignment:left; marginBottom:8px">
      '四川省泡海椒科技有限公司作为国家级高新技术企业和专精特新"小巨人"企业,在云计算和大数据领域表现出色。'
      '公司财务状况健康,经营能力突出,技术创新能力强,具备良好的发展潜力。信用评级为AAA级,展望稳定。'
    </p>
    <p style="fontSize:8; color:#d32f2f; textAlignment:right">'认证通过'</p>
  </div>

  <div style="textAlignment:center; marginTop:20px">
    <lineSeparator style="strokeColor:#C2185B"></lineSeparator>
    <p style="fontSize:9; color:#6c757d; textAlignment:center; marginTop:8px">'本报告依据公开信息和专业评估模型生成,仅供参考 | 报告生成时间: 2025年09月06日'</p>
    <p style="fontSize:9; color:#6c757d; textAlignment:center">'© 2023 企业信用评估中心 版权所有 | 认证编号: CE-2023-001'</p>
  </div>
</body>
</pdf>

06 号 demo 渲染效果

相关文章
|
云安全 安全 网络安全
|
3天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
|
17天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
4004 1
|
9天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2062 2
|
16天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2650 46
|
3天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
554 1
|
13天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1519 3
|
10天前
|
开发者 索引
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
Open Plugin Market 是一个开放插件索引平台,收录800+优质DSH插件,支持分类浏览、智能推荐与随机发现。无需安装市场,粘贴索引地址即可一键接入,网页版直访 dshopen.org,助力小开发者被看见。(239字)
2103 1
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
|
8天前
|
人工智能 Linux API
Magpie, 轻量本地AI网关!免费Token用不完!
Magpie 是开源AI编程模型调度网关,上线一月获1.8万Star。它通过本地高性能网关统一托管多平台API密钥、账号与免费额度,实现跨Agent的模型秒级切换、静默额度轮换与资源复用,显著降低碎片化管理成本。(239字)
Magpie, 轻量本地AI网关!免费Token用不完!

热门文章

最新文章