添加生成html格式的RRR报告

This commit is contained in:
duwenyuan 2026-07-20 18:28:47 +08:00
parent b73d9b54e2
commit 23fa01ba57
8 changed files with 891 additions and 3588 deletions

View File

@ -253,7 +253,7 @@ public class EmailServiceManager {
properties.put("mail.imap.host", email.getEmailServerAddress()); properties.put("mail.imap.host", email.getEmailServerAddress());
properties.put("mail.imap.port", email.getPort()); properties.put("mail.imap.port", email.getPort());
properties.put("mail.imap.ssl.enable", "false"); properties.put("mail.imap.ssl.enable", "false");
properties.put("mail.imap.starttls.enable", "true"); properties.put("mail.imap.starttls.enable", "false");
properties.put("mail.imap.auth", "true"); properties.put("mail.imap.auth", "true");
// 超时设置(毫秒) // 超时设置(毫秒)
properties.put("mail.imap.connectiontimeout", "10000"); properties.put("mail.imap.connectiontimeout", "10000");
@ -299,7 +299,7 @@ public class EmailServiceManager {
store.connect(host, username, password); store.connect(host, username, password);
return store.isConnected(); return store.isConnected();
} catch (Exception e) { } catch (Exception e) {
log.error("收件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage()); log.error("收件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常:", host, port, username, e);
return false; return false;
} }
} }

View File

@ -6474,4 +6474,21 @@ public class GammaFileUtil extends AbstractLogOrReport {
mdcInfo.setYield(nuclideLines.vyield.get(maxIndex)); mdcInfo.setYield(nuclideLines.vyield.get(maxIndex));
} }
/**
* 生成RRR报告HTML格式
* @param middleData
* @return
*/
public Map<String, Object> OutPutRrrHtml(GStoreMiddleProcessData middleData){
Map<String, Object> result = new HashMap<>();
result.put("middleData",middleData);
return result;
}
public Map<String, Object> OutPutRrrHtml(PHDFile phd, String userName, String flag){
GStoreMiddleProcessData middleData = new GStoreMiddleProcessData();
GetInterMiddlData(phd, userName, middleData, flag);
return OutPutRrrHtml(middleData);
}
} }

View File

@ -446,7 +446,11 @@ public class GammaController {
public Result viewRRR(Integer sampleId, String fileName, HttpServletRequest request) { public Result viewRRR(Integer sampleId, String fileName, HttpServletRequest request) {
return gammaService.viewRRR(sampleId, fileName, request); return gammaService.viewRRR(sampleId, fileName, request);
} }
@GetMapping("viewRRRHtml")
@ApiOperation(value = "查看RRR页面数据", notes = "查看RRR页面数据")
public Result viewRRRHtml(Integer sampleId, String fileName, HttpServletRequest request) {
return gammaService.viewRRRHtml(sampleId, fileName, request);
}
@GetMapping("exportRRR") @GetMapping("exportRRR")
public void exportRRR(Integer sampleId, String fileName, HttpServletRequest request, HttpServletResponse response) { public void exportRRR(Integer sampleId, String fileName, HttpServletRequest request, HttpServletResponse response) {
gammaService.exportRRR(sampleId, fileName, request, response); gammaService.exportRRR(sampleId, fileName, request, response);

View File

@ -7,6 +7,6 @@ import org.jeecg.modules.entity.GardsAnalysesSpectrum;
public interface GardsAnalysesManMapper extends BaseMapper<GardsAnalyses> { public interface GardsAnalysesManMapper extends BaseMapper<GardsAnalyses> {
void updateEntity(@Param(value = "analyses") GardsAnalysesSpectrum analyses); void updateEntity(@Param(value = "analyses") GardsAnalysesSpectrum analyses,@Param("dbType") String dbType);
} }

View File

@ -67,6 +67,9 @@ import javax.xml.parsers.ParserConfigurationException;
import java.io.*; import java.io.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -157,14 +160,14 @@ public class GammaServiceImpl extends AbstractLogOrReport implements IGammaServi
private ISysDictSpectrumService sysDictService; private ISysDictSpectrumService sysDictService;
@Autowired @Autowired
private IDataService dataService; private IDataService dataService;
/// 样品等级服务 /// 样品等级服务
@Autowired @Autowired
private ISampleGradingService sampleGradingService; private ISampleGradingService sampleGradingService;
// 获取阈值信息 // 获取阈值信息
@Autowired @Autowired
private IRnManGardsThresholdService gardsThresholdService; private IRnManGardsThresholdService gardsThresholdService;
@Autowired
private HtmlReportGenerator reportByThymeleaf;
@Override @Override
public void initValue(Integer sampleId, String dbName, String analyst, String samfileName, public void initValue(Integer sampleId, String dbName, String analyst, String samfileName,
@ -4451,6 +4454,23 @@ public class GammaServiceImpl extends AbstractLogOrReport implements IGammaServi
return result; return result;
} }
public Result viewRRRHtml(Integer sampleId, String fileName, HttpServletRequest request)
{
Result result = new Result();
String userName = JwtUtil.getUserNameByToken(request);
Cache<String, PHDFile> phdCache = localCache.getPHDCache();
PHDFile phd = phdCache.getIfPresent(fileName + StringPool.DASH + userName);
if (Objects.isNull(phd)) {
result.error500("Please select the parse file first");
return result;
}
String templatePath = "templates/reportP.html";
Map<String, Object> rrrMap = gammaFileUtil.OutPutRrrHtml(phd,userName,"log");
String html= reportByThymeleaf.generateHtmlReportWithTemplate(rrrMap,templatePath);
result.setSuccess(true);
result.setResult(html);
return new Result<>();
}
@Override @Override
public void exportRRR(Integer sampleId, String fileName, HttpServletRequest request, public void exportRRR(Integer sampleId, String fileName, HttpServletRequest request,
HttpServletResponse response) { HttpServletResponse response) {
@ -5362,6 +5382,27 @@ public class GammaServiceImpl extends AbstractLogOrReport implements IGammaServi
FileInputStream in = new FileInputStream(rptFile); FileInputStream in = new FileInputStream(rptFile);
ftpUtil.saveFile(spectrumPathProperties.getRootPath() + ftpUtil.saveFile(spectrumPathProperties.getRootPath() +
middleData.analyses_absolute_ReportPath + ".txt", in); middleData.analyses_absolute_ReportPath + ".txt", in);
Map<String, Object> rrrMap = gammaFileUtil.OutPutRrrHtml(middleData);
String targetDir =
spectrumPathProperties.getRootPath() + middleData.analyses_absolute_ReportPath;
Path destinationDir = Paths.get(targetDir);
try {
// 创建目录及所有不存在的父目录
// 模板文件放在 src/main/resources/templates/my-report.html
String templatePath = "templates/reportP.html";
if (!Files.exists(destinationDir)) {
Files.createDirectories(destinationDir);
}
// 完整文件路径
Path htmlFile =
destinationDir.resolve(destinationDir.getFileName() + ".html");
reportByThymeleaf.generateHtmlReportWithTemplateToFile(rrrMap,templatePath, htmlFile.toString());
} catch (IOException e) {
System.err.println("目录创建失败: " + e.getMessage());
e.printStackTrace();
}
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} finally { } finally {

View File

@ -0,0 +1,272 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Radionuclide Report</title>
<style>
body { font-family: 'Courier New', Courier, monospace; background-color: #f4f7f6; padding: 20px; color: #333; }
.report-container { max-width: 1100px; margin: 0 auto; background: #fff; padding: 30px; box-shadow: 0 0 10px rgba(0,0,0,0.1); border-radius: 4px; }
h1, h2, h3 { text-align: center; margin: 5px 0; }
.section-title { font-weight: bold; font-size: 16px; margin-top: 25px; margin-bottom: 10px; border-bottom: 2px solid #333; padding-bottom: 3px; }
/* 模拟原报告的网格对齐或直接使用标准HTML表格 */
.info-table { width: 100%; border-collapse: collapse; margin-bottom: 15px; }
.info-table td { padding: 4px 8px; vertical-align: top; }
.info-table td.label { width: 30%; color: #555; }
.info-table td.value { width: 70%; font-weight: bold; }
.data-table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 13px; }
.data-table th { background-color: #f2f2f2; border: 1px solid #ddd; padding: 8px; text-align: left; }
.data-table td { border: 1px solid #ddd; padding: 6px 8px; }
.data-table tr:nth-child(even) { background-color: #fafafa; }
.pass-flag { color: green; font-weight: bold; }
.fail-flag { color: red; font-weight: bold; }
</style>
</head>
<body>
<div class="report-container">
<!-- 头部标题区域 -->
<h1>CNL06 GENERATED REPORT</h1>
<h2 th:text="${middleData.analyses_type + ' RADIONUCLIDE REPORT'}">SAMPLE RADIONUCLIDE REPORT</h2>
<!-- 动态样品版本判断 -->
<h3>
<span th:if="${middleData.sample_Type == 'PARTICULATE'}">(Particulates Version)</span>
<span th:if="${middleData.sample_Type == 'GAMMA' || middleData.sample_Type == 'SELFSTATION'}">(Noble Gas Version)</span>
</h3>
<!-- 报告创建时间直接在前端使用 Thymeleaf dates 工具动态获取 -->
<p style="text-align: center;" th:text="${'Creation Date ' + #dates.format(#dates.createNow(), 'yyyy/MM/dd-HH:mm:ss')}"></p>
<!-- #1. SAMPLE INFORMATION -->
<div class="section-title">#SAMPLE INFORMATION</div>
<table class="info-table">
<tr><td class="label">Station ID:</td><td class="value" th:text="${middleData.sample_stationID}"></td></tr>
<tr><td class="label">Detector ID:</td><td class="value" th:text="${middleData.sample_detectID}"></td></tr>
<tr><td class="label">Sample ID:</td><td class="value" th:text="${middleData.sample_id}"></td></tr>
<tr><td class="label">Sample Geometry:</td><td class="value" th:text="${middleData.sample_Geometry}"></td></tr>
<tr><td class="label">Sample Quantity[m3]:</td><td class="value" th:text="${middleData.sample_quantity}"></td></tr>
<tr><td class="label">Sample Type:</td><td class="value" th:text="${middleData.sample_Type}"></td></tr>
<tr><td class="label">Collection Start:</td><td class="value" th:text="${middleData.sample_collection_start}"></td></tr>
<tr><td class="label">Collection Stop:</td><td class="value" th:text="${middleData.sample_collection_stop}"></td></tr>
<tr><td class="label">Sampling Time[h]:</td><td class="value" th:text="${middleData.sample_time}"></td></tr>
<tr><td class="label">Decay Time[h]:</td><td class="value" th:text="${middleData.sample_decay_time}"></td></tr>
<tr><td class="label">Acquisition Start:</td><td class="value" th:text="${middleData.sample_acquisiton_start}"></td></tr>
<tr><td class="label">Acquisition Stop:</td><td class="value" th:text="${middleData.sample_acquistion_stop}"></td></tr>
<tr><td class="label">Acquisition Time[s]:</td><td class="value" th:text="${middleData.sample_acquistion_time}"></td></tr>
<tr><td class="label">Avg Flow Rate[m3/h]:</td><td class="value" th:text="${middleData.sample_Avg_Flow_Rate}"></td></tr>
<tr><td class="label">Collection Station Comments:</td><td class="value" th:text="${middleData.Collection_Station_Comments}"></td></tr>
<tr><td class="label">Analysis General Comments:</td><td class="value" th:text="${middleData.NDC_Analysis_General_Comments}"></td></tr>
</table>
<!-- #2. ACTIVITY SUMMARY -->
<div class="section-title">#ACTIVITY SUMMARY</div>
<table class="info-table">
<tr>
<td class="label">Nuclides Identified:</td>
<!-- 在前端用 Thymeleaf 拼接 List 为分号隔开的字符串 -->
<td class="value" th:text="${#strings.join(middleData.nucl_ided_Nuclidename, ';')}"></td>
</tr>
<tr><td class="label">Keyline Activities for Nuclides:</td><td class="value">with defined Reference Line</td></tr>
<tr><td class="label">Activity Reference Time:</td><td class="value" th:text="${middleData.sample_acquisiton_start}"></td></tr>
<tr><td class="label">Concentration Reference Time:</td><td class="value" th:text="${middleData.sample_collection_start}"></td></tr>
</table>
<!-- 核素具体数据列表 -->
<table class="data-table">
<thead>
<tr>
<th>Nuclide</th><th>Halflife(s)</th><th>Activity(Bq)</th><th>RelErr%</th><th>MDA(Bq)</th><th>Conc(uBq/m^3)</th><th>MDC</th>
</tr>
</thead>
<tbody>
<!-- 利用 th:each status 做到多 List 按相同索引同步遍历 -->
<tr th:each="nuclide, stat : ${middleData.nucl_ided_Nuclidename}">
<td th:text="${nuclide}"></td>
<td th:text="${middleData.nucl_ided_Halflife[stat.index]}"></td>
<!-- 前端格式化数字保留3位小数 -->
<td th:text="${#numbers.formatDecimal(middleData.nucl_ided_activ_key[stat.index], 1, 3)}"></td>
<!-- 复杂的数学计算直接移到 Thymeleaf 表达式中完成 -->
<td th:text="${#numbers.formatDecimal((tostringformat == null ? (100.0 * middleData.nucl_ided_activ_key_err[stat.index] / middleData.nucl_ided_activ_key[stat.index]) : 0), 1, 3)}"></td>
<td th:text="${middleData.nucl_ided_mda[stat.index]}"></td>
<td th:text="${middleData.nucl_ided_Concentration[stat.index]}"></td>
<td th:text="${middleData.nucl_ided_MDC[stat.index]}"></td>
</tr>
</tbody>
</table>
<!-- #3. MINIMUM DETECTABLE CONCENTRATION FOR KEY NUCLIDES -->
<div class="section-title">#MINIMUM DETECTABLE CONCENTRATION FOR KEY NUCLIDES</div>
<table class="data-table">
<thead>
<tr>
<th>Nuclide</th>
<th>Halflife</th>
<th>MDC(uBq/m3)</th>
<!-- 根据动态条件判断是否显示 MDA -->
<th th:if="${#lists.anyString(middleData.mdcInfos, 'mdaStr')}">MDA(uBq)</th>
</tr>
</thead>
<tbody>
<tr th:each="mdc : ${middleData.mdcInfos}">
<td th:text="${mdc.nuclideName}"></td>
<td th:text="${mdc.halfLifeStr}"></td>
<td th:text="${mdc.mdcStr}"></td>
<td th:if="${#lists.anyString(middleData.mdcInfos, 'mdaStr')}" th:text="${mdc.mdaStr}"></td>
</tr>
</tbody>
</table>
<!-- #4. PEAK SEARCH RESULTS -->
<div class="section-title">#PEAK SEARCH RESULTS</div>
<!-- JS 计算复杂的峰值统计 Thymeleaf 内联语法将数据无缝传给 JS -->
<div id="peak-statistics-box">
<p><span id="total-peaks" th:text="${middleData.peaks_idPeak.size()}">0</span> peaks reported:</p>
<p><span id="used-peaks">0</span> peaks with ID (<span id="used-peaks-percent">0%</span>):</p>
<p><span id="unused-peaks">0</span> peaks without ID (<span id="unused-peaks-percent">0%</span>):</p>
</div>
<table class="data-table">
<thead>
<tr>
<th>PeakID</th><th>Energy[kev]</th><th>Centroid</th><th>FWHM[kev]</th><th>NetArea</th><th>NAErr%</th><th>Signif</th><th>Sensit</th><th>Nuclide</th>
</tr>
</thead>
<tbody>
<tr th:each="peakId, stat : ${middleData.peaks_idPeak}">
<td th:text="${peakId}"></td>
<td th:text="${#numbers.formatDecimal(middleData.peaks_Energy[stat.index], 1, 3)}"></td>
<td th:text="${#numbers.formatDecimal(middleData.peaks_peakCentroid[stat.index], 1, 3)}"></td>
<td th:text="${#numbers.formatDecimal(middleData.peaks_Fwhm[stat.index], 1, 3)}"></td>
<td th:text="${#numbers.formatDecimal(middleData.peaks_Area[stat.index], 1, 3)}"></td>
<td th:text="${#numbers.formatDecimal((100.0 * middleData.peaks_areaErr[stat.index] / middleData.peaks_Area[stat.index]), 1, 3)}"></td>
<td th:text="${#numbers.formatDecimal(middleData.peaks_Significance[stat.index], 1, 3)}"></td>
<td th:text="${#numbers.formatDecimal(middleData.peaks_Sensitivity[stat.index], 1, 3)}"></td>
<!-- 对应原代码StringUtils.join(..., ';') -->
<td th:text="${#strings.join(middleData.peaks_Nuclide_name[stat.index], ';')}"></td>
</tr>
</tbody>
</table>
<!-- #5. PROCESSING PARAMETERS -->
<div class="section-title">#PROCESSING PARAMETERS</div>
<table class="info-table" th:if="${middleData.setting_specSetup != null}">
<tr><td class="label">ECutAnalysis_Low:</td><td class="value" th:text="${middleData.setting_specSetup.ECutAnalysis_Low}"></td></tr>
<tr>
<td class="label">ECutAnalysis_High:</td>
<td class="value" th:text="${middleData.setting_specSetup.ECutAnalysis_High == -9999 ? 'inf' : middleData.setting_specSetup.ECutAnalysis_High}"></td>
</tr>
<tr><td class="label">EnergyTolerance:</td><td class="value" th:text="${middleData.setting_specSetup.EnergyTolerance}"></td></tr>
<tr><td class="label">BaseImprovePSS:</td><td class="value" th:text="${middleData.setting_specSetup.BaseImprovePSS}"></td></tr>
<tr><td class="label">Pss_low:</td><td class="value" th:text="${middleData.setting_specSetup.pss_low}"></td></tr>
<tr><td class="label">k_back:</td><td class="value" th:text="${middleData.setting_specSetup.k_back}"></td></tr>
<tr><td class="label">k_alpha:</td><td class="value" th:text="${middleData.setting_specSetup.k_alpha}"></td></tr>
<tr><td class="label">k_beta:</td><td class="value" th:text="${middleData.setting_specSetup.k_beta}"></td></tr>
<tr><td class="label">RiskLevelK:</td><td class="value" th:text="${middleData.setting_specSetup.riskLevelK}"></td></tr>
<tr><td class="label">refTime_act:</td><td class="value" th:text="${#dates.format(middleData.setting_specSetup.refTime_act, 'yyyy-MM-dd HH:mm:ss')}"></td></tr>
<tr><td class="label">refTime_conc:</td><td class="value" th:text="${#dates.format(middleData.setting_specSetup.refTime_conc, 'yyyy-MM-dd HH:mm:ss')}"></td></tr>
</table>
<!-- #6. CALIBRATION PARAMETERS -->
<div class="section-title">#CALIBRATION PARAMETERS</div>
<table class="info-table" th:if="${middleData.setting_specSetup != null}">
<tr><td class="label">CalibrationPSS_low:</td><td class="value" th:text="${middleData.setting_specSetup.CalibrationPSS_low}"></td></tr>
<tr><td class="label">CalibrationPSS_high:</td><td class="value" th:text="${middleData.setting_specSetup.CalibrationPSS_high}"></td></tr>
<tr><td class="label">bUpdateCal:</td><td class="value" th:text="${middleData.setting_specSetup.bUpdateCal ? '1' : '0'}"></td></tr>
<tr><td class="label">KeepCalPeakSearchPeaks:</td><td class="value" th:text="${middleData.setting_specSetup.keepCalPeakSearchPeaks ? '1' : '0'}"></td></tr>
</table>
<!-- 多重 Calibration 条件判断区块 -->
<div th:if="${#lists.size(middleData.calibration_pairs_E_idCalPoint) > 0}">
<div class="section-title">#Calibration (Energy Calibration)</div>
<table class="info-table">
<tr><td class="label">Function:</td><td class="value" th:text="${middleData.calibration_E_functionTypeDef}"></td></tr>
<tr><td class="label">E:</td><td class="value" th:text="${middleData.calibration_E_functionDef}"></td></tr>
<tr><td class="label">P:</td><td class="value" th:text="${middleData.calibration_E_coeff_string}"></td></tr>
<tr><td class="label">Err:</td><td class="value" th:text="${middleData.calibration_E_uncoeff_string}"></td></tr>
<tr><td class="label">Data:</td><td class="value" th:text="${middleData.calibration_pairs_E_Input}"></td></tr>
</table>
</div>
<div th:if="${#lists.size(middleData.calibration_pairs_R_idCalPoint) > 0}">
<div class="section-title">Resolution Calibration</div>
<table class="info-table">
<tr><td class="label">Function:</td><td class="value" th:text="${middleData.calibration_R_functionTypeDef}"></td></tr>
<tr><td class="label">E:</td><td class="value" th:text="${middleData.calibration_R_functionDef}"></td></tr>
<tr><td class="label">P:</td><td class="value" th:text="${middleData.calibration_R_coeff_string}"></td></tr>
<tr><td class="label">Err:</td><td class="value" th:text="${middleData.calibration_R_uncoeff_string}"></td></tr>
<tr><td class="label">Data:</td><td class="value" th:text="${middleData.calibration_pairs_R_Input}"></td></tr>
</table>
</div>
<div th:if="${#lists.size(middleData.calibration_pairs_EF_idCalPoint) > 0}">
<div class="section-title">Efficiency Calibration</div>
<table class="info-table">
<tr><td class="label">Function:</td><td class="value" th:text="${middleData.calibration_EF_functionTypeDef}"></td></tr>
<tr><td class="label">E:</td><td class="value" th:text="${middleData.calibration_EF_functionDef}"></td></tr>
<tr><td class="label">P:</td><td class="value" th:text="${middleData.calibration_EF_coeff_string}"></td></tr>
<tr><td class="label">Err:</td><td class="value" th:text="${middleData.calibration_EF_uncoeff_string}"></td></tr>
<tr><td class="label">Data:</td><td class="value" th:text="${middleData.calibration_pairs_EF_Input}"></td></tr>
</table>
</div>
<!-- #7. DATA QUALITY FLAGS -->
<div class="section-title">#DATA QUALITY FLAGS</div>
<table class="data-table">
<thead>
<tr>
<th>Name</th><th>Pass/Fail</th><th>Value</th><th>Test</th>
</tr>
</thead>
<tbody>
<tr th:each="qcName, stat : ${middleData.QC_CHECK_QC_NAME}">
<td th:text="${qcName}"></td>
<!-- 对应原代码Double.valueOf(QC_RESULT) < 1 ? "Fail" : "Pass" -->
<td>
<span th:if="${middleData.QC_CHECK_QC_RESULT[stat.index] < 1}" class="fail-flag">Fail</span>
<span th:if="${middleData.QC_CHECK_QC_RESULT[stat.index] >= 1}" class="pass-flag">Pass</span>
</td>
<!-- 对应原代码的数字格式化及 null 判断 -->
<td>
<span th:if="${middleData.QC_CHECK_QC_VALUE[stat.index] != null}" th:text="${#numbers.formatDecimal(middleData.QC_CHECK_QC_VALUE[stat.index], 1, 3)}"></span>
<span th:if="${middleData.QC_CHECK_QC_VALUE[stat.index] == null}">null</span>
</td>
<td th:text="${middleData.QC_CHECK_QC_STANDARD[stat.index]}"></td>
</tr>
</tbody>
</table>
</div>
<!-- 通过 Thymeleaf 内联 JavaScript 引擎优雅地在前端执行复杂的峰值占比运算 -->
<script th:inline="javascript">
document.addEventListener("DOMContentLoaded", function() {
// 1. 无缝将 Thymeleaf Java 数组传给前端 JS
const nuclideNames = [[${middleData.peaks_Nuclide_name}]];
const totalPeaks = nuclideNames.length;
// 2. 原生 JS 过滤非空峰值对应原 Java 里的 peaksUsed 逻辑
let peaksUsed = 0;
nuclideNames.forEach(name => {
if (name && name.trim() !== '') {
peaksUsed++;
}
});
const peaksWithoutId = totalPeaks - peaksUsed;
const usedPercent = totalPeaks > 0 ? ((peaksUsed / totalPeaks) * 100).toFixed(4) : "0.0000";
const unusedPercent = totalPeaks > 0 ? ((peaksWithoutId / totalPeaks) * 100).toFixed(4) : "0.0000";
// 3. 将计算好的数据安全地写入网页 DOM 节点
document.getElementById("used-peaks").innerText = peaksUsed;
document.getElementById("used-peaks-percent").innerText = usedPercent + "%";
document.getElementById("unused-peaks").innerText = peaksWithoutId;
document.getElementById("unused-peaks-percent").innerText = unusedPercent + "%";
});
</script>
</body>
</html>

View File

@ -15,7 +15,7 @@
#{stationId} #{stationId}
</foreach> </foreach>
</if> </if>
AND d.TIME BETWEEN to_timestamp(#{params.startTime}, 'YYYY-MM-DD HH24:MI:SS') AND to_timestamp(#{params.endTime}, 'YYYY-MM-DD HH24:MI:SS') AND d.TIME BETWEEN #{params.startTime} AND #{params.endTime}
</where> </where>
ORDER BY d.TIME DESC ORDER BY d.TIME DESC
</select> </select>