Skip to content

Ticket handling SLA trend (government hotline / ticketing) — generate this PDF with Java (MultipleLine)

JQuick-PdfBiz Demo

MultipleLine2 页 A4 · 194 KB

Tracks the average handling duration and the number of overdue tickets per month with multiple line series.

Download the PDFView raw template fileBack to all demos

Ticket handling SLA trend (government hotline / ticketing) — MultipleLine
Rendered output

Output specs

PDF pages
2
Chart type
MultipleLine
Template lines
98
Source lines
132

Java source · JQuickBiz21TicketSlaLineTest.java

This is the complete test class that produced the PDF above — copy it and run as-is; see the quick-start section for the Maven dependency.

/*
 * 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 ([email protected])
 */
package com.github.paohaijiao.demo.biz;

import com.github.paohaijiao.JOption;
import com.github.paohaijiao.JTitle;
import com.github.paohaijiao.combol.JMultiLineChartData;
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;
import java.util.List;

/**
 * 业务场景 Demo 21:工单处理时效趋势(政务服务热线 / 企业工单系统)
 *
 * <p>业务场景:政务与企业工单系统按月统计受理、处理、办结及超期工单的处理时长,
 * 用于服务质量考核与流程优化,主色采用政务蓝 #2F5597。</p>
 * <p>实际图表类型:{@link JChartType#MultipleLine} 多重折线图(四条时长指标共用「小时」量纲,观察月度收敛趋势)。</p>
 *
 * <p>模板:{@code report/biz/21_ticket_sla_line.txt};图表以 SVG 文本形式绑定到模板的
 * {@code ${svg}} 占位符,输出到 {@code D:\test\biz\21_ticket_sla_line.pdf}。</p>
 *
 * <p>图表尺寸说明:图表按 700pt × 380pt(宽 × 高)的横版比例设计;模板中 {@code <svg>}
 * 只声明宽度、不声明高度,因此宽度被页面自动收窄时高度会按原比例同步缩放,不会纵向拉伸变形。</p>
 *
 * @author Martin
 * @version 1.0.0
 */
public class JQuickBiz21TicketSlaLineTest {

    public static final String path = JQuickConstant.path;

    @Test
    public void biz21TicketSlaLine() throws IOException {
        List<String> months = Arrays.asList("1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月");
        JMultiLineChartData chartData = new JMultiLineChartData();
        chartData.setXAxisLabels(months);
        chartData.setTitleText("2024年工单处理时效趋势");
        chartData.setSubtitleText("受理 / 处理 / 办结 / 超期时长月度对比");
        chartData.setYAxisTitle("时长(小时)");
        chartData.setFooterText("数据来源:工单管理系统 | 统计口径:自然月(单位:小时)");
        chartData.setGridCount(6);
        chartData.setShowDataLabels(false);
        chartData.setShowInnerPoint(true);
        chartData.setPointRadius(5);
        chartData.setInnerPointRadius(2);
        chartData.setChartAreaColor(new Color(248, 249, 250));
        chartData.setAxisColor(Color.BLACK);
        chartData.setGridColor(new Color(220, 220, 220));
        chartData.setTextColor(Color.BLACK);
        chartData.setFooterColor(new Color(128, 128, 128));
        chartData.setValueWithPercent(false);
        chartData.setAutoCalculateMax(true);
        chartData.setRotateXAxisLabels(false);
        // 平均受理时长:前端智能分派与自助填报推动逐月下降
        JMultiLineChartData.LineData lineA = new JMultiLineChartData.LineData();
        lineA.setName("平均受理时长");
        lineA.setLegendText("平均受理时长(小时)");
        lineA.setValues(Arrays.asList(2.4, 2.1, 1.9, 1.8, 1.7, 1.6, 1.6, 1.5, 1.4, 1.3, 1.2, 1.1));
        lineA.setLineColor(new Color(47, 85, 151));
        lineA.setLineWidth(2.5f);
        // 平均处理时长:部门流转与协同处置环节耗时
        JMultiLineChartData.LineData lineB = new JMultiLineChartData.LineData();
        lineB.setName("平均处理时长");
        lineB.setLegendText("平均处理时长(小时)");
        lineB.setValues(Arrays.asList(3.6, 3.4, 3.2, 3.0, 2.8, 2.7, 2.6, 2.4, 2.3, 2.1, 2.0, 1.8));
        lineB.setLineColor(new Color(91, 155, 213));
        lineB.setLineWidth(2.5f);
        // 平均办结时长:从受理到办结的端到端耗时(3月、8月出现小幅反弹)
        JMultiLineChartData.LineData lineC = new JMultiLineChartData.LineData();
        lineC.setName("平均办结时长");
        lineC.setLegendText("平均办结时长(小时)");
        lineC.setValues(Arrays.asList(6.2, 5.8, 5.9, 5.5, 5.1, 4.8, 4.6, 4.7, 4.3, 3.9, 3.5, 3.1));
        lineC.setLineColor(new Color(197, 90, 17));
        lineC.setLineWidth(2.5f);
        // 超期工单平均超期时长:长尾工单管控效果
        JMultiLineChartData.LineData lineD = new JMultiLineChartData.LineData();
        lineD.setName("超期工单平均超期时长");
        lineD.setLegendText("超期工单平均超期时长(小时)");
        lineD.setValues(Arrays.asList(9.8, 9.2, 8.6, 8.1, 7.6, 7.2, 6.8, 6.4, 6.0, 5.5, 5.1, 4.6));
        lineD.setLineColor(new Color(127, 127, 127));
        lineD.setLineWidth(2.5f);
        chartData.setLineDataList(Arrays.asList(lineA, lineB, lineC, lineD));
        // 设置完折线数据后必须刷新 Y 轴最大值
        chartData.updateMaxValues();
        JOption option = new JOption();
        JTitle title = new JTitle();
        title.setText("2024年工单处理时效趋势");
        title.setSubtext("受理 / 处理 / 办结 / 超期时长月度对比");
        option.setTitle(title);
        option.setData(chartData);

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

        File dir = new File(path + "biz");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        FileOutputStream fileOutputStream = new FileOutputStream(path + "biz/21_ticket_sla_line.pdf");
        JPdfConfig config = new JPdfConfig();
        // 开启 flex 行布局,使模板中的 display:flex 生效(图表居中)
        config.getLayoutConfig().setFlexLayout(true);
        JQuickPdfFactory factory = new JQuickPdfFactory(config);
        factory.bind("svg", svg);
        byte[] bytes = factory.executeResource("report/biz/21_ticket_sla_line.txt");
        fileOutputStream.write(bytes);
        fileOutputStream.close();
    }
}

Minimal invocation (3 lines)

Skip the full test class — the core is these three lines: bind the chart SVG, execute the template, get the PDF bytes. Copy them straight into your project.

// config 可省略;svg 来自 JChartRendererFactory.renderChart(...),见下方完整源码
factory.bind("svg", svg);
byte[] pdf = new JQuickPdfFactory(config).executeResource("report/biz/21_ticket_sla_line.txt");

Template file · 21_ticket_sla_line.txt

An HTML-like template with inline CSS that renders to PDF once bound to data. The full template is below — copy it or download the raw file.

<pdf>
<body>
  <div style="marginBottom:12px; borderBottom:4px solid #2F5597; paddingBottom:8px; keepTogether:true">
    <h1 style="color:#2F5597; fontSize:19pt; bold:true; marginBottom:4px">'2024年工单处理时效趋势'</h1>
    <div style="display:flex; justifyContent:space-between">
      <div style="width:290px">
        <p style="color:#6c757d; fontSize:9pt">'副标题:受理 / 处理 / 办结 / 超期时长月度对比'</p>
      </div>
      <div style="width:250px; textAlignment:right">
        <p style="color:#6c757d; fontSize:9pt">'统计周期:2024年1月 - 12月 | 单位:小时'</p>
      </div>
    </div>
  </div>

  <div style="marginBottom:10px">
    <h2 style="color:#2F5597; fontSize:13pt; bold:true; underline:true; marginBottom:6px">'一、处理时效月度走势'</h2>
    <div style="display:flex; justifyContent:center">
      <svg style="width:700pt">${svg}</svg>
    </div>
    <p style="fontSize:9pt; color:#6c757d; italic:true; marginTop:6px">'图 1  2024年1-12月受理 / 处理 / 办结 / 超期工单平均时长(数据来源:工单管理系统)'</p>
  </div>
  <areaBreak></areaBreak>

  <div style="marginBottom:10px">
    <h2 style="color:#2F5597; fontSize:13pt; bold:true; underline:true; marginBottom:6px">'二、季度时效汇总'</h2>
    <table style="width:560px; fontSize:10pt">
      <tr>
        <th style="width:120px; backgroundColor:#2F5597; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'季度'</th>
        <th style="width:110px; backgroundColor:#2F5597; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'受理时长(小时)'</th>
        <th style="width:110px; backgroundColor:#2F5597; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'处理时长(小时)'</th>
        <th style="width:110px; backgroundColor:#2F5597; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'办结时长(小时)'</th>
        <th style="width:110px; backgroundColor:#2F5597; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'超期时长(小时)'</th>
      </tr>
      <tr>
        <td style="padding:5px; borderTop:1px solid #DCE3EC; borderRight:1px solid #DCE3EC; borderBottom:1px solid #DCE3EC; borderLeft:3px solid #2F5597">'第一季度'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'2.1'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'3.4'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'6.0'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'9.2'</td>
      </tr>
      <tr>
        <td style="padding:5px; borderTop:1px solid #DCE3EC; borderRight:1px solid #DCE3EC; borderBottom:1px solid #DCE3EC; borderLeft:3px solid #2F5597">'第二季度'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'1.7'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'2.8'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'5.1'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'7.6'</td>
      </tr>
      <tr>
        <td style="padding:5px; borderTop:1px solid #DCE3EC; borderRight:1px solid #DCE3EC; borderBottom:1px solid #DCE3EC; borderLeft:3px solid #2F5597">'第三季度'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'1.5'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'2.4'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'4.5'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'6.4'</td>
      </tr>
      <tr>
        <td style="padding:5px; borderTop:1px solid #DCE3EC; borderRight:1px solid #DCE3EC; borderBottom:1px solid #DCE3EC; borderLeft:3px solid #2F5597">'第四季度'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'1.2'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'2.0'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'3.5'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'5.1'</td>
      </tr>
      <tr>
        <td style="padding:6px; bold:true; borderTop:1px solid #DCE3EC; borderRight:1px solid #DCE3EC; borderBottom:1px solid #DCE3EC; borderLeft:3px solid #2F5597">'全年平均'</td>
        <td style="padding:6px; textAlign:right; bold:true; border:1px solid #DCE3EC">'1.6'</td>
        <td style="padding:6px; textAlign:right; bold:true; border:1px solid #DCE3EC">'2.7'</td>
        <td style="padding:6px; textAlign:right; bold:true; border:1px solid #DCE3EC">'4.8'</td>
        <td style="padding:6px; textAlign:right; bold:true; border:1px solid #DCE3EC">'7.1'</td>
      </tr>
    </table>
  </div>

  <div style="marginBottom:10px">
    <h2 style="color:#2F5597; fontSize:13pt; bold:true; underline:true; marginBottom:6px">'三、时效改进结论'</h2>
    <list style="listStyleType:disc; paddingLeft:16px; fontSize:10pt">
      <li style="marginBottom:5px"><span style="bold:true; color:#2F5597">'端到端时效持续收敛:'</span>'平均办结时长由1月 6.2 小时降至12月 3.1 小时,降幅 50.0%。'</li>
      <li style="marginBottom:5px"><span style="bold:true; color:#2F5597">'受理环节提速最明显:'</span>'平均受理时长由 2.4 小时降至 1.1 小时,四季度均值 1.2 小时,为全年最低水平。'</li>
      <li style="marginBottom:5px"><span style="bold:true; color:#2F5597">'处理环节稳定下降:'</span>'平均处理时长从 3.6 小时降至 1.8 小时,四季度首次进入 2 小时区间。'</li>
      <li style="marginBottom:5px"><span style="bold:true; color:#2F5597">'超期工单管控见效:'</span>'超期工单平均超期时长由 9.8 小时压降至 4.6 小时,降幅 53.1%。'</li>
      <li style="marginBottom:5px"><span style="bold:true; color:#2F5597">'波动提示:'</span>'3月、8月办结时长出现小幅反弹(5.9 / 4.7 小时),与月中集中交办和系统升级窗口重叠,建议错峰安排。'</li>
      <li style="marginBottom:5px"><span style="bold:true; color:#2F5597">'建议:'</span>'将全年目标设为办结时长不超过 3 小时,并把超期时长纳入部门月度服务质量考核。'</li>
    </list>
  </div>

  <lineSeparator style="strokeColor:#DCE3EC"></lineSeparator>
  <div style="display:flex; justifyContent:space-between; marginTop:8px">
    <div style="width:180px">
      <p style="color:#6c757d; fontSize:8pt">'密级:内部'</p>
    </div>
    <div style="width:200px; textAlignment:center">
      <p style="color:#6c757d; fontSize:8pt">'生成时间:2025年1月10日'</p>
    </div>
    <div style="width:180px; textAlignment:right">
      <p style="color:#6c757d; fontSize:8pt">'批准人:政务服务热线中心主任'</p>
    </div>
  </div>
</body>
</pdf>

More demos in this group

The PDF, preview image, template and source code on this page were all produced by a real JQuick-Pdf run and are free to copy into your own project.