Compare commits

..

10 Commits
mdc ... noFtp-F

Author SHA1 Message Date
nieziyan
939ffb1f6c feat:完善AutoProcess F状态数据解析 2024-06-07 18:25:16 +08:00
nieziyan
6b16aa6a40 fix:bug 2024-06-07 09:35:48 +08:00
nieziyan
41245f0546 feat:自动处理分析失败谱可以加载其基础数据 2024-06-06 10:30:42 +08:00
nieziyan
86968e383b fix:删除多余文件 2024-05-13 14:58:41 +08:00
qiaoqinzheng
9fffd2436c 自动处理模块模块同步代码 2024-05-13 14:14:01 +08:00
qiaoqinzheng
2407b65a06 自动处理模块下载邮件代码修改 2024-05-13 14:09:42 +08:00
qiaoqinzheng
6c5a0bf546 人工交互模块BetaDataFile实体类增加detectorId字段用于报警使用 2024-05-13 09:24:25 +08:00
qiaoqinzheng
caf47a58d5 人工交互模块增加判断如果不是正常谱提示异常信息内容 2024-05-10 16:12:26 +08:00
nieziyan
18b495d1d0 Merge remote-tracking branch 'origin/noFtp' into noFtp 2024-04-25 15:05:45 +08:00
nieziyan
6335a3f588 fix:修改FTP为本地文件 2024-04-24 09:34:59 +08:00
338 changed files with 5417 additions and 34858 deletions

View File

@ -124,6 +124,13 @@
<version>${mysql-connector-java.version}</version>
<scope>runtime</scope>
</dependency>
<!-- sqlserver-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>${sqljdbc4.version}</version>
<scope>runtime</scope>
</dependency>
<!-- oracle驱动 -->
<dependency>
<groupId>com.oracle</groupId>

View File

@ -41,14 +41,4 @@ public interface RedisConstant {
String EMAIL_MSG_ID = "email_msg_id";
String UNDEAL_FILE = "Undeal:";
//自动分析等级
String AUTO_CAT = "Stream:AutoCat";
String GROUP_AutoCat = "Group_AutoCat";
String AUTO_CONSUMER = "AutoCat_Consumer";
//人工交互等级
String CATEGORY = "Stream:Category";
String GROUP_Category = "Group_Category";
String CATEGORY_CONSUMER = "Category_Consumer";
}

View File

@ -126,8 +126,4 @@ public class SymbolConstant {
public static final String LINE = "\n";
public static final String AT = "@";
public static final String VERTICAL = "|";
public static final char VERTICAL_CHAR = '|';
}

View File

@ -1,16 +1,15 @@
package org.jeecg.common.email;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.sun.mail.imap.IMAPStore;
import com.sun.mail.pop3.POP3Folder;
import com.sun.mail.smtp.SMTPAddressFailedException;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
@ -22,10 +21,10 @@ import org.jeecg.common.exception.DownloadEmailException;
import org.jeecg.common.properties.SpectrumPathProperties;
import org.jeecg.common.properties.TaskProperties;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.Md5Util;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.entity.postgre.SysEmail;
import org.jetbrains.annotations.NotNull;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
@ -36,11 +35,7 @@ import javax.mail.search.SearchTerm;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
@ -62,53 +57,39 @@ public class EmailServiceManager {
* 系统启动时间
*/
private Date systemStartupTime;
/**
* 邮件接收数量
*/
/** 邮件接收数量 */
private Integer receiveNum;
/**
* smtp协议的存储对象
*/
//private IMAPStore store = null;
private Store store = null;
/**
* 邮件附件临时存储路径
*/
/** smtp协议的存储对象 */
private IMAPStore store = null;
/** 邮件附件临时存储路径 */
private String temporaryStoragePath;
/**
* 收件箱
*/
/** 收件箱 */
private Folder folder = null;
// 判断协议类型
private String protocol;
private RedisUtil redisUtil;
private Object downloadEmlLocal = new Object();
private final ReentrantLock lock = new ReentrantLock();
@NotNull
public static EmailServiceManager getInstance() {
public static EmailServiceManager getInstance(){
return new EmailServiceManager();
}
/**
* 初始化邮件服务管理器
*
* @param email 邮件属性
*/
public void init(SysEmail email) {
public void init(SysEmail email){
this.email = email;
}
/**
* 初始化邮件服务管理器
*
* @param email 邮件属性
*/
public void init(SysEmail email, Integer receiveNum, String temporaryStoragePath,
Date systemStartupTime, SpectrumPathProperties pathProperties, TaskProperties taskProperties,
RedisUtil redisUtil) {
Date systemStartupTime, SpectrumPathProperties pathProperties,TaskProperties taskProperties,
RedisUtil redisUtil){
this.email = email;
this.receiveNum = receiveNum;
this.temporaryStoragePath = temporaryStoragePath;
@ -121,18 +102,18 @@ public class EmailServiceManager {
/**
* 测试邮件服务连通性
*/
public boolean testConnectEmailServer() {
public boolean testConnectEmailServer(){
Socket socket = new Socket();
boolean flag = false;
try {
socket.connect(new InetSocketAddress(email.getEmailServerAddress(), email.getPort()), 3000);
log.info("{}邮件服务连接测试成功", email.getName());
socket.connect(new InetSocketAddress(email.getEmailServerAddress(),email.getPort()),3000);
log.info("{}邮件服务连接测试成功",email.getName());
flag = true;
} catch (IOException e) {
log.error("{}邮件服务连接测试失败,请检查邮件服务属性配置是否正确或邮件服务未开启,原因: ", email.getName(), e);
} finally {
log.error("{}邮件服务连接测试失败,请检查邮件服务属性配置是否正确或邮件服务未开启,原因{}",email.getName(),e.getMessage());
}finally {
try {
if (null != socket) {
if(null != socket){
socket.close();
}
} catch (IOException e) {
@ -145,16 +126,14 @@ public class EmailServiceManager {
/**
* 接收邮件
*/
public Message[] receiveMail1() throws Exception {
public Message[] receiveMail() throws MessagingException {
String status = EmailLogManager.STATUS_SUCCESS;
try {
try{
//配置邮件服务属性
Properties properties = new Properties();
properties.put("mail.store.protocol", "imap");
properties.put("mail.imap.host", email.getEmailServerAddress());
properties.put("mail.imap.port", email.getPort());
properties.put("mail.imap.connectiontimeout", "3000");
properties.put("mail.imap.timeout", "3000");
properties.put("mail.imap.port",email.getPort());
if (email.getIsQiye() == 1) {
properties.put("mail.imap.ssl.enable", "true");
} else {
@ -163,10 +142,10 @@ public class EmailServiceManager {
HashMap IAM = new HashMap();
//带上IMAP ID信息由key和value组成例如nameversionvendorsupport-email等
IAM.put("name", "myname");
IAM.put("version", "1.0.0");
IAM.put("vendor", "myclient");
IAM.put("support-email", "testmail@test.com");
IAM.put("name","myname");
IAM.put("version","1.0.0");
IAM.put("vendor","myclient");
IAM.put("support-email","testmail@test.com");
//获取邮件回话
final Session session = Session.getDefaultInstance(properties);
@ -175,194 +154,64 @@ public class EmailServiceManager {
//获取smtp协议的存储对象
store = (IMAPStore) session.getStore();
//连接
store.connect(email.getUsername(), email.getPassword());
if (email.getEmailServerType() == 1) {
// 解决163普通邮箱无法建立连接问题
((IMAPStore) store).id(IAM);
}
store.connect(email.getUsername(),email.getPassword());
// 解决163普通邮箱无法建立连接问题
store.id(IAM);
//获取收件箱
folder = store.getFolder("INBOX");//INBOX
folder.open(Folder.READ_WRITE);
//如果邮箱邮件数量 > 0
final int messageCount = folder.getMessageCount();
if (messageCount > 0) {
if(messageCount > 0){
Message[] messages = null;
if (Objects.isNull(this.systemStartupTime)) {
int finalNum = messageCount > this.receiveNum ? this.receiveNum : messageCount;
if(Objects.isNull(this.systemStartupTime)){
int finalNum = messageCount > this.receiveNum?this.receiveNum:messageCount;
//邮箱邮件下标是从1开始的
return folder.getMessages(1, finalNum);
return folder.getMessages(1,finalNum);
}
SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GE, this.systemStartupTime);
SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GE,this.systemStartupTime);
messages = folder.search(searchTerm);
Arrays.sort(messages, (o1, o2) -> {
try {
return o1.getReceivedDate().compareTo(o2.getReceivedDate());
} catch (MessagingException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
return 0;
});
if (this.receiveNum >= messages.length) {
if(this.receiveNum >= messages.length){
return messages;
} else {
return Arrays.copyOfRange(messages, 0, this.receiveNum - 1);
}else{
return Arrays.copyOfRange(messages,0,this.receiveNum-1);
}
}
} catch (Exception e) {
} catch (MessagingException e){
status = EmailLogManager.STATUS_ERROR;
log.error("Email connection is abnormal, account is {}, service is {},the reason is {}.", email.getName(), email.getEmailServerAddress(), e.getMessage());
log.error("Email connection is abnormal, account is {}, service is {},the reason is {}.",email.getName(),email.getEmailServerAddress(),e.getMessage());
throw e;
} finally {
EmailLogEvent connectEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET, email, status, EmailLogManager.CONNECT);
EmailLogEvent connectEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET,email,status,EmailLogManager.CONNECT);
EmailLogManager.getInstance().setConnectLogEvent(connectEvent);
//GetAllId C++原业务是把远程邮箱邮件同步到C++本次java编写没有这一步所以和Connect绑定若Connect成功则GetAllId成功
EmailLogEvent getAllEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETALLID);
EmailLogEvent getAllEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET,status,EmailLogManager.GETALLID);
EmailLogManager.getInstance().setGetAllIdLogEvent(getAllEvent);
}
return null;
}
public Message[] receiveMail() throws Exception {
String status = EmailLogManager.STATUS_SUCCESS;
try {
store = setStoreProperties();
//获取收件箱
folder = store.getFolder("INBOX");//INBOX
folder.open(Folder.READ_WRITE);
//如果邮箱邮件数量 > 0
final int messageCount = folder.getMessageCount();
if (messageCount > 0) {
Message[] messages = null;
if (Objects.isNull(this.systemStartupTime)) {
int finalNum = messageCount > this.receiveNum ? this.receiveNum : messageCount;
//邮箱邮件下标是从1开始的
return folder.getMessages(1, finalNum);
}
SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GE, this.systemStartupTime);
messages = folder.search(searchTerm);
Arrays.sort(messages, (o1, o2) -> {
try {
if (o1.getReceivedDate() == null && o2.getReceivedDate() == null) {
return o1.getSentDate().compareTo(o2.getSentDate());
} else {
return o1.getReceivedDate().compareTo(o2.getReceivedDate());
}
} catch (MessagingException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
return 0;
});
if (this.receiveNum >= messages.length) {
return messages;
} else {
return Arrays.copyOfRange(messages, 0, this.receiveNum - 1);
}
}
} catch (Exception e) {
status = EmailLogManager.STATUS_ERROR;
log.error("Email connection is abnormal, account is {}, service is {},the reason is {}.", email.getName(), email.getEmailServerAddress(), e.getMessage());
throw e;
} finally {
EmailLogEvent connectEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET, email, status, EmailLogManager.CONNECT);
EmailLogManager.getInstance().setConnectLogEvent(connectEvent);
//GetAllId C++原业务是把远程邮箱邮件同步到C++本次java编写没有这一步所以和Connect绑定若Connect成功则GetAllId成功
EmailLogEvent getAllEvent = new EmailLogEvent(EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETALLID);
EmailLogManager.getInstance().setGetAllIdLogEvent(getAllEvent);
}
return null;
}
private Store setStoreProperties() throws MessagingException {
HashMap IAM = new HashMap();
//带上IMAP ID信息由key和value组成例如nameversionvendorsupport-email等
IAM.put("name", "myname");
IAM.put("version", "1.0.0");
IAM.put("vendor", "myclient");
IAM.put("support-email", "testmail@test.com");
Properties properties = getProperties();
//获取邮件回话
Session session = Session.getInstance(properties);
//获取smtp协议的存储对象
Store store = session.getStore();
log.info("连接 {}:{}:{}", email.getUsername(), email.getPassword(), email.getPort());
//连接
store.connect(email.getUsername(), email.getPassword());
if (email.getEmailServerType() == 1) {
// 解决163普通邮箱无法建立连接问题
((IMAPStore) store).id(IAM);
}
protocol = store.getURLName().getProtocol();
return store;
}
@NotNull
private Properties getProperties() {
Properties properties = new Properties();
switch (email.getPort()) {
case 110:
properties.put("mail.store.protocol", "pop3");
properties.put("mail.pop3.host", email.getEmailServerAddress());
properties.put("mail.pop3.port", email.getPort());
properties.put("mail.pop3.starttls.enable", "true");
// 超时设置(毫秒)
properties.put("mail.pop3.connectiontimeout", "10000");
properties.put("mail.pop3.timeout", "15000");
break;
case 995:
properties.put("mail.store.protocol", "pop3");
properties.put("mail.pop3.host", email.getEmailServerAddress());
properties.put("mail.pop3.port", email.getPort());
properties.put("mail.pop3.starttls.enable", "true");
properties.put("mail.pop3.connectiontimeout", "10000");
properties.put("mail.pop3.timeout", "15000");
properties.put("mail.pop3.auth", "true");
break;
case 143:
properties.put("mail.store.protocol", "imap");
properties.put("mail.imap.host", email.getEmailServerAddress());
properties.put("mail.imap.port", email.getPort());
properties.put("mail.imap.ssl.enable", "false");
properties.put("mail.imap.starttls.enable", "true");
properties.put("mail.imap.auth", "true");
// 超时设置(毫秒)
properties.put("mail.imap.connectiontimeout", "10000");
properties.put("mail.imap.timeout", "30000");
break;
case 993:
default:
properties.put("mail.store.protocol", "imap");
properties.put("mail.imap.host", email.getEmailServerAddress());
properties.put("mail.imap.port", email.getPort());
properties.put("mail.imap.connectiontimeout", "3000");
properties.put("mail.imap.timeout", "3000");
if (email.getIsQiye() == 1) {
properties.put("mail.imap.ssl.enable", "true");
} else {
properties.put("mail.imap.ssl.enable", "false");
}
break;
}
return properties;
}
/*
* 测试收件邮箱账号是否可以正常使用
* */
public boolean canReceive() {
public boolean canReceive(){
Integer port = email.getPort();
String username = email.getUsername();
String password = email.getPassword();
String host = email.getEmailServerAddress();
Properties props = getProperties();
Properties props = new Properties();
props.put("mail.store.protocol","imap");
props.put("mail.imap.host", host);
props.put("mail.imap.port", port);
Session session = Session.getInstance(props, new Authenticator() {
@Override
@ -371,26 +220,26 @@ public class EmailServiceManager {
}
});
try (Store store = session.getStore()) {
try(Store store = session.getStore()) {
store.connect(host, username, password);
return store.isConnected();
} catch (Exception e) {
log.error("收件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage());
log.error("收件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage());
return false;
}
}
/*
* 测试收件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱)
* */
public boolean canReceiveSSL() {
* 测试收件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱)
* */
public boolean canReceiveSSL(){
Integer port = email.getPort();
String username = email.getUsername();
String password = email.getPassword();
String host = email.getEmailServerAddress();
Properties props = new Properties();
props.put("mail.store.protocol", "imap");
props.put("mail.store.protocol","imap");
props.put("mail.imap.host", host);
props.put("mail.imap.port", port);
props.put("mail.imap.auth", "true");
@ -404,19 +253,19 @@ public class EmailServiceManager {
}
});
try (Store store = session.getStore()) {
try(Store store = session.getStore()) {
store.connect(host, username, password);
return store.isConnected();
} catch (Exception e) {
log.error("收件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage());
log.error("收件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage());
return false;
}
}
/*
* 测试发件邮箱账号是否可以正常使用
* */
public boolean canSend() {
* 测试发件邮箱账号是否可以正常使用
* */
public boolean canSend(){
Integer port = email.getPort();
String username = email.getUsername();
String password = email.getPassword();
@ -435,19 +284,19 @@ public class EmailServiceManager {
}
});
try (Transport transport = session.getTransport()) {
try (Transport transport = session.getTransport()){
transport.connect(host, username, password);
return true;
} catch (Exception e) {
log.error("发件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage());
log.error("发件邮箱服务[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage());
return false;
}
}
/*
* 测试发件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱)
* */
public boolean canSendSSL() {
* 测试发件邮箱账号是否可以正常使用(开启了SSL安全验证的邮箱)
* */
public boolean canSendSSL(){
Integer port = email.getPort();
String username = email.getUsername();
String password = email.getPassword();
@ -468,11 +317,11 @@ public class EmailServiceManager {
}
});
try (Transport transport = session.getTransport()) {
try (Transport transport = session.getTransport()){
transport.connect(host, username, password);
return true;
} catch (Exception e) {
log.error("发件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}", host, port, username, e.getMessage());
log.error("发件邮箱服务SSL[Host: {}, Port: {}, Username: {}]连接异常: {}",host, port, username, e.getMessage());
return false;
}
}
@ -508,7 +357,7 @@ public class EmailServiceManager {
// 发送邮件
Transport transport = session.getTransport();
transport.connect(email.getUsername(), email.getPassword());
transport.connect(email.getUsername(),email.getPassword());
transport.sendMessage(message, message.getAllRecipients());
// 关闭资源
@ -518,7 +367,7 @@ public class EmailServiceManager {
/**
* 发送邮件 群发
*/
public void sendMail(MessageDTO messageDTO) {
public void sendMail(MessageDTO messageDTO){
// 邮箱连接属性
Properties props = new Properties();
props.put("mail.transport.protocol", "smtp");
@ -543,24 +392,24 @@ public class EmailServiceManager {
InternetAddress.parse(messageDTO.getToUser()));
// 发送邮件
transport = session.getTransport();
transport.connect(email.getUsername(), email.getPassword());
transport.sendMessage(message, message.getAllRecipients());
transport.connect(email.getUsername(),email.getPassword());
transport.sendMessage(message,message.getAllRecipients());
} catch (MessagingException e) {
// 无效的电子邮箱导致群发失败,剔除无效邮箱然后重新发送
Address[] invalid;
if (e instanceof SMTPAddressFailedException) {
invalid = ((SMTPAddressFailedException) e).getInvalidAddresses();
reSendMail(invalid, messageDTO);
reSendMail(invalid,messageDTO);
} else if (e instanceof SendFailedException) {
invalid = ((SendFailedException) e).getInvalidAddresses();
reSendMail(invalid, messageDTO);
reSendMail(invalid,messageDTO);
}
} finally {
if (transport != null) {
}finally {
if (transport != null){
try {
transport.close();
} catch (MessagingException e) {
log.error("Transport关闭失败,{}", e);
log.error("Transport关闭失败,{}",e);
}
}
}
@ -572,20 +421,20 @@ public class EmailServiceManager {
* @param invalid 无效电子邮箱列表
* @param messageDTO 消息dto
*/
private void reSendMail(Address[] invalid, MessageDTO messageDTO) {
private void reSendMail(Address[] invalid,MessageDTO messageDTO){
List<String> invalidEmails = Arrays.stream(invalid)
.map(address -> address.toString())
.collect(Collectors.toList());
log.warn("部分或者全部邮件发送失败,无效的电子邮箱:{}", invalidEmails);
log.warn("部分或者全部邮件发送失败,无效的电子邮箱:{}",invalidEmails);
String[] allEmails = messageDTO.getToUser().split(SymbolConstant.COMMA);
String[] emails = new String[]{};
for (String address : invalidEmails) {
emails = ArrayUtil.removeEle(allEmails, address);
emails = ArrayUtil.removeEle(allEmails,address);
}
// 如果移除无效电子邮箱后,待发送邮箱不为空
String toUser = Arrays.stream(emails)
.collect(Collectors.joining(SymbolConstant.COMMA));
if (StrUtil.isNotBlank(toUser)) {
if (StrUtil.isNotBlank(toUser)){
messageDTO.setToUser(toUser);
sendMail(messageDTO);
}
@ -593,11 +442,10 @@ public class EmailServiceManager {
/**
* 获取邮件主题
*
* @param message
* @return
*/
public String getMailSubject(@NotNull Message message, Integer batchesCounter) throws MessagingException {
public String getMailSubject(@NotNull Message message,Integer batchesCounter) throws MessagingException {
String subject = "";
String status = EmailLogManager.STATUS_SUCCESS;
try {
@ -607,61 +455,34 @@ public class EmailServiceManager {
} catch (MessagingException e) {
status = EmailLogManager.STATUS_ERROR;
throw e;
} finally {
EmailLogEvent event = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETIDHEADER);
EmailLogManager.getInstance().offer(Thread.currentThread().getId(), event);
}finally {
EmailLogEvent event = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.GETIDHEADER);
EmailLogManager.getInstance().offer(Thread.currentThread().getId(),event);
}
return subject;
}
public String getMessagesID(Message message, Integer batchesCounter) throws MessagingException {
String messageId = null;
String status = EmailLogManager.STATUS_SUCCESS;
try {
if (null == message.getHeader("Message-ID")) {
String subject = message.getSubject().replace(" ", StringConstant.UNDER_LINE);
Date date = message.getReceivedDate() == null ? message.getSentDate() : message.getReceivedDate();
String receivedStr = DateUtil.format(date, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
messageId = subject + StringConstant.UNDER_LINE + receivedStr;
} else {
messageId = ((MimeMessage) message).getMessageID();
}
} catch (MessagingException e) {
status = EmailLogManager.STATUS_ERROR;
log.error(e.getMessage());
throw e;
}finally {
EmailLogEvent event = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETIDHEADER);
EmailLogManager.getInstance().offer(Thread.currentThread().getId(), event);
}
return messageId;
}
/**
* 获取邮件内容
*
* @param part
* @return
* @throws MessagingException
* @throws IOException
*/
public void getMailContent(@NotNull Part part, StringBuilder content) throws MessagingException, IOException {
if (part.isMimeType(MailContentType.PLAIN.getContentType())) {
if(part.isMimeType(MailContentType.PLAIN.getContentType())){
content.append(part.getContent());
} else if (part.isMimeType("multipart/*")) {
}else if(part.isMimeType("multipart/*")){
Multipart multipart = (Multipart) part.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
for(int i=0;i<multipart.getCount();i++) {
final Part bodyPart = multipart.getBodyPart(i);
getMailContent(bodyPart, content);
getMailContent(bodyPart,content);
}
}
}
/**
* 保存邮件附件
*
* @param part
* @throws MessagingException
* @throws IOException
@ -669,27 +490,27 @@ public class EmailServiceManager {
public List<String> saveAttachment(@NotNull Part part) throws MessagingException, IOException {
List<String> filePathList = Lists.newArrayList();
Multipart multipart = (Multipart) part.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
for(int i=0;i<multipart.getCount();i++){
final BodyPart bodyPart = multipart.getBodyPart(i);
if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
if(Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
try{
final String fileName = MimeUtility.decodeText(bodyPart.getFileName());
bis = new BufferedInputStream(bodyPart.getInputStream());
File file = new File(this.temporaryStoragePath + File.separator + fileName);
File file = new File(this.temporaryStoragePath+File.separator+fileName);
bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] buf = new byte[4096];
int len;
while (-1 != (len = bis.read(buf, 0, buf.length))) {
bos.write(buf, 0, buf.length);
while(-1 != (len = bis.read(buf,0,buf.length))){
bos.write(buf,0,buf.length);
}
filePathList.add(file.getAbsolutePath());
} finally {
if (null != bis) {
}finally {
if(null != bis){
bis.close();
}
if (null != bos) {
if(null != bos){
bos.flush();
bos.close();
}
@ -706,231 +527,133 @@ public class EmailServiceManager {
* 新格式为发件人_主题_年月日_时分秒毫秒_receive_年月日_时分秒毫秒_计数0-10000
* 当计数大于10000后从0开始服务重启后也从0开始
*/
public File downloadEmailToEmlDir(@NotNull Message message, Integer emailCounter, Integer batchesCounter) throws MessagingException {
public File downloadEmailToEmlDir(@NotNull Message message,Integer emailCounter,Integer batchesCounter) throws MessagingException {
synchronized (downloadEmlLocal) {
String subject = "";
File emlFile = null;
String status = EmailLogManager.STATUS_SUCCESS;
Date receivedDate = null;
//InputStream inputStream = null;
//BufferedOutputStream outputStream = null;
InputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
//获取发件人
final String address = ((InternetAddress) message.getFrom()[0]).getAddress();
final String from = address.substring(0, address.indexOf(StringConstant.AT));
final String from = address.substring(0,address.indexOf(StringConstant.AT));
//获取主题
subject = MimeUtility.decodeText(message.getSubject());
if (subject.indexOf(StringConstant.SLASH) != -1) {
subject = StringUtils.replace(subject, StringConstant.SLASH, "");
if(subject.indexOf(StringConstant.SLASH) != -1){
subject = StringUtils.replace(subject,StringConstant.SLASH,"");
}
if (subject.indexOf(StringConstant.COLON) != -1) {
subject = StringUtils.replace(subject, StringConstant.COLON, "");
if(subject.indexOf(StringConstant.COLON) != -1){
subject = StringUtils.replace(subject,StringConstant.COLON,"");
}
receivedDate = message.getReceivedDate() == null ? message.getSentDate() : message.getReceivedDate();
receivedDate = message.getReceivedDate();
StringBuilder fileName = new StringBuilder();
fileName.append(from);
fileName.append(StringConstant.UNDER_LINE);
fileName.append(subject);
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(new Date(), "YYMMdd"));
fileName.append(DateUtils.formatDate(new Date(),"YYMMdd"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(new Date(), "HHmmssSSS"));
fileName.append(DateUtils.formatDate(new Date(),"HHmmssSSS"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append("receive");
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(receivedDate, "YYMMdd"));
fileName.append(DateUtils.formatDate(receivedDate,"YYMMdd"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(receivedDate, "HHmmssSSS"));
fileName.append(DateUtils.formatDate(receivedDate,"HHmmssSSS"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append(emailCounter);
fileName.append(SAVE_EML_SUFFIX);
final String rootPath = spectrumPathProperties.getRootPath();
final String emlPath = spectrumPathProperties.getEmlPath();
emlFile = new File(rootPath + emlPath + File.separator + fileName);
emlFile = new File(rootPath+emlPath+File.separator+fileName);
// outputStream = new FileOutputStream(emlFile);
// message.writeTo(outputStream);
int bufferSize = 1024 * 1024; // 1M
try (InputStream inputStream = message.getInputStream();
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(emlFile),bufferSize)) {
byte[] buffer = new byte[1024*1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush(); // 显式刷新
} catch (IOException e) {
FileUtils.copyInputStreamToFile(message.getInputStream(), emlFile);
}
if (emlFile.length() <= 0) {
FileUtils.copyInputStreamToFile(message.getInputStream(), emlFile);
inputStream = message.getInputStream();
outputStream = new BufferedOutputStream(new FileOutputStream(emlFile), bufferSize);
// 从邮件的输入流读取内容并写入到本地文件
byte[] buffer = new byte[bufferSize];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (MessagingException | IOException e) {
// 下载邮件失败 抛出自定义邮件下载异常
status = EmailLogManager.STATUS_ERROR;
String errorMsg = StrUtil.format("The email download failed, the subject of the email is {}, the reason is {}.", subject, e.getMessage());
log.error(errorMsg);
throw new DownloadEmailException(errorMsg);
} catch (Exception e) {
log.error("", e);
throw new RuntimeException(e);
} finally {
EmailLogEvent event = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETIDEML, subject, DateUtils.formatDate(receivedDate, "yyyy-MM-dd HH:mm:ss:SSS"),
(Objects.isNull(emlFile) ? " " : emlFile.getAbsolutePath()));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(), event);
}catch (Exception e) {
log.error("",e);
}finally {
EmailLogEvent event = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.GETIDEML,subject,DateUtils.formatDate(receivedDate,"yyyy-MM-dd HH:mm:ss:SSS"),
(Objects.isNull(emlFile)?" ":emlFile.getAbsolutePath()));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(),event);
try {
if (Objects.nonNull(inputStream)) {
inputStream.close();
}
if (Objects.nonNull(outputStream)) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return emlFile;
}
}
/*public File downloadEmailToEmlDir(@NotNull Message message, Integer emailCounter, Integer batchesCounter) throws MessagingException, IOException {
AtomicReference<FileOutputStream> outputStream = new AtomicReference<>();
CompletableFuture<File> future = CompletableFuture.supplyAsync(() -> {
try {
lock.lock(); // 获取锁
// 执行需要获取锁才能进行的操作
// return executeWithLock(message, emailCounter, batchesCounter);
File file = executeWithLock(message, emailCounter, batchesCounter);
outputStream.set(new FileOutputStream(file));
a(outputStream,message);
return null;
} catch (MessagingException e) {
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
// 如果成功拿到锁 释放锁
lock.unlock();
}
});
try {
return future.get(5, TimeUnit.SECONDS);
// return future.get(5, TimeUnit.SECONDS);// 等待任务执行超过5秒则抛出TimeoutException
} catch (InterruptedException | ExecutionException | TimeoutException e) {
future.cancel(true); // 取消任务执行
if (ObjectUtil.isNotNull(outputStream) && ObjectUtil.isNotNull(outputStream.get()))
outputStream.get().close();
log.error("下载 eml 执行超时", e);
throw new RuntimeException("下载 eml 执行超时");
}
}*/
public File executeWithLock(Message message, Integer emailCounter, Integer batchesCounter) throws MessagingException {
String subject = "";
File emlFile = null;
String status = EmailLogManager.STATUS_SUCCESS;
Date receivedDate = null;
try {
// 获取锁 设置超时
//获取发件人
final String address = ((InternetAddress) message.getFrom()[0]).getAddress();
final String from = address.substring(0, address.indexOf(StringConstant.AT));
//获取主题
subject = MimeUtility.decodeText(message.getSubject());
if (subject.contains(StringConstant.SLASH)) {
subject = StringUtils.replace(subject, StringConstant.SLASH, "");
}
if (subject.contains(StringConstant.COLON)) {
subject = StringUtils.replace(subject, StringConstant.COLON, "");
}
receivedDate = message.getReceivedDate() == null ? message.getSentDate() : message.getReceivedDate();
StringBuilder fileName = new StringBuilder();
fileName.append(from);
fileName.append(StringConstant.UNDER_LINE);
fileName.append(subject);
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(new Date(), "YYMMdd"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(new Date(), "HHmmssSSS"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append("receive");
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(receivedDate, "YYMMdd"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append(DateUtils.formatDate(receivedDate, "HHmmssSSS"));
fileName.append(StringConstant.UNDER_LINE);
fileName.append(emailCounter);
fileName.append(SAVE_EML_SUFFIX);
final String rootPath = spectrumPathProperties.getRootPath();
final String emlPath = spectrumPathProperties.getEmlPath();
emlFile = new File(rootPath + emlPath + File.separator + fileName);
// Thread.sleep(6000l);
// try(FileOutputStream outputStream = new FileOutputStream(emlFile)) {
// message.writeTo(outputStream);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
} catch (MessagingException | IOException e) {
// 下载邮件失败 抛出自定义邮件下载异常
status = EmailLogManager.STATUS_ERROR;
String errorMsg = StrUtil.format("The email download failed, the subject of the email is {}, the reason is {}.", subject, e.getMessage());
log.error(errorMsg);
throw new DownloadEmailException(errorMsg);
} catch (Exception e) {
log.error("", e);
} finally {
EmailLogEvent event = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.GETIDEML, subject, DateUtils.formatDate(receivedDate, "yyyy-MM-dd HH:mm:ss:SSS"),
(Objects.isNull(emlFile) ? " " : emlFile.getAbsolutePath()));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(), event);
}
return emlFile;
}
public void a(AtomicReference<FileOutputStream> outputStream, Message message) throws MessagingException, IOException {
message.writeTo(outputStream.get());
}
/**
* 删除邮件
*
* @param message
* @throws MessagingException
*/
public void removeMail(@NotNull Message message, Integer batchesCounter) {
public void removeMail(@NotNull Message message,Integer batchesCounter){
String status = EmailLogManager.STATUS_SUCCESS;
String subject = "";
Date receivedDate = null;
try {
subject = MimeUtility.decodeText(message.getSubject());
receivedDate = message.getReceivedDate() == null ? message.getSentDate() : message.getReceivedDate();
message.setFlag(Flags.Flag.DELETED, true);
// log.info("EmailServiceManager: Remove Email:{},receiveTime:{}",message.getSubject(), DateUtils.formatDate(message.getReceivedDate(),"yyyy-MM-dd HH:mm:ss"));
receivedDate = message.getReceivedDate();
message.setFlag(Flags.Flag.DELETED,true);
// log.info("EmailServiceManager: Remove Email:{},receiveTime:{}",message.getSubject(), DateUtils.formatDate(message.getReceivedDate(),"yyyy-MM-dd HH:mm:ss"));
} catch (MessagingException | UnsupportedEncodingException e) {
status = EmailLogManager.STATUS_ERROR;
log.error("Email deletion failed, the subject of the email is :{}, the reason is :", subject, e);
log.error("Email deletion failed, the subject of the email is :{}, the reason is :{}.",subject,e.getMessage());
e.printStackTrace();
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
EmailLogEvent removeEvent = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.DELETEID, subject, DateUtils.formatDate(receivedDate, "yyyy-MM-dd HH:mm:ss:SSS"));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(), removeEvent);
}finally {
EmailLogEvent removeEvent = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.DELETEID,subject,DateUtils.formatDate(receivedDate,"yyyy-MM-dd HH:mm:ss:SSS"));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(),removeEvent);
//这里删除和彻底删除一起写入日志java和C++处理有差异java是在连接关闭时彻底删除的
EmailLogEvent expungeEvent = new EmailLogEvent(batchesCounter, Thread.currentThread().getId(), EmailLogManager.GS_TYPE_GET, status, EmailLogManager.EXPUNGE, subject, DateUtils.formatDate(receivedDate, "yyyy-MM-dd HH:mm:ss:SSS"));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(), expungeEvent);
EmailLogEvent expungeEvent = new EmailLogEvent(batchesCounter,Thread.currentThread().getId(),EmailLogManager.GS_TYPE_GET,status,EmailLogManager.EXPUNGE,subject,DateUtils.formatDate(receivedDate,"yyyy-MM-dd HH:mm:ss:SSS"));
EmailLogManager.getInstance().offer(Thread.currentThread().getId(),expungeEvent);
}
}
/**
* 关闭邮件服务连接资源
*/
public void close(List<String> messageIds) {
public void close(List<String> messageIds){
try {
if (null != folder) {
if ("imap".equalsIgnoreCase(protocol)) {
folder.expunge();
}
if(null != folder){
folder.expunge();
folder.close();
}
if (null != store) {
if(null != store){
store.close();
}
log.info("{}: EmailServiceManage资源关闭完成.", Thread.currentThread().getName());
for (String messageId : messageIds) {
String key = RedisConstant.EMAIL_MSG_ID + StringConstant.COLON + messageId;
redisUtil.del(key);
}
// for(String messageId : messageIds){
// String key = RedisConstant.EMAIL_MSG_ID+StringConstant.COLON+messageId;
// redisUtil.del(key);
// }
} catch (MessagingException e) {
log.error("Email closure failed, email address is: {}, reason is: {}", email.getUsername(), e);
log.error("Email closure failed, email address is: {}, reason is: {}",email.getUsername(),e.getMessage());
e.printStackTrace();
}
}
@ -938,20 +661,18 @@ public class EmailServiceManager {
/**
* 校验邮件
* 若此次获取的邮件是上次删除失败的邮件直接删除
*
* @param message
*/
public boolean check(Message message, String messageId) {
public boolean check(Message message,String messageId){
boolean exist = false;
try {
String key = RedisConstant.EMAIL_MSG_ID + StringConstant.COLON + messageId;
int numberKey = redisUtil.get(key) != null ? (int) redisUtil.get(key) : 0;
// exist = redisUtil.hasKey(key);
if (numberKey >= taskProperties.getForceDeletedNumber()) {
String key = RedisConstant.EMAIL_MSG_ID+StringConstant.COLON+messageId;
int numberKey = redisUtil.get(key) != null? (int) redisUtil.get(key):0;
// exist = redisUtil.hasKey(key);
if(numberKey >= taskProperties.getForceDeletedNumber()){
exist = true;
Date dateUtils = message.getReceivedDate() == null ? message.getSentDate() : message.getReceivedDate();
log.info("Check: Remove Email:{},receiveTime:{}", message.getSubject(), DateUtils.formatDate(dateUtils, "yyyy-MM-dd HH:mm:ss"));
message.setFlag(Flags.Flag.DELETED, true);
log.info("Check: Remove Email:{},receiveTime:{}",message.getSubject(), DateUtils.formatDate(message.getReceivedDate(),"yyyy-MM-dd HH:mm:ss"));
message.setFlag(Flags.Flag.DELETED,true);
redisUtil.del(key);
}
return exist;

View File

@ -1,48 +0,0 @@
package org.jeecg.common.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MybatisTypeHandler extends BaseTypeHandler<Boolean> {
/**
* 功能描述: <br>
* <>
* @param: [ps, i, parameter, jdbcType]
* i:Jdbc预编译时设置参数的索引值
* parameter:要插入的参数值 true 或者false
* jdbcType:要插入JDBC的类型
* 里面的业务逻辑要根据实际开发场景来写 我这里就写的简单一点比较好理解一下
* @return:
* @author: wlt
* @date: 2022/3/22 21:25
**/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {
if (parameter){
ps.setInt(i,1);
}else ps.setInt(i,0);
}
@Override
public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {
int man = rs.getInt(columnName);
return man == 1 ? true : false;
}
@Override
public Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int man = rs.getInt(columnIndex);
return man == 1 ? true : false;
}
@Override
public Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int man = cs.getInt(columnIndex);
return man == 1 ? true : false;
}
}

View File

@ -1,14 +1,13 @@
package org.jeecg.common.util;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class DataTool {
private int counter = 1;
private final Map<String, Object> data = new LinkedHashMap<>();
private final Map<String, Object> data = new HashMap<>();
public DataTool put(Object value) {
data.put(String.format("p%d", counter), value);

View File

@ -206,29 +206,6 @@ public class DateUtils extends PropertyEditorSupport {
return sformat.format(nowDate);
}
/**
* 时间字符串格式转换
* @param date 时间字符串
* @param sourceFormat 字符串原有格式
* @param targetFormat 需要转换成的格式
* @return 字符串
*/
public static String dateformat(String date,String sourceFormat,String targetFormat)
{
SimpleDateFormat sformat = new SimpleDateFormat(sourceFormat);
Date nowDate = null;
try {
nowDate = sformat.parse(date);
sformat=new SimpleDateFormat(targetFormat);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sformat.format(nowDate);
}
/**
* 日期转换为字符串
*

View File

@ -55,15 +55,6 @@ public class NumUtil {
return result;
}
public static String keep6ScienceStr(Double value){
if (ObjectUtil.isNull(value))
return null;
String result = NumberUtil.decimalFormat("0.######E00", value);
if (!StrUtil.contains(result, "E-"))
return StrUtil.replace(result, "E", "E+");
return result;
}
public static Double keep(Double value, int scale){
if (ObjectUtil.isNull(value))
return null;

View File

@ -1,264 +0,0 @@
package org.jeecg.common.util;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Slf4j
public class RadionuclideUtil {
// 存储所有分类的核素数据分类名称核素列表
private static final Map<String, List<String>> radionuclideData = new HashMap<>();
// 反向映射核素到分类的映射用于快速查询
private static final Map<String, String> nuclideToSection = new HashMap<>();
// 初始化标志
private static boolean initialized = false;
private static Integer dayValue;
/**
* 初始化方法从XML文件加载数据
*
* @param xmlFilePath XML文件路径
* @throws Exception 加载过程中发生的异常
*/
public static synchronized void initialize(String xmlFilePath)
throws ParserConfigurationException, SAXException, IOException {
File xmlFile = new File(xmlFilePath);
if (!xmlFile.exists()) {
throw new FileNotFoundException("XML file not found: " + xmlFilePath);
}
if (!xmlFile.isFile()) {
throw new IOException("Path is not a file: " + xmlFilePath);
}
initializeInternal(xmlFile);
}
/**
* 重载初始化方法支持从输入流加载数据
*
* @param xmlInputStream XML输入流
* @throws Exception 加载过程中发生的异常
*/
public static synchronized void initialize(InputStream xmlInputStream)
throws ParserConfigurationException, SAXException, IOException {
if (xmlInputStream == null) {
throw new IllegalArgumentException("Input stream cannot be null");
}
initializeInternal(xmlInputStream);
}
/**
* 内部初始化方法实际执行XML解析逻辑
*/
private static void initializeInternal(Object source)
throws ParserConfigurationException, SAXException, IOException {
if (initialized) {
return;
}
radionuclideData.clear();
nuclideToSection.clear();
dayValue = null;
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc;
if (source instanceof File) {
doc = dBuilder.parse((File) source);
} else if (source instanceof InputStream) {
doc = dBuilder.parse((InputStream) source);
} else {
throw new IllegalArgumentException("Unsupported source type");
}
doc.getDocumentElement().normalize();
NodeList sectionList = doc.getElementsByTagName("section");
for (int i = 0; i < sectionList.getLength(); i++) {
Node sectionNode = sectionList.item(i);
if (sectionNode.getNodeType() == Node.ELEMENT_NODE) {
Element sectionElement = (Element) sectionNode;
String sectionName = sectionElement.getAttribute("name");
if (sectionName == null || sectionName.trim().isEmpty()) {
log.error("Skipping section with empty name attribute");
continue;
}
if (radionuclideData.containsKey(sectionName)) {
log.error("Duplicate section name found: " + sectionName + ", skipping");
continue;
}
if ("Days".equals(sectionName)) {
// 只读取第一个value元素的值
NodeList valueList = sectionElement.getElementsByTagName("value");
if (valueList.getLength() > 0) {
Node valueNode = valueList.item(0);
if (valueNode.getNodeType() == Node.ELEMENT_NODE) {
try {
dayValue = Integer.parseInt(valueNode.getTextContent().trim());
} catch (NumberFormatException e) {
System.err.println("Invalid days format: " + valueNode.getTextContent());
}
}
} else {
System.err.println("Section 'Days' has no 'value' element");
}
} else {
Set<String> nuclideSet = new HashSet<>();
NodeList nuclideList = sectionElement.getElementsByTagName("nuclide");
for (int j = 0; j < nuclideList.getLength(); j++) {
Node nuclideNode = nuclideList.item(j);
if (nuclideNode.getNodeType() == Node.ELEMENT_NODE) {
String nuclideValue = nuclideNode.getTextContent().trim();
if (!nuclideValue.isEmpty()) {
if (!nuclideSet.add(nuclideValue)) {
System.out.println("Duplicate nuclide found in section " + sectionName + ": " + nuclideValue);
}
}
}
}
List<String> nuclides = new ArrayList<>(nuclideSet);
radionuclideData.put(sectionName, Collections.unmodifiableList(nuclides));
// 构建核素到分类的反向映射
for (String nuclide : nuclides) {
if (nuclideToSection.containsKey(nuclide)) {
System.out.println("Nuclide " + nuclide + " exists in multiple sections: " +
nuclideToSection.get(nuclide) + " and " + sectionName);
} else {
nuclideToSection.put(nuclide, sectionName);
}
}
}
}
}
initialized = true;
}
/**
* 获取天数值只返回一个值
*
* @return 天数如果未设置则返回null
*/
public static Integer getDayValue() {
checkInitialized();
return dayValue;
}
/**
* 获取指定分类的所有核素
*
* @param sectionName 分类名称
* @return 核素列表不可修改如果分类不存在则返回空列表
* @throws IllegalStateException 如果未初始化
*/
public static List<String> getNuclidesBySection(String sectionName) {
checkInitialized();
return radionuclideData.getOrDefault(sectionName, Collections.emptyList());
}
/**
* 获取所有分类名称
*
* @return 分类名称列表不可修改
* @throws IllegalStateException 如果未初始化
*/
public static List<String> getAllSections() {
checkInitialized();
return Collections.unmodifiableList(new ArrayList<>(radionuclideData.keySet()));
}
/**
* 获取所有核素不区分分类
*
* @return 所有核素的列表不可修改
* @throws IllegalStateException 如果未初始化
*/
public static List<String> getAllNuclides() {
checkInitialized();
// 汇总所有分类的核素并去重
Set<String> allNuclideSet = new HashSet<>();
for (List<String> nuclides : radionuclideData.values()) {
allNuclideSet.addAll(nuclides);
}
return Collections.unmodifiableList(new ArrayList<>(allNuclideSet));
}
/**
* 根据核素名获取其所属的分类
*
* @param nuclide 核素名称
* @return 核素所属的分类名称如果核素不存在则返回null
* @throws IllegalStateException 如果未初始化
*/
public static String getSectionByNuclide(String nuclide) {
checkInitialized();
if (nuclide == null || nuclide.trim().isEmpty()) {
return null;
}
return nuclideToSection.get(nuclide.trim());
}
/**
* 检查是否已初始化
*
* @throws IllegalStateException 如果未初始化
*/
private static void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("RadionuclideManager 尚未初始化,请先调用 initialize() 方法");
}
}
public static void main(String[] args) {
try {
// 程序启动时初始化
RadionuclideUtil.initialize("F:\\Work_MDC\\AnalysisSystemForRadionuclide\\jeecg-boot-base-core\\src\\main\\resources\\ctbt_radionuclides.xml");
// 测试新添加的方法
String testNuclide1 = "K40";
System.out.println(testNuclide1 + " 所属类型: " + RadionuclideUtil.getSectionByNuclide(testNuclide1));
String testNuclide2 = "Cs137";
System.out.println(testNuclide2 + " 所属类型: " + RadionuclideUtil.getSectionByNuclide(testNuclide2));
String testNuclide3 = "Unknown";
System.out.println(testNuclide3 + " 所属类型: " + RadionuclideUtil.getSectionByNuclide(testNuclide3));
// 原有功能测试
System.out.println("\n所有分类: " + RadionuclideUtil.getAllSections());
String ctbtSection = "CTBTRADS";
System.out.println("\n" + ctbtSection + " 包含的核素数量: " +
RadionuclideUtil.getNuclidesBySection(ctbtSection).size());
String naturalSection = "NATURALRADS";
System.out.println(naturalSection + " 包含的核素: " +
RadionuclideUtil.getNuclidesBySection(naturalSection));
System.out.println("所有核素总数: " + RadionuclideUtil.getAllNuclides().size());
System.out.println("天数值: " + RadionuclideUtil.getDayValue());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}

View File

@ -198,15 +198,6 @@ public class RedisStreamUtil {
// 向Redis Stream中推送消息
return putRecord(record);
}
/**
* 添加消息到 Stream (对象格式)
*/
public <T> RecordId addMessage(String streamKey, T message) {
ObjectRecord<String, T> record = StreamRecords.newRecord()
.in(streamKey)
.ofObject(message);
return stringRedisTemplate.opsForStream().add(record);
}
public void setSilence(Map<String, Long> silenceMap){
// 返回批处理的执行结果

View File

@ -61,42 +61,13 @@ public class TemplateUtil {
for (String key : keys) {
contents.add(ReUtil.getGroup1(StrUtil.format(pattern, key), templateContent));
}
String join = StrUtil.SPACE+ "#"+StrUtil.SPACE;
templateContent = CollUtil.join(contents, join);
templateContent = CollUtil.join(contents, "#");
String content = FreemarkerParseFactory
.parseTemplateContent(templateContent, data, true);
messageDTO.setContent(content);
String title = FreemarkerParseFactory.parseTemplateContent(templateName,data);
messageDTO.setTitle(title);
return messageDTO;
}
public static MessageDTO parse1(String code, Map<String, Object> data,Map<String,Object> stationData){
MessageDTO messageDTO = new MessageDTO();
SysMessageTemplate template = templateService.getOne(code);
// 如果没有消息模板
if(ObjectUtil.isNull(template))
return messageDTO;
String templateName = template.getTemplateName();
String templateContent = template.getTemplateContent();
if (MapUtil.isEmpty(data))
return messageDTO;
Set<String> keys = data.keySet();
String pattern = "\\<([^<>]*{}[^<>]*)\\>";
List<String> contents = new ArrayList<>();
for (String key : keys) {
contents.add(ReUtil.getGroup1(StrUtil.format(pattern, key), templateContent));
}
String replaceStr=System.lineSeparator();
String join = replaceStr+ "#";
templateContent = CollUtil.join(contents, join);
String content = FreemarkerParseFactory
.parseTemplateContent(templateContent, data, true);
messageDTO.setContent(content.replace(":",":"+replaceStr+StrUtil.SPACE));
String title = FreemarkerParseFactory.parseTemplateContent(templateName,stationData);
messageDTO.setTitle(title);
return messageDTO;
}
public static MessageDTO parse(String title, String code, Map<String, Object> data) {
MessageDTO messageDTO = new MessageDTO();
SysMessageTemplate template = templateService.getOne(code);
@ -131,8 +102,7 @@ public class TemplateUtil {
for (String key : keys) {
contents.add(ReUtil.getGroup1(StrUtil.format(pattern, key), templateContent));
}
String join = StrUtil.SPACE + "#" + StrUtil.SPACE;
templateContent = CollUtil.join(contents, join);
templateContent = CollUtil.join(contents, "#");
String content = FreemarkerParseFactory
.parseTemplateContent(templateContent, data, true);
messageDTO.setContent(content);

View File

@ -164,8 +164,8 @@ public class TokenUtils {
String secret = CommonConstant.TEMP_TOKEN_SECRET;
// 模拟登录生成Token
String token = JwtUtil.sign(username, secret);
// 设置Token缓存有效时间为 60
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token, 60);
// 设置Token缓存有效时间为 3 分钟
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token, 3 * 60);
return token;
}
}

View File

@ -52,7 +52,7 @@ public class ShiroConfig {
/**
* Filter Chain定义说明
* <p>
*
* 1一个URL可以配置多个Filter使用逗号分隔
* 2当设置多个过滤器时全部验证通过才视为通过
* 3部分过滤器可指定参数如permsroles
@ -65,12 +65,12 @@ public class ShiroConfig {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//支持yml方式配置拦截排除
if (jeecgBaseConfig != null && jeecgBaseConfig.getShiro() != null) {
if(jeecgBaseConfig!=null && jeecgBaseConfig.getShiro()!=null){
String shiroExcludeUrls = jeecgBaseConfig.getShiro().getExcludeUrls();
if (oConvertUtils.isNotEmpty(shiroExcludeUrls)) {
if(oConvertUtils.isNotEmpty(shiroExcludeUrls)){
String[] permissionUrl = shiroExcludeUrls.split(",");
for (String url : permissionUrl) {
filterChainDefinitionMap.put(url, "anon");
for(String url : permissionUrl){
filterChainDefinitionMap.put(url,"anon");
}
}
}
@ -119,14 +119,14 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/swagger**/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
//积木报表排除
filterChainDefinitionMap.put("/jmreport/**", "anon");
filterChainDefinitionMap.put("/**/*.js.map", "anon");
filterChainDefinitionMap.put("/**/*.css.map", "anon");
//大屏模板例子
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
@ -140,14 +140,6 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
//邮件监控 排除
filterChainDefinitionMap.put("/sysEmailLog/getDashboardDailyStats", "anon");
filterChainDefinitionMap.put("/sysEmailLog/getRecentEmailDatas", "anon");
filterChainDefinitionMap.put("/sysEmail/sourceList", "anon");
//台站有效率
filterChainDefinitionMap.put("/stationOperation/getDataProvisionEfficiency", "anon");
//性能监控安全隐患泄露TOEKNdurid连接池也有
//filterChainDefinitionMap.put("/actuator/**", "anon");
//测试模块排除
@ -157,7 +149,7 @@ public class ShiroConfig {
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
//如果cloudServer为空 则说明是单体 需要加载跨域配置微服务跨域切换
Object cloudServer = env.getProperty(CommonConstant.CLOUD_SERVER_KEY);
filterMap.put("jwt", new JwtFilter(cloudServer == null));
filterMap.put("jwt", new JwtFilter(cloudServer==null));
shiroFilterFactoryBean.setFilters(filterMap);
// <!-- 过滤链定义从上向下顺序执行一般将/**放在最为下边
filterChainDefinitionMap.put("/**", "jwt");
@ -191,7 +183,6 @@ public class ShiroConfig {
/**
* 下面的代码是添加注解支持
*
* @return
*/
@Bean
@ -258,15 +249,15 @@ public class ShiroConfig {
redisManager.setPassword(lettuceConnectionFactory.getPassword());
}
manager = redisManager;
} else {
}else{
// redis集群支持优先使用集群配置
RedisClusterManager redisManager = new RedisClusterManager();
Set<HostAndPort> portSet = new HashSet<>();
lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost(), node.getPort())));
lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));
//update-begin--Author:scott Date:20210531 for修改集群模式下未设置redis密码的bug issues/I3QNIC
if (oConvertUtils.isNotEmpty(lettuceConnectionFactory.getPassword())) {
JedisCluster jedisCluster = new JedisCluster(portSet, 2000, 2000, 5,
lettuceConnectionFactory.getPassword(), new GenericObjectPoolConfig());
lettuceConnectionFactory.getPassword(), new GenericObjectPoolConfig());
redisManager.setPassword(lettuceConnectionFactory.getPassword());
redisManager.setJedisCluster(jedisCluster);
} else {

View File

@ -27,42 +27,4 @@ public class AlarmAnalysisRuleInfo implements Serializable {
private String contactGroup;
private String remark;
private String sample;
private String sampleType;
private Integer coefficient;
private List<String> colTime;
private List<String> acqTime;
private Double airFlow;
private Double decayTime;
private Double sampVol;
private Double ba140MDC;
private Double be7FWHM;
private List<String> xe133MDC;
private Double xeVol;
private Integer xe131mFlag;
private Integer xe133mFlag;
private Integer xe133Flag;
private Integer xe135Flag;
private Integer days;
private String identifyNuclides;
private List<String> identifyNuclidesChecked;
}

View File

@ -36,6 +36,4 @@ public class EmailDto implements Serializable {
private String username; // 邮箱用户名
private Integer isQiye; // 是否企业邮箱
private Integer emailServerType;
}

View File

@ -8,30 +8,25 @@ import org.jeecg.modules.base.enums.SourceType;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import java.util.Set;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Info implements Serializable {
public class Info implements Serializable{
// 台站id
private String stationId;
// 谱id
private String sampleId;
//分析ID号
public String IdAnalysis;
// 谱Name
private String sampleName;
// 采样时间
private LocalDateTime collectionDate;
//采集停止时间
private Date collectStop;
// 数据源类型(ARMDARR=1|ARMDRRR=2|IDCARR=3|IDCRRR=4)
private String datasource;
@ -45,7 +40,7 @@ public class Info implements Serializable {
private String analyst;
// 核素名称-浓度值
private Map<String, String> nuclides;
private Map<String,String> nuclides;
/* 以下属性不需要传值 */
private String ruleId;
@ -53,8 +48,4 @@ public class Info implements Serializable {
private String groupId;
private String conditions;
private Set<String> identifyNuclideSet;
private String sampleType;
}

View File

@ -1,11 +0,0 @@
package org.jeecg.modules.base.dto;
import lombok.Data;
@Data
public class SampNucl {
private String sampleId;
private String nuclideName;
}

View File

@ -1,6 +1,5 @@
package org.jeecg.modules.base.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
@ -15,9 +14,4 @@ public class SourceDto implements Serializable {
private String hostId;
private String cpuUsedItemId;
/**
* 是否启用邮箱0-不启用1-启用
*/
private Integer enabled;
}

View File

@ -1,17 +0,0 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class GardsNuclThresholds implements Serializable {
private String id;
private String sampleId;
private String stationId;
private Double thresholdValue;
private String nuclideName;
private LocalDateTime calculationTime;
}

View File

@ -1,18 +0,0 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class SampleGardsThreshold implements Serializable {
/**
* 样品id
*/
private Integer sampleId;
private String sampleType;
private Integer stationId;
private String Grading;
private String GradingStatus;
}

View File

@ -1,23 +0,0 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
@Data
public class SampleIdentifiedNuclides {
private Integer sampleId;
/**
* 分析ID号
*/
private Integer idAnalysis;
/**
* 核素名称
*/
private String nuclideName;
/**
* 活度浓度
*/
private String concentration;
}

View File

@ -1,15 +0,0 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
import java.util.Date;
@Data
public class StatisticsResult {
private String nuclideName;
private Double median; // 中位数
private Double percentile25; // 25分位数
private Double percentile75; // 75分位数
private int dataCount; // 有效数据量
private Date collectStop;
}

View File

@ -1,17 +0,0 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Data
public class ThresholdMetric implements Serializable {
private Integer stationId;//站点ID
private Integer sampleId;//样品ID
private String nuclideName;//核素名称
private String concentration;//浓度值
private Date collectStop;//采集停止时间
private List<Double> concentrations;// 浓度列表
}

View File

@ -1,13 +0,0 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class ThresholdMetricResults {
private Integer stationId;//站点ID
private String nuclideName;//核素名称
private Date collectStop;//采集停止时间
private List<Double> concentrations;// 浓度列表
}

View File

@ -1,6 +1,5 @@
package org.jeecg.modules.base.entity.configuration;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -23,7 +22,7 @@ public class GardsDetectors implements Serializable {
/**
* 探测器id
*/
@TableId(type = IdType.INPUT)
@TableId(value = "DETECTOR_ID")
private Integer detectorId;
/**

View File

@ -1,6 +1,5 @@
package org.jeecg.modules.base.entity.configuration;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -20,57 +19,57 @@ import java.util.Date;
public class GardsStations implements Serializable {
/**
* 台站id
* 台站id
*/
@TableId(type = IdType.INPUT)
@TableId("STATION_ID")
@NotNull(message = "不能为空", groups = {InsertGroup.class, UpdateGroup.class})
private Integer stationId;
/**
* 台站编码
* 台站编码
*/
@TableField(value = "STATION_CODE")
@NotBlank(message = "不能为空", groups = {InsertGroup.class, UpdateGroup.class})
private String stationCode;
/**
* 城市编码
* 城市编码
*/
@TableField(value = "COUNTRY_CODE")
private String countryCode;
/**
* 台站类型
* 台站类型
*/
@TableField(value = "TYPE")
private String type;
/**
* 经度
* 经度
*/
@TableField(value = "LON")
private Double lon;
/**
* 纬度
* 纬度
*/
@TableField(value = "LAT")
private Double lat;
/**
* 海拔
* 海拔
*/
@TableField(value = "ELEVATION")
private Double elevation;
/**
* 描述
* 描述
*/
@TableField(value = "DESCRIPTION")
private String description;
/**
* 开始运行日期
* 开始运行日期
*/
@TableField(value = "DATE_BEGIN")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ -86,13 +85,13 @@ public class GardsStations implements Serializable {
private Date dateEnd;
/**
* 运行状态
* 运行状态
*/
@TableField(value = "STATUS")
private String status;
/**
* 操作时间
* 操作时间
*/
@TableField(value = "MODDATE")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ -101,9 +100,5 @@ public class GardsStations implements Serializable {
@TableField(value = "CATEGORY")
private Integer category;
/**
* 有效率计算类型
*/
@TableField(value = "EFFIC_CALCUL_TYPE")
private String efficCalculType;
}

View File

@ -22,7 +22,7 @@ public class GardsAlertData implements Serializable {
@TableField(value = "STATION_CODE")
private String stationCode;
@TableId(type = IdType.AUTO)
@TableId(value = "ALERT_ID",type = IdType.AUTO)
private Integer alertId;
@TableField(value = "TIME")

View File

@ -1,8 +1,6 @@
package org.jeecg.modules.base.entity.original;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@ -21,7 +19,7 @@ public class GardsGPSData implements Serializable {
@TableField(value = "STATION_CODE")
private String stationCode;
@TableId(type = IdType.AUTO)
@TableField(value = "GPS_ID")
private Integer gpsId;
@TableField(value = "LON")

View File

@ -31,7 +31,7 @@ public class GardsMetData implements Serializable {
/**
* 气象数据id
*/
@TableId(type = IdType.AUTO)
@TableId(value = "MET_ID",type = IdType.AUTO)
private Integer metId;
/**

View File

@ -27,7 +27,7 @@ public class GardsSampleData implements Serializable {
* 样品id
*/
@TableId(type = IdType.AUTO)
@TableId(value = "SAMPLE_ID",type = IdType.AUTO)
private Integer sampleId;
/**

View File

@ -31,7 +31,7 @@ public class GardsSohData implements Serializable {
/**
* 报警ID号
*/
@TableId(type = IdType.AUTO)
@TableId(value = "SOH_ID",type = IdType.AUTO)
@Excel(name = "SID",orderNum = "5")
private Integer sohId;

View File

@ -1,12 +1,21 @@
package org.jeecg.modules.base.entity.postgre;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.jeecg.common.system.base.entity.JeecgEntity;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.scheduling.annotation.Scheduled;
@Data
@TableName("alarm_analysis_rule")
@ -14,9 +23,6 @@ import java.math.BigDecimal;
@Accessors(chain = true)
public class AlarmAnalysisRule extends JeecgEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/** 规则名称 */
private String name;
@ -41,55 +47,6 @@ public class AlarmAnalysisRule extends JeecgEntity {
/** 联系人组id */
private String contactGroup;
private String sample;
private String sampleType;
private BigDecimal coefficient;
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String colTime;
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String acqTime;
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Double airFlow;
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Double decayTime;
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Double sampVol;
@TableField(value = "ba140_mdc", updateStrategy = FieldStrategy.IGNORED)
private Double ba140MDC;
@TableField(value = "be7_fwhm", updateStrategy = FieldStrategy.IGNORED)
private Double be7FWHM;
@TableField(value = "xe133_mdc", updateStrategy = FieldStrategy.IGNORED)
private String xe133MDC;
@TableField(value = "xe_vol", updateStrategy = FieldStrategy.IGNORED)
private Double xeVol;
@TableField(value = "xe131m_flag", updateStrategy = FieldStrategy.IGNORED)
private Integer xe131mFlag;
@TableField(value = "xe133m_flag", updateStrategy = FieldStrategy.IGNORED)
private Integer xe133mFlag;
@TableField(value = "xe133_flag", updateStrategy = FieldStrategy.IGNORED)
private Integer xe133Flag;
@TableField(value = "xe135_flag", updateStrategy = FieldStrategy.IGNORED)
private Integer xe135Flag;
private Integer days;
@TableField(value = "identify_nuclides", updateStrategy = FieldStrategy.IGNORED)
private String identifyNuclides;
/** 备注 */
private String remark;
}

View File

@ -94,6 +94,4 @@ public class SysEmail implements Serializable {
*/
@TableField(value = "update_by")
private String updateBy;
@TableField(value = "email_server_type")
private Integer emailServerType;
}

View File

@ -21,7 +21,7 @@ public class GardsAnalyses implements Serializable {
/**
* 分析ID号
*/
@TableId(value = "idanalysis",type = IdType.AUTO)
@TableId(value = "IDANALYSIS",type = IdType.AUTO)
private Integer idAnalysis;
/**
* 样品id

View File

@ -41,7 +41,7 @@ public class GardsCalibration implements Serializable {
/**
* 拟合方程ID号统一定义
*/
@TableField(value = "\"FUNCTION\"")
@TableField(value = "FUNCTION")
private Integer function;
/**
* 拟合方程描述

View File

@ -1,47 +0,0 @@
package org.jeecg.modules.base.entity.rnauto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("RNAUTO.GARDS_SAMPLE_GRADING")
public class GardsSampleGrading {
/**
* 样品ID (对应 SAMPLE_ID)
*/
@TableField(value = "SAMPLE_ID")
private Long sampleId;
/**
* 台站ID (对应 STATION_ID)
*/
@TableField(value = "STATION_ID")
private Long stationId;
/**
* 分级结果 (对应 GRADING)
* 存储分级结果 "1", "2", "3"
*/
@TableField(value = "GRADING")
private String grading;
/**
* 分级状态 (对应 GRADING_STATUS)
* 0: 未处理
* 1: 已处理
* -1: 处理失败
*/
@TableField(value = "GRADING_STATUS")
private Integer gradingStatus;
/**
* 样品类型 (对应 SAMPLE_TYPE)
* P: 颗粒样品
* B: 惰性气体样品
*/
@TableField(value = "SAMPLE_TYPE")
private String sampleType;
}

View File

@ -1,31 +0,0 @@
package org.jeecg.modules.base.entity.rnauto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@TableName("RNAUTO.GARDS_THRESHOLD_RESULT")
public class GardsThresholdResult {
@TableId(type = IdType.ASSIGN_ID)
private String id;
@TableField(value = "IDANALYSIS")
private Integer idAnalysis;
private String stationId;
@TableField("NUCLIDENAME")
private String nuclideName;
private String category;
private Double thresholdValue;
private Double median;
private Double percentile25;
private Double percentile75;
@TableField(exist = false)
private Date calculationTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date collectStop;
}

View File

@ -1,33 +0,0 @@
package org.jeecg.modules.base.entity.rnauto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@TableName("RNAUTO.GARDS_THRESHOLD_RESULT_HIS")
public class GardsThresholdResultHistory {
@TableId(type = IdType.ASSIGN_ID)
private String id;
@TableField(value = "IDANALYSIS")
private Integer idAnalysis;
private String stationId;
@TableField("NUCLIDENAME")
private String nuclideName;
private Double thresholdValue;
private Double median;
private Double percentile25;
private Double percentile75;
@TableField(exist = false)
private Date calculationTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date collectStop;
private String category;
}

View File

@ -1,52 +0,0 @@
package org.jeecg.modules.base.entity.rnauto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.modules.base.enums.TransportTaskCloseStatusEnum;
import org.jeecg.modules.base.enums.TransportTaskStatusEnum;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("RNAUTO.GARDS_TRANSPORT_STATUS")
public class GardsTransportStatus implements Serializable {
/**
* 样品id
*/
@TableId(value = "SAMPLE_ID", type = IdType.INPUT)
private Integer sampleId;
/**
* 输运模拟状态-1执行失败0未开始1运行中2已完成3缺少气象数据
*/
@TableField(value = "TRANSPORT_STATUS")
private Integer transportStatus;
/**
* 输运模拟说明
*/
@TableField(value = "DESCRIPTION")
private String description;
/**
* 关闭状态(0-未关闭1-关闭)
*/
@TableField(value = "CLOSE_STATUS")
private Integer closeStatus;
/**
* 更新时间
*/
@TableField(value = "MODDATE")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date moddate;
}

View File

@ -1,8 +1,6 @@
package org.jeecg.modules.base.entity.rnman;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@ -22,7 +20,7 @@ public class GardsAnalyses implements Serializable {
/**
* 分析ID号
*/
@TableId(value = "idanalysis",type = IdType.AUTO)
@TableField(value = "IDANALYSIS")
private Integer idAnalysis;
/**
* 样品id

View File

@ -1,43 +0,0 @@
package org.jeecg.modules.base.entity.rnman;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("RNAMN.GARDS_SAMPLE_GRADING")
public class GardsSampleGrading {
/**
* 样品ID (对应 SAMPLE_ID)
*/
private Long sampleId;
/**
* 台站ID (对应 STATION_ID)
*/
private Long stationId;
/**
* 分级结果 (对应 GRADING)
* 存储分级结果 "1", "2", "3"
*/
private String grading;
/**
* 分级状态 (对应 GRADING_STATUS)
* 0: 未处理
* 1: 已处理
* -1: 处理失败
*/
private Integer gradingStatus;
/**
* 样品类型 (对应 SAMPLE_TYPE)
* P: 颗粒样品
* B: 惰性气体样品
*/
private String sampleType;
}

View File

@ -1,30 +0,0 @@
package org.jeecg.modules.base.entity.rnman;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@TableName("RNMAN.GARDS_THRESHOLD_RESULT")
public class GardsThresholdResult {
@TableId(type = IdType.ASSIGN_ID)
private String id;
@TableField(value = "IDANALYSIS")
private Integer idAnalysis;
private String stationId;
@TableField("NUCLIDENAME")
private String nuclideName;
private Double thresholdValue;
private Double median;
private Double percentile25;
private Double percentile75;
@TableField(exist = false)
private Date calculationTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date collectStop;
}

View File

@ -1,28 +0,0 @@
package org.jeecg.modules.base.entity.rnman;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("RNMAN.GARDS_THRESHOLD_RESULT_HIS")
public class GardsThresholdResultHistory {
@TableId(type = IdType.ASSIGN_ID)
private String id;
@TableField(value = "IDANALYSIS")
private Integer idAnalysis;
private String stationId;
@TableField("NUCLIDENAME")
private String nuclideName;
private Double thresholdValue;
private Double median;
private Double percentile25;
private Double percentile75;
@TableField(exist = false)
private Date calculationTime;
}

View File

@ -7,22 +7,7 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public enum Condition {
/**
* 首次发现核素
*/
FIRST_FOUND("1"),
/**
* 核素conc超过平均值
*/
ABOVE_AVERAGE("2"),
/**
* 同时识别到多个核素
*/
MEANWHILE("3"),
/**
* 识别到某个核素
*/
IDENTIFY_NUCLIDES("4");
FIRST_FOUND("1"), ABOVE_AVERAGE("2"), MEANWHILE("3");
private final String value;

View File

@ -7,13 +7,12 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public enum Item {
EMAIL_CONN("1", "Email Connection Status"),
TABLESPACE_USAGE("2", "TableSpace Usage"),
EMAIL_UNPROCESSED("3", "Email Unprocessed");
EMAIL_CONN("1", "Connection Status"),
TABLESPACE_USAGE("2", "TableSpace Usage");
private final String value;
private String value;
private final String name;
private String name;
public static Item of(String value){
for (Item item : Item.values()) {

View File

@ -2,7 +2,6 @@ package org.jeecg.modules.base.enums;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
/**
* 资源类型
@ -10,19 +9,22 @@ import lombok.Getter;
* @author nieziyan
* @date 2023-06-30
*/
@Getter
public enum SourceType {
EMAIL("Email"),
DATABASE("Database"),
SERVER("Server");
private final String type;
private String type;
SourceType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public static SourceType typeOf(String type){
for (SourceType sourceType : SourceType.values()) {
if (StrUtil.equals(sourceType.getType(),type))

View File

@ -1,13 +0,0 @@
package org.jeecg.modules.base.enums;
public enum StationDetailType {
SAUNA,
SAUNA2,
SPALAX,
SPALAX_PLC,
Car,
LAB,
CINDER,
RASA,
ARIX_2
}

View File

@ -1,23 +0,0 @@
package org.jeecg.modules.base.enums;
public enum TransportTaskCloseStatusEnum {
/**
* 未关闭
*/
NOT_CLOSED(0),
/**
* 已关闭
*/
CLOSE(1);
private Integer value;
TransportTaskCloseStatusEnum(Integer value) {
this.value = value;
}
public Integer getValue(){
return this.value;
}
}

View File

@ -1,35 +0,0 @@
package org.jeecg.modules.base.enums;
public enum TransportTaskStatusEnum {
/**
* 执行失败
*/
FAILURE(-1),
/**
* 未开始
*/
NOT_STARTED(0),
/**
* 执行中
*/
IN_OPERATION(1),
/**
* 已完成
*/
COMPLETED(2),
/**
* 缺少气象数据
*/
LACK_MET_DATA(3);
private Integer value;
TransportTaskStatusEnum(Integer value) {
this.value = value;
}
public Integer getValue(){
return this.value;
}
}

View File

@ -1,12 +0,0 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.base.entity.rnauto.GardsThresholdResultHistory;
@Mapper
public interface RnAutoThresholdResultHisMapper extends BaseMapper<GardsThresholdResultHistory> {
}

View File

@ -1,9 +0,0 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.base.entity.rnman.GardsThresholdResultHistory;
@Mapper
public interface RnManThresholdResultHisMapper extends BaseMapper<GardsThresholdResultHistory> {
}

View File

@ -1,21 +0,0 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.base.entity.ThresholdMetric;
import org.jeecg.modules.base.entity.rnauto.GardsThresholdResult;
import java.util.List;
@Mapper
public interface ThresholdRnAutoResultMapper extends BaseMapper<GardsThresholdResult> {
List<GardsThresholdResult> selectByStationId(String stationId);
void deleteByStationId(String stationId);
int batchInsert(List<GardsThresholdResult> subList);
List<ThresholdMetric> selectByRnAutoStationIds(@Param("stationIds") List<String> stationIds, @Param("oneYearAgo") String oneYearAgo);
}

View File

@ -1,21 +0,0 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.base.entity.ThresholdMetric;
import org.jeecg.modules.base.entity.rnman.GardsThresholdResult;
import java.util.List;
@Mapper
public interface ThresholdRnManResultMapper extends BaseMapper<GardsThresholdResult> {
int batchInsertRnMan(@Param("list") List<GardsThresholdResult> results);
void deleteByStationId(String stationId);
List<GardsThresholdResult> selectByStationId(String stationId);
List<ThresholdMetric> selectByRnManStationIds(@Param("stationIds") List<String> stationIds, @Param("oneYearAgo") String oneYearAgo);
}

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.base.mapper.ThresholdRnAutoResultMapper">
<insert id="batchInsert" parameterType="java.util.List">
INSERT ALL
<foreach collection="list" item="result" separator="">
INTO RNAUTO.GARDS_THRESHOLD_RESULT (id, station_id, nuclidename, threshold_value, median, percentile25,
percentile75)
VALUES (#{result.id}, #{result.stationId}, #{result.nuclideName}, #{result.thresholdValue},#{result.median},
#{result.percentile25}, #{result.percentile75})
</foreach>
SELECT 1 FROM DUAL
</insert>
<delete id="deleteByStationId" parameterType="String">
DELETE
FROM RNAUTO.GARDS_THRESHOLD_RESULT
WHERE STATION_ID = #{stationId}
</delete>
<select id="selectByStationId" resultType="org.jeecg.modules.base.entity.rnauto.GardsThresholdResult">
SELECT t.ID,
t.STATION_ID,
t.NUCLIDENAME,
t.THRESHOLD_VALUE,
t.MEDIAN,
t.PERCENTILE25,
t.PERCENTILE75,
t.CALCULATION_TIME
FROM RNAUTO.GARDS_THRESHOLD_RESULT t
WHERE t.station_id = #{stationId}
ORDER BY t.CALCULATION_TIME DESC
</select>
<select id="selectByRnAutoStationIds01" resultType="org.jeecg.modules.base.entity.ThresholdMetric">
SELECT
a.STATION_ID as STATION_ID,
a.SAMPLE_ID as SAMPLE_ID,
CASE
WHEN a.SAMPLE_TYPE = 'P' THEN
b.NUCLIDENAME
WHEN a.SAMPLE_TYPE = 'B' THEN
c.NUCLIDE_NAME
END AS NUCLIDE_NAME,
CASE
WHEN a.SAMPLE_TYPE = 'P' THEN
TO_NUMBER(REGEXP_REPLACE(b.CONCENTRATION, '[^0-9.Ee-]', ''))
WHEN a.SAMPLE_TYPE = 'B' THEN
c.CONC
END AS CONCENTRATION
FROM ORIGINAL.GARDS_SAMPLE_DATA a
JOIN RNAUTO.GARDS_NUCL_IDED b ON a.SAMPLE_ID = b.SAMPLE_ID
AND a.SAMPLE_TYPE = 'P'
LEFT JOIN RNAUTO.GARDS_XE_RESULTS c ON a.SAMPLE_TYPE = 'B'
AND a.SAMPLE_ID = c.SAMPLE_ID
<where>
a.STATION_ID IN
<foreach item="stationId" collection="stationIds" open="(" close=")" separator=",">
'${stationId}'
</foreach>
AND a.TRANSMIT_DTG > TO_DATE(#{oneYearAgo}, 'yyyy-mm-dd hh24:mi:ss')
</where>
</select>
<select id="selectByRnAutoStationIds" resultType="org.jeecg.modules.base.entity.ThresholdMetric">
SELECT a.STATION_ID as stationId,
a.SAMPLE_ID as sampleId,
b.NUCLIDENAME as nuclideName,
a.COLLECT_STOP as collectStop,
b.CONCENTRATION as concentration
FROM ORIGINAL.GARDS_SAMPLE_DATA a
JOIN RNAUTO.GARDS_NUCL_IDED b
ON a.SAMPLE_ID = b.SAMPLE_ID
<where>
a.SAMPLE_TYPE IN ('P','G')
<if test="stationIds != null and stationIds.size() > 0">
AND a.STATION_ID IN
<foreach item="stationId" collection="stationIds" open="(" close=")" separator=",">
#{stationId}
</foreach>
</if>
<if test="oneYearAgo != null">
AND a.COLLECT_STOP &gt; TO_DATE(#{oneYearAgo}, 'yyyy-mm-dd hh24:mi:ss')
</if>
</where>
UNION ALL
SELECT a.STATION_ID as stationId,
a.SAMPLE_ID as sampleId,
c.NUCLIDE_NAME as nuclideName,
a.COLLECT_STOP as collectStop,
TO_CHAR(c.CONC, 'FM9999999990.999999') as concentration
FROM ORIGINAL.GARDS_SAMPLE_DATA a
JOIN RNAUTO.GARDS_XE_RESULTS c
ON a.SAMPLE_ID = c.SAMPLE_ID
<where>
a.SAMPLE_TYPE = 'B'
<if test="stationIds != null and stationIds.size() > 0">
AND a.STATION_ID IN
<foreach item="stationId" collection="stationIds" open="(" close=")" separator=",">
#{stationId}
</foreach>
</if>
<if test="oneYearAgo != null">
AND a.COLLECT_STOP &gt; TO_DATE(#{oneYearAgo}, 'yyyy-mm-dd hh24:mi:ss')
</if>
</where>
</select>
</mapper>

View File

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.mapper.threshold.ThresholdResultMapper">
<insert id="batchInsertRnMan" parameterType="java.util.List">
INSERT INTO RN_MAN_TABLE (
RNMAN.GARDS_THRESHOLD_RESULT (id, station_id, nuclidename, threshold_value, median, percentile25, percentile75)
) VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.id},
#{item.station_id},
#{item.nuclidename},
#{item.median},
#{item.percentile25},
#{item.percentile75}
)
</foreach>
</insert>
<delete id="deleteByStationId" parameterType="String">
DELETE
FROM RNMAN.GARDS_THRESHOLD_RESULT
WHERE STATION_ID = #{stationId}
</delete>
<select id="selectByStationId" resultType="org.jeecg.modules.base.entity.rnman.GardsThresholdResult">
SELECT t.ID,
t.STATION_ID,
t.NUCLIDENAME,
t.THRESHOLD_VALUE,
t.MEDIAN,
t.PERCENTILE25,
t.PERCENTILE75,
t.CALCULATION_TIME
FROM RNMAN.GARDS_THRESHOLD_RESULT t
WHERE t.station_id = #{stationId}
ORDER BY t.CALCULATION_TIME DESC
</select>
<select id="selectByRnManStationIds" resultType="org.jeecg.modules.base.entity.ThresholdMetric">
SELECT
a.STATION_ID as STATION_ID,
a.SAMPLE_ID as SAMPLE_ID,
CASE
WHEN a.SAMPLE_TYPE = 'P' THEN
b.NUCLIDENAME
WHEN a.SAMPLE_TYPE = 'B' THEN
c.NUCLIDE_NAME
END AS NUCLIDE_NAME,
CASE
WHEN a.SAMPLE_TYPE = 'P' THEN
TO_NUMBER(REGEXP_REPLACE(b.CONCENTRATION, '[^0-9.Ee-]', ''))
WHEN a.SAMPLE_TYPE = 'B' THEN
c.CONC
END AS CONCENTRATION
FROM ORIGINAL.GARDS_SAMPLE_DATA a
JOIN RNMAN.GARDS_NUCL_IDED b ON a.SAMPLE_ID = b.SAMPLE_ID
AND a.SAMPLE_TYPE = 'P'
LEFT JOIN RNMAN.GARDS_XE_RESULTS c ON a.SAMPLE_TYPE = 'B'
AND a.SAMPLE_ID = c.SAMPLE_ID
<where>
a.STATION_ID IN
<foreach item="stationId" collection="stationIds" open="(" close=")" separator=",">
'${stationId}'
</foreach>
AND a.TRANSMIT_DTG > TO_DATE(#{oneYearAgo}, 'yyyy-mm-dd hh24:mi:ss')
</where>
</select>
</mapper>

View File

@ -1,33 +0,0 @@
package org.jeecg.modules.base.service;
import org.jeecg.modules.base.dto.Info;
import java.util.List;
public interface ISampleGradingService {
/**
* RNMAN 处理P类型样品分级
*/
Integer processTypeP(Info sample, List<org.jeecg.modules.base.entity.rnman.GardsThresholdResult> thresholds);
/**
* RNAUTO 处理P类型样品分级
*/
Integer processAutoTypeP(Info sample, List<org.jeecg.modules.base.entity.rnauto.GardsThresholdResult> thresholds);
/**
* RNAMN 处理B类型样品分级
*/
Integer processTypeB(Info sample, List<org.jeecg.modules.base.entity.rnman.GardsThresholdResult> thresholds);
/**
* RNAUTO 处理B类型样品分级
* @param sample
* @param thresholds
* @return
*/
Integer processAutoTypeB(Info sample, List<org.jeecg.modules.base.entity.rnauto.GardsThresholdResult> thresholds);
}

View File

@ -1,21 +0,0 @@
package org.jeecg.modules.base.service;
import org.jeecg.modules.base.dto.Info;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
public interface IThresholdCalculationService {
@Transactional(rollbackFor = Exception.class)
Map<String, Double> calculateSingleStationThreshold(Info info);
Map<String, Double> getStationThresholds(String stationId);
@Transactional(rollbackFor = Exception.class)
void processBatchCalculation(List<Info> infos);
}

View File

@ -1,5 +0,0 @@
package org.jeecg.modules.base.service;
public interface IThresholdResultHisService {
}

View File

@ -1,13 +0,0 @@
package org.jeecg.modules.base.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.base.entity.rnauto.GardsThresholdResultHistory;
import org.jeecg.modules.base.mapper.RnAutoThresholdResultHisMapper;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@DS("ora")
public class RnAutoThresholdHisServiceImpl extends ThresholdResultHisBaseService<RnAutoThresholdResultHisMapper,GardsThresholdResultHistory>{
}

View File

@ -1,227 +0,0 @@
package org.jeecg.modules.base.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.NumberFormatUtil;
import org.jeecg.common.util.RadionuclideUtil;
import org.jeecg.modules.base.dto.Info;
import org.jeecg.modules.base.entity.StatisticsResult;
import org.jeecg.modules.base.entity.ThresholdMetric;
import org.jeecg.modules.base.entity.rnauto.GardsThresholdResult;
import org.jeecg.modules.base.entity.rnauto.GardsThresholdResultHistory;
import org.jeecg.modules.base.mapper.ThresholdRnAutoResultMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* RNAUTO类型阈值计算实现类
*/
@Service
@Slf4j
@DS("ora")
public class RnAutoThresholdServiceImpl extends ThresholdCalculationBaseService<ThresholdRnAutoResultMapper, GardsThresholdResult> {
@Autowired
private RnAutoThresholdHisServiceImpl thresholdHisService;
/**
* 获取当前服务处理的数据类型
*
* @return RNAUTO数据类型
*/
@Override
protected String getCurrentDataType() {
return DATA_TYPE_RNAUTO;
}
/**
* 保存RNAUTO类型阈值计算结果
*
* @param info 台站ID
* @param thresholds 阈值映射
* @param statistics 统计结果映射
*/
@Override
protected void saveThresholdResults(Info info, Map<String, Double> thresholds,
Map<String, StatisticsResult> statistics) {
String stationId = info.getStationId();
validateSaveParams(stationId, thresholds, statistics);
log.debug("开始保存RNAUTO阈值结果台站{},核素{}个", stationId, thresholds.size());
List<GardsThresholdResult> results = buildThresholdResultList(info, thresholds, statistics);
if (!CollectionUtils.isEmpty(results)) {
// 先删除旧数据
this.baseMapper.deleteByStationId(stationId);
// 批量保存新数据
boolean saveSuccess = this.saveBatch(results);
// saveBatch(results, DEFAULT_BATCH_SIZE);
if (saveSuccess) {
List<GardsThresholdResultHistory> resultHisList = results.stream()
.map(item -> {
GardsThresholdResultHistory his = new GardsThresholdResultHistory();
BeanUtils.copyProperties(item, his);
return his;
})
.collect(Collectors.toList());
thresholdHisService.saveBatch(resultHisList);
stationThresholdCache.put(stationId, new HashMap<>(thresholds));
log.info("RNAUTO阈值结果保存成功台站{},核素{}个", stationId, results.size());
} else {
log.error("RNAUTO阈值结果保存失败台站{}", stationId);
}
} else {
log.warn("RNAUTO阈值结果为空台站{}", stationId);
}
}
/**
* 从数据库查询RNAUTO类型的台站阈值
*
* @param stationId 台站ID
* @return 核素-阈值映射
*/
@Override
protected Map<String, Double> queryThresholdsFromDb(String stationId) {
if (!StringUtils.hasText(stationId)) {
log.warn("查询台站阈值失败台站ID为空");
return new HashMap<>();
}
try {
List<GardsThresholdResult> results = this.baseMapper.selectByStationId(stationId);
Map<String, Double> thresholds = new HashMap<>(results.size());
results.forEach(result -> {
if (result != null && StringUtils.hasText(result.getNuclideName())) {
thresholds.put(result.getNuclideName(), result.getThresholdValue());
}
});
return thresholds;
} catch (Exception e) {
log.error("查询RNAUTO类型台站{}阈值失败", stationId, e);
return new HashMap<>();
}
}
/**
* 构建ThresholdResult列表
*/
private List<GardsThresholdResult> buildThresholdResultList(Info info, Map<String, Double> thresholds,
Map<String, StatisticsResult> statistics) {
List<GardsThresholdResult> results = new ArrayList<>(thresholds.size());
thresholds.forEach((nuclideName, thresholdValue) -> {
StatisticsResult stats = statistics.get(nuclideName);
if (stats == null) {
log.warn("核素{}未找到对应的统计结果,跳过保存", nuclideName);
return;
}
Map<String, String> nulides = info.getNuclides();
String category = "A"; // 默认无效
if (Objects.nonNull(nulides)) {
String concStr = info.getNuclides().get(nuclideName);
if (StringUtils.hasText(concStr)) {
try {
double concValue = Double.parseDouble(NumberFormatUtil.numberFormat(concStr));
category = concValue < thresholdValue ? "B" : "C";
} catch (Exception ignored) {
// 解析失败保持 A
}
}
}
GardsThresholdResult result = new GardsThresholdResult();
result.setId(UUID.randomUUID().toString());
result.setStationId(info.getStationId());
result.setNuclideName(nuclideName);
result.setCategory(category);
result.setThresholdValue(thresholdValue);
result.setMedian(stats.getMedian());
result.setPercentile25(stats.getPercentile25());
result.setPercentile75(stats.getPercentile75());
result.setCollectStop(info.getCollectStop());
results.add(result);
});
return results;
}
/**
* 批量保存RNAUTO阈值结果
*/
public boolean saveBatch(List<GardsThresholdResult> list, int batchSize) {
if (CollectionUtils.isEmpty(list)) {
log.warn("批量保存RNAUTO结果列表为空直接返回成功");
return true;
}
if (batchSize <= 0) {
log.warn("批次大小{}无效,使用默认值{}", batchSize, DEFAULT_BATCH_SIZE);
batchSize = DEFAULT_BATCH_SIZE;
}
log.debug("批量保存RNAUTO结果总数{},批次大小{}", list.size(), batchSize);
int total = list.size();
int successCount = 0;
try {
// 循环处理批次
for (int i = 0; i < total; i += batchSize) {
int end = Math.min(i + batchSize, total);
List<GardsThresholdResult> subList = list.subList(i, end);
int insertCount = this.baseMapper.batchInsert(subList);
if (insertCount != subList.size()) {
log.error("批次{}保存失败:预期{}条,实际插入{}条",
(i / batchSize) + 1, subList.size(), insertCount);
return false;
}
successCount += insertCount;
}
return successCount == total;
} catch (Exception e) {
log.error("RNAUTO批量保存异常", e);
return false;
}
}
/*** 通过台站ID查询核素名称核素浓度用于计算核素阈值
*
* @param stationIds 台站ID列表
* @param startDate 开始时间
* @return List<ThresholdMetric> ThresholdMetric
*/
public List<ThresholdMetric> queryMetricsByDataType(List<String> stationIds, String startDate) {
try {
return this.baseMapper.selectByRnAutoStationIds(stationIds, startDate);
} catch (Exception e) {
log.error("查询核素度量数据失败:,台站{}", stationIds, e);
return Collections.emptyList();
}
}
public List<String> getAllNuclides() {
return RadionuclideUtil.getAllNuclides();
}
public Integer getDayValue() {
return RadionuclideUtil.getDayValue();
}
}

View File

@ -1,13 +0,0 @@
package org.jeecg.modules.base.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.base.entity.rnman.GardsThresholdResultHistory;
import org.jeecg.modules.base.mapper.RnManThresholdResultHisMapper;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@DS("ora")
public class RnManThresholdHisServiceImpl extends ThresholdResultHisBaseService<RnManThresholdResultHisMapper, GardsThresholdResultHistory> {
}

View File

@ -1,198 +0,0 @@
package org.jeecg.modules.base.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.RadionuclideUtil;
import org.jeecg.modules.base.dto.Info;
import org.jeecg.modules.base.entity.StatisticsResult;
import org.jeecg.modules.base.entity.ThresholdMetric;
import org.jeecg.modules.base.entity.rnman.GardsThresholdResult;
import org.jeecg.modules.base.entity.rnman.GardsThresholdResultHistory;
import org.jeecg.modules.base.mapper.ThresholdRnManResultMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* RNMAN类型阈值计算实现类
*/
@Slf4j
@Service
public class RnManThresholdServiceImpl extends ThresholdCalculationBaseService<ThresholdRnManResultMapper, GardsThresholdResult> {
@Autowired
private RnManThresholdHisServiceImpl thresholdHisService;
/**
* 获取当前服务处理的数据类型
*
* @return RNMAN数据类型
*/
@Override
protected String getCurrentDataType() {
return DATA_TYPE_RNMAN;
}
/**
* 保存RNMAN类型阈值计算结果
*
* @param stationId 台站ID
* @param thresholds 阈值映射
* @param statistics 统计结果映射
*/
protected void saveThresholdResults(Info info, Map<String, Double> thresholds,
Map<String, StatisticsResult> statistics) {
String stationId=info.getStationId();
validateSaveParams(stationId, thresholds, statistics);
log.debug("开始保存RNMAN阈值结果台站{},核素{}个", stationId, thresholds.size());
List<GardsThresholdResult> results = buildThresholdRnManResultList(info, thresholds, statistics);
if (!CollectionUtils.isEmpty(results)) {
// 先删除旧数据
this.baseMapper.deleteByStationId(stationId);
boolean saveSuccess = this.saveBatch(results);
if (saveSuccess) {
List<GardsThresholdResultHistory> resultHisList = results.stream()
.map(item -> {
GardsThresholdResultHistory his = new GardsThresholdResultHistory();
BeanUtils.copyProperties(item, his);
return his;
})
.collect(Collectors.toList());
thresholdHisService.saveBatch(resultHisList);
stationThresholdCache.put(stationId, new HashMap<>(thresholds));
log.info("RNMAN阈值结果保存成功台站{},核素{}个", stationId, results.size());
}
} else {
log.warn("RNMAN阈值结果为空台站{}", stationId);
}
}
/**
* 从数据库查询RNMAN类型的台站阈值
*
* @param stationId 台站ID
* @return 核素-阈值映射
*/
@Override
protected Map<String, Double> queryThresholdsFromDb(String stationId) {
if (!StringUtils.hasText(stationId)) {
log.warn("查询台站阈值失败台站ID为空");
return new HashMap<>();
}
try {
List<GardsThresholdResult> results = this.baseMapper.selectByStationId(stationId);
Map<String, Double> thresholds = new HashMap<>(results.size());
results.forEach(result -> {
if (result != null && StringUtils.hasText(result.getNuclideName())) {
thresholds.put(result.getNuclideName(), result.getThresholdValue());
}
});
return thresholds;
} catch (Exception e) {
log.error("查询RNMAN类型台站{}阈值失败", stationId, e);
return new HashMap<>();
}
}
/**
* 构建ThresholdRnManResult列表
*/
private List<GardsThresholdResult> buildThresholdRnManResultList(Info info, Map<String, Double> thresholds,
Map<String, StatisticsResult> statistics) {
List<GardsThresholdResult> results = new ArrayList<>(thresholds.size());
thresholds.forEach((nuclideName, thresholdValue) -> {
StatisticsResult stats = statistics.get(nuclideName);
if (stats == null) {
log.warn("核素{}未找到对应的统计结果,跳过保存", nuclideName);
return;
}
GardsThresholdResult result = new GardsThresholdResult();
result.setId(UUID.randomUUID().toString());
result.setStationId(info.getStationId());
result.setNuclideName(nuclideName);
result.setThresholdValue(thresholdValue);
result.setMedian(stats.getMedian());
result.setPercentile25(stats.getPercentile25());
result.setPercentile75(stats.getPercentile75());
result.setCollectStop(info.getCollectStop());
results.add(result);
});
return results;
}
/**
* 批量保存RNMAN阈值结果
*/
private void saveRnManBatch(List<GardsThresholdResult> list, int batchSize) {
if (CollectionUtils.isEmpty(list)) {
log.warn("批量保存RNMAN结果列表为空直接返回");
return;
}
if (batchSize <= 0) {
log.warn("批次大小{}无效,使用默认值{}", batchSize, DEFAULT_BATCH_SIZE);
batchSize = DEFAULT_BATCH_SIZE;
}
log.debug("批量保存RNMAN结果总数{},批次大小{}", list.size(), batchSize);
int total = list.size();
try {
// 循环处理批次
for (int i = 0; i < total; i += batchSize) {
int end = Math.min(i + batchSize, total);
List<GardsThresholdResult> subList = list.subList(i, end);
int insertCount = this.baseMapper.batchInsertRnMan(subList);
if (insertCount != subList.size()) {
log.error("批次{}保存失败:预期{}条,实际插入{}条",
(i / batchSize) + 1, subList.size(), insertCount);
throw new RuntimeException("RNMAN阈值结果批量保存失败");
}
}
} catch (Exception e) {
log.error("RNMAN批量保存异常", e);
throw new RuntimeException("RNMAN阈值结果批量保存异常", e);
}
}
/*** 通过台站ID分析ID查询核素名称核素浓度用于计算核素阈值
*
* @param stationIds 台站ID列表
* @param startDate 开始时间
* @return List<ThresholdMetric> ThresholdMetric
*/
public List<ThresholdMetric> queryMetricsByDataType(List<String> stationIds, String startDate) {
try {
return this.baseMapper.selectByRnManStationIds(stationIds, startDate);
} catch (Exception e) {
log.error("查询核素度量数据失败:,台站{}", stationIds, e);
return Collections.emptyList();
}
}
public List<String> getAllNuclides() {
return RadionuclideUtil.getAllNuclides();
}
public Integer getDayValue(){
return RadionuclideUtil.getDayValue();
}
}

View File

@ -1,232 +0,0 @@
package org.jeecg.modules.base.service.impl;
import org.jeecg.common.util.RadionuclideUtil;
import org.jeecg.modules.base.dto.Info;
import org.jeecg.modules.base.entity.GardsNuclThresholds;
import org.jeecg.modules.base.entity.rnauto.GardsThresholdResult;
import org.jeecg.modules.base.service.ISampleGradingService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/***
* 计算样品等级服务
*/
@Service
public class SampleGradingServiceImpl implements ISampleGradingService {
/***
* RNMAN 处理PG样品
* @param sample
* @param thresholds
* @return
*/
@Override
public Integer processTypeP(Info sample, List<org.jeecg.modules.base.entity.rnman.GardsThresholdResult> thresholds) {
int level = 0;
Map<String, String> nucls = sample.getNuclides();
List<Nuclide> nuclides = new ArrayList<>();
if (nucls.isEmpty()) {
return 0;
}
for (Map.Entry<String, String> nucl : nucls.entrySet()) {
String nuclideName = nucl.getKey();
double concentration = Double.parseDouble(nucl.getValue());
Double thresholdValue = thresholds.stream()
.filter(t -> nuclideName.equals(t.getNuclideName()))
.findFirst()
.map(org.jeecg.modules.base.entity.rnman.GardsThresholdResult::getThresholdValue)
.orElse(0.0);
boolean isNormal = isConcentrationNormal(concentration, thresholdValue.toString());
String nuclType = RadionuclideUtil.getSectionByNuclide(nuclideName);
nuclides.add(new Nuclide(nuclideName, concentration, NuclideType.valueOf(nuclType), isNormal));
}
level = analyzeSample(nuclides);
return level;
}
/***
* RNAUTO 处理PG样品
* @param sample 样品信息
* @param thresholds 阈值结果
* @return
*/
@Override
public Integer processAutoTypeP(Info sample, List<org.jeecg.modules.base.entity.rnauto.GardsThresholdResult> thresholds) {
int level = 0;
//样品识别到的核素
Map<String, String> nucls = sample.getNuclides();
if (nucls.isEmpty()) {
return 0;
}
List<Nuclide> nuclides = new ArrayList<>();
for (Map.Entry<String, String> nucl : nucls.entrySet()) {
String nuclideName = nucl.getKey();
double concentration = Double.parseDouble(nucl.getValue());
Double thresholdValue = thresholds.stream()
.filter(t -> nuclideName.equals(t.getNuclideName()))
.findFirst()
.map(GardsThresholdResult::getThresholdValue)
.orElse(0.0);
boolean isNormal = isConcentrationNormal(concentration, thresholdValue.toString());
//获取核素类型-从xml文件中获取
String nuclType = RadionuclideUtil.getSectionByNuclide(nuclideName);
if (nuclType == null || nuclType == "") {
continue;
}
nuclides.add(new Nuclide(nuclideName, concentration, NuclideType.valueOf(nuclType), isNormal));
}
level = analyzeSample(nuclides);
return level;
}
@Override
public Integer processTypeB(Info sample, List<org.jeecg.modules.base.entity.rnman.GardsThresholdResult> thresholds) {
int level = 0;
try {
Map<String, String> xeNucls = sample.getNuclides();
boolean hasBIsotope = false;
boolean hasAbnormalActivity = false;
for (Map.Entry<String, String> isotope : xeNucls.entrySet()) {
String nuclideName = isotope.getKey();
double concentration = Double.parseDouble(isotope.getValue());
Double thresholdValue = thresholds.stream()
.filter(t -> nuclideName.equals(t.getNuclideName()))
.findFirst()
.map(org.jeecg.modules.base.entity.rnman.GardsThresholdResult::getThresholdValue)
.orElse(0.0);
hasBIsotope = true;
if (!isConcentrationNormal(concentration, thresholdValue.toString())) {
hasAbnormalActivity = true;
break;
}
}
if (!hasBIsotope) {
level = 1;
} else if (!hasAbnormalActivity) {
level = 2;
} else {
level = 3;
}
} catch (Exception e) {
level = 0;
}
return level;
}
@Override
public Integer processAutoTypeB(Info sample, List<org.jeecg.modules.base.entity.rnauto.GardsThresholdResult> thresholds) {
int level = 0;
Map<String, String> xeNucls = sample.getNuclides();
boolean hasBIsotope = false;
boolean hasAbnormalActivity = false;
for (Map.Entry<String, String> isotope : xeNucls.entrySet()) {
String nuclideName = isotope.getKey();
double concentration = Double.parseDouble(isotope.getValue());
Double thresholdValue = thresholds.stream()
.filter(t -> nuclideName.equals(t.getNuclideName()))
.findFirst()
.map(GardsThresholdResult::getThresholdValue)
.orElse(0.0);
hasBIsotope = true;
if (!isConcentrationNormal(concentration, thresholdValue.toString())) {
hasAbnormalActivity = true;
break;
}
}
if (!hasBIsotope) {
level = 1;
} else if (!hasAbnormalActivity) {
level = 2;
} else {
level = 3;
}
return level;
}
public boolean isConcentrationNormal(Double currentReading, String normalThreshold) {
try {
// 科学计数法转换
double threshold = Double.parseDouble(normalThreshold);
// 比较逻辑包含容差处理
return currentReading <= threshold * (1 + 1e-10); // 添加微小容差
} catch (NumberFormatException e) {
// 异常处理
System.err.println("无效的数字格式: " + currentReading + "" + normalThreshold);
return false;
}
}
private GardsNuclThresholds createThreshold(Info sample, String nuclideName, Double thresholdValue) {
GardsNuclThresholds threshold = new GardsNuclThresholds();
threshold.setId(UUID.randomUUID().toString());
threshold.setSampleId(sample.getSampleId());
threshold.setStationId(sample.getStationId());
threshold.setNuclideName(nuclideName);
threshold.setThresholdValue(thresholdValue);
return threshold;
}
public enum NuclideType {NATURALRADS, CTBTRADS}
public Integer analyzeSample(List<Nuclide> nuclides) {
boolean hasCTBT = false;
boolean hasAbnormalCTBT = false;
int abnormalCTBTCount = 0;
for (Nuclide n : nuclides) {
if (n.type == NuclideType.CTBTRADS) {
hasCTBT = true;
if (!n.isNormal) {
hasAbnormalCTBT = true;
abnormalCTBTCount++;
}
}
}
if (!hasCTBT) {
return nuclides.stream().anyMatch(n -> !n.isNormal)
? 2
: 1;
} else if (!hasAbnormalCTBT) {
return 3;
} else {
return abnormalCTBTCount > 1
? 5
: 4;
}
}
public class Nuclide {
private final String name;
private final double concentration;
private final NuclideType type;
private final boolean isNormal;
public Nuclide(String name, double conc, NuclideType type, boolean isNormal) {
this.name = name;
this.concentration = conc;
this.type = type;
this.isNormal = isNormal;
}
}
}

View File

@ -1,632 +0,0 @@
package org.jeecg.modules.base.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.properties.ParameterProperties;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.NumUtil;
import org.jeecg.common.util.RadionuclideUtil;
import org.jeecg.modules.base.dto.Info;
import org.jeecg.modules.base.entity.StatisticsResult;
import org.jeecg.modules.base.entity.ThresholdMetric;
import org.jeecg.modules.base.entity.ThresholdMetricResults;
import org.jeecg.modules.base.service.IThresholdCalculationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Slf4j
@DS("ora")
public abstract class ThresholdCalculationBaseService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements IThresholdCalculationService {
// ------------------------------ 公共常量 ------------------------------
/**
* 默认批量保存大小
*/
protected static final int DEFAULT_BATCH_SIZE = 1000;
/**
* RNAUTO数据类型
*/
protected static final String DATA_TYPE_RNAUTO = "RNAUTO";
/**
* RNMAN数据类型
*/
protected static final String DATA_TYPE_RNMAN = "RNMAN";
/**
* 数据库精度配置总位数
*/
protected static final int DB_TOTAL_PRECISION = 19;
/**
* 数据库精度配置小数位数
*/
protected static final int DB_DECIMAL_PLACES = 10;
/**
* 数据库精度配置整数位数
*/
protected static final int DB_INTEGER_PLACES = DB_TOTAL_PRECISION - DB_DECIMAL_PLACES;
/**
* 数据库支持最大值
*/
protected static final BigDecimal DB_MAX_VALUE = new BigDecimal("999999999.9999999999");
/**
* 数据库支持最小值
*/
protected static final BigDecimal DB_MIN_VALUE = new BigDecimal("-999999999.9999999999");
@Autowired
private ParameterProperties parameterProperties;
// ------------------------------ 公共缓存 ------------------------------
/**
* 阈值缓存线程安全key=stationId, value=Map<nuclideName, threshold>
*/
protected final Map<String, Map<String, Double>> stationThresholdCache = new ConcurrentHashMap<>();
// ------------------------------ 抽象方法子类实现差异化逻辑 ------------------------------
/**
* 保存阈值计算结果子类实现具体保存逻辑
*
* @param info 台站ID
* @param thresholds 阈值映射
* @param statistics 统计结果映射
*/
protected abstract void saveThresholdResults(Info info, Map<String, Double> thresholds, Map<String, StatisticsResult> statistics);
/**
* 从数据库查询台站阈值子类实现具体查询逻辑
*
* @param stationId 台站ID
* @return 核素-阈值映射
*/
protected abstract Map<String, Double> queryThresholdsFromDb(String stationId);
/**
* 获取当前服务处理的数据类型RNAUTO/RNMAN
*
* @return 数据类型
*/
protected abstract String getCurrentDataType();
/***
* 获取全部的CTBT核素
*/
protected abstract List<String> getAllNuclides();
protected abstract Integer getDayValue();
// ------------------------------ 公共业务方法 ------------------------------
/**
* 计算单个台站的阈值公共逻辑
*
* @param info 台站ID
* @return 核素-阈值映射
*/
@Transactional(rollbackFor = Exception.class)
@Override
public Map<String, Double> calculateSingleStationThreshold(Info info) {
String stationId = info.getStationId();
// 1. 参数校验
validateCalculateParams(stationId);
log.info("开始计算单个台站阈值stationId={}", stationId);
// 2. 获取该台站的度量数据
List<String> stationIds = Collections.singletonList(stationId);
Map<String, Map<String, List<Double>>> metricsMap = getMetricsForStations(stationIds);
// List<ThresholdMetric> metricsMap = getThresholdMetric(stationIds);
// 3. 检查是否有数据getConcentrationsByStation(metricsMap, stationId);//
Map<String, List<Double>> metrics = metricsMap.get(stationId);
if (CollectionUtils.isEmpty(metrics)) {
log.warn("台站{}没有找到有效的度量数据", stationId);
return new HashMap<>();
}
// 4. 计算阈值和统计结果
Map<String, Double> thresholds = new HashMap<>();
Map<String, StatisticsResult> statistics = new HashMap<>();
calculateThresholdAndStats(metrics, thresholds, statistics);
// 5. 保存计算结果子类实现
saveThresholdResults(info, thresholds, statistics);
log.info("单个台站阈值计算完成stationId={}, 核素数量={}", stationId, thresholds.size());
return thresholds;
}
//根据台站ID筛选出核素对应的浓度
public Map<String, List<ThresholdMetric>> getConcentrationsByStation(List<ThresholdMetric> metrics, String stationId) {
return metrics.stream()
.filter(m -> Objects.equals(m.getStationId(), Integer.valueOf(stationId)))
.filter(m -> StringUtils.hasText(m.getNuclideName()) && StringUtils.hasText(m.getConcentration()))
.collect(Collectors.groupingBy(
ThresholdMetric::getNuclideName, // 按核素名称分组
Collectors.mapping(
m -> m, // 转换浓度为 double
Collectors.toList()
)
));
}
/**
* 查询单个台站的阈值优先缓存缓存未命中查库
*
* @param stationId 台站ID
* @return 核素-阈值映射
*/
@Override
public Map<String, Double> getStationThresholds(String stationId) {
if (!StringUtils.hasText(stationId)) {
log.warn("查询台站阈值失败台站ID为空");
return new HashMap<>();
}
// 1. 优先从缓存获取
if (stationThresholdCache.containsKey(stationId)) {
log.debug("从缓存获取台站{}阈值:核素数量={}", stationId, stationThresholdCache.get(stationId).size());
return new HashMap<>(stationThresholdCache.get(stationId));
}
// 2. 缓存未命中从数据库查询子类实现
try {
Map<String, Double> thresholds = queryThresholdsFromDb(stationId);
// 存入缓存
stationThresholdCache.put(stationId, new HashMap<>(thresholds));
log.debug("从数据库查询台站{}阈值:核素数量={}", stationId, thresholds.size());
return thresholds;
} catch (Exception e) {
log.error("查询台站{}阈值失败", stationId, e);
return new HashMap<>();
}
}
/**
* 批量计算所有台站阈值公共逻辑
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void processBatchCalculation(List<Info> infos) {
List<String> stationIds = infos.stream().map(info -> info.getStationId()).collect(Collectors.toList());
String currentDataType = getCurrentDataType();
log.info("开始批量阈值计算dataType={}", currentDataType);
try {
// 1. 获取所有待处理台站
if (CollectionUtils.isEmpty(stationIds)) {
log.info("没有需要处理的台站dataType={}", currentDataType);
return;
}
log.info("发现 {} 条待处理台站dataType={}", stationIds.size(), currentDataType);
// 2. 批量获取度量数据
Map<String, Map<String, List<Double>>> metricsMap = getMetricsForStations(stationIds);
// 3. 处理每个台站
infos.forEach(info -> {
Map<String, List<Double>> metrics = metricsMap.get(info.getStationId());
if (metrics != null && !metrics.isEmpty()) {
processSingleStation(info, metrics);
} else {
log.warn("台站 {} {} 没有度量数据,跳过处理", info.getStationId(), currentDataType);
}
});
log.info("批量阈值计算完成dataType={}", currentDataType);
} catch (Exception e) {
log.error("{} 批量阈值计算发生错误", currentDataType, e);
throw new RuntimeException(currentDataType + " 批量阈值计算失败", e);
}
}
// ------------------------------ 公共工具方法 ------------------------------
/**
* 验证计算参数合法性
*
* @param stationId 台站ID
*/
protected void validateCalculateParams(String stationId) {
if (!StringUtils.hasText(stationId)) {
throw new IllegalArgumentException("台站ID不能为空");
}
}
/**
* 验证保存参数合法性
*
* @param stationId 台站ID
* @param thresholds 阈值映射
* @param statistics 统计结果映射
*/
protected void validateSaveParams(String stationId, Map<String, Double> thresholds, Map<String, StatisticsResult> statistics) {
if (!StringUtils.hasText(stationId)) {
throw new IllegalArgumentException("台站ID不能为空");
}
if (thresholds == null) {
throw new IllegalArgumentException("阈值映射不能为空");
}
if (statistics == null) {
throw new IllegalArgumentException("统计结果映射不能为空");
}
}
/**
* 按台站ID和数据类型批量获取核素度量数据
*
* @param stationIds 台站ID列表
* @return 分层映射key=stationId, value=Map<nuclideName, List<concentration>>
*/
protected Map<String, Map<String, List<Double>>> getMetricsForStations(List<String> stationIds) {
// 参数校验
if (CollectionUtils.isEmpty(stationIds)) {
log.warn("获取核素度量数据失败台站ID列表为空");
throw new IllegalArgumentException("台站ID列表不可为空");
}
//查询核素浓度
// 计算查询时间范围近1年
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, -getDayValue());
String startDate = DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd HH:mm:ss");
log.debug("查询核素度量数据:台站{}个,时间范围{}至今",
stationIds.size(), startDate);
// 按数据类型查询度量数据
List<ThresholdMetric> queryMetrics = queryMetricsByDataType(stationIds, startDate);
List<ThresholdMetric> metrics = new ArrayList<>();
// 查询结果的快速索引 (StationId -> (NuclideName -> ThresholdMetric))
Map<Integer, Map<String, List<ThresholdMetric>>> metricIndex = queryMetrics.stream()
.collect(Collectors.groupingBy(
ThresholdMetric::getStationId,
Collectors.groupingBy(ThresholdMetric::getNuclideName)
));
// 2. 预先处理所有核素名称
List<String> allNuclides = RadionuclideUtil.getAllNuclides();
// 3. 遍历所有组合
for (String stationId : stationIds) {
Integer station = Integer.parseInt(stationId);
// 获取当前站点对应的核素Map若不存在则返回空Map
Map<String, List<ThresholdMetric>> nuclideMap = metricIndex.getOrDefault(station, Collections.emptyMap());
for (String nuclideName : allNuclides) {
// 直接从索引中获取该站点的该核素数据列表
List<ThresholdMetric> stationMetrics = nuclideMap.get(nuclideName);
if (stationMetrics == null || stationMetrics.isEmpty()) {
// 没有找到记录创建默认对象
ThresholdMetric tm = new ThresholdMetric();
tm.setStationId(station);
tm.setNuclideName(nuclideName);
tm.setConcentration("0");
metrics.add(tm);
} else {
// 找到了对应的记录直接添加
metrics.addAll(stationMetrics);
}
}
}
if (CollectionUtils.isEmpty(metrics)) {
log.debug("未查询到核素度量数据:台站{}", stationIds);
return new HashMap<>();
}
// 组装分层数据结构
Map<String, Map<String, List<Double>>> result = new HashMap<>(stationIds.size());
metrics.forEach(metric -> parseMetricToMap(metric, result));
log.debug("核素度量数据查询完成:有效台站{}个", result.size());
return result;
}
protected List<ThresholdMetric> getThresholdMetric(List<String> stationIds) {
// 参数校验
if (CollectionUtils.isEmpty(stationIds)) {
log.warn("获取核素度量数据失败台站ID列表为空");
throw new IllegalArgumentException("台站ID列表不可为空");
}
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, -getDayValue());
String startDate = DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd HH:mm:ss");
log.debug("查询核素度量数据:台站{}个,时间范围{}至今",
stationIds.size(), startDate);
// 按数据类型查询度量数据
List<ThresholdMetric> queryMetrics = queryMetricsByDataType(stationIds, startDate);
List<ThresholdMetric> metrics = stationIds.stream()
.flatMap(stationId -> getAllNuclides().stream()
.map(nuclide -> {
// 查找匹配的查询结果
Optional<ThresholdMetric> matched = queryMetrics.stream()
.filter(Objects::nonNull)
.filter(qm -> qm.getStationId() == Integer.parseInt(stationId))
.filter(qm -> nuclide != null && nuclide.equals(qm.getNuclideName()))
.findFirst();
return matched.orElseGet(() -> {
ThresholdMetric tm = new ThresholdMetric();
tm.setStationId(Integer.valueOf(stationId));
tm.setNuclideName(nuclide);
tm.setConcentration("0");
return tm;
});
}))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(metrics)) {
log.debug("未查询到核素度量数据:台站{}", stationIds);
return new ArrayList<>();
}
return metrics;
}
/**
* 按数据类型查询度量数据差异化查询逻辑
*
* @param stationIds 台站ID列表
* @param startDate 开始时间
* @return 度量数据列表
*/
protected abstract List<ThresholdMetric> queryMetricsByDataType(List<String> stationIds, String startDate);
/**
* 解析度量数据到分层映射
*
* @param metric 度量数据实体
* @param result 目标分层映射
*/
protected void parseMetricToMap(ThresholdMetric metric, Map<String, Map<String, List<Double>>> result) {
// 提取基础字段
String stationId = Optional.ofNullable(metric.getStationId())
.map(String::valueOf)
.orElse(null);
String nuclideName = metric.getNuclideName();
String concentrationStr = metric.getConcentration();
// 跳过无效数据
if (!StringUtils.hasText(stationId) || !StringUtils.hasText(nuclideName) || !StringUtils.hasText(concentrationStr)) {
log.trace("跳过无效核素度量数据stationId={}, nuclideName={}, concentration={}",
stationId, nuclideName, concentrationStr);
return;
}
// 浓度值转换科学计数法转double
double concentration = toDouble(concentrationStr, 6);
if (Double.isInfinite(concentration) || Double.isNaN(concentration)) {
log.warn("跳过异常浓度值stationId={}, nuclideName={}, value={}",
stationId, nuclideName, concentrationStr);
return;
}
// 组装映射
result.computeIfAbsent(stationId, k -> new HashMap<>())
.computeIfAbsent(nuclideName, k -> new ArrayList<>())
.add(concentration);
}
/**
* 计算阈值和统计结果
*
* @param metrics 核素-浓度列表映射
* @param thresholds 输出核素-阈值映射
* @param statistics 输出核素-统计结果映射
*/
protected void calculateThresholdAndStats(Map<String, List<Double>> metrics,
Map<String, Double> thresholds,
Map<String, StatisticsResult> statistics) {
// 遍历核素数据
metrics.forEach((nuclideName, values) -> {
// 过滤无效值NaN/Infinite
List<Double> validValues = values.stream()
.filter(v -> !Double.isNaN(v) && !Double.isInfinite(v))
.collect(Collectors.toList());
// 至少需要2个有效数据点才计算
// if (validValues.size() < 2) {
// log.warn("核素{}数据不足({}个有效值),跳过计算", nuclideName, validValues.size());
// return;
// }
// 计算统计值中位数四分位数
StatisticsResult stats = calculateStatistics(validValues, nuclideName);
statistics.put(nuclideName, stats);
// 计算阈值中位数 + 3 * IQR四分位距
double median = stats.getMedian();
double q1 = stats.getPercentile25();
double q3 = stats.getPercentile75();
double iqr = q3 - q1;
double threshold = NumUtil.keep(median + (iqr * 3), 6);
thresholds.put(nuclideName, threshold);
});
}
// protected void calculateThresholdAndStats(Map<String, List<ThresholdMetric>> metrics,
// Map<String, Double> thresholds,
// Map<String, StatisticsResult> statistics) {
// if (metrics == null || metrics.isEmpty()) {
// log.warn("核素度量数据为空,跳过计算");
// return;
// }
// metrics.forEach((nuclideName, values) -> {
// if (values==null||values.isEmpty()) {
// log.trace("核素{}数据为空,跳过计算", nuclideName);
// return;
// }
//
// // 计算统计值中位数四分位数
// StatisticsResult stats = calculateStatistics( nuclideName);
// statistics.put(nuclideName, stats);
//
// // 计算阈值中位数 + 3 * IQR四分位距
// double median = stats.getMedian();
// double q1 = stats.getPercentile25();
// double q3 = stats.getPercentile75();
// double iqr = q3 - q1;
// double threshold = NumUtil.keep(median + (iqr * 3), 6);
//
// thresholds.put(nuclideName, threshold);
// });
//
//
// }
/**
* 处理单个台站批量计算时用
*
* @param info 台站ID
* @param metrics 核素-浓度列表映射
*/
protected void processSingleStation(Info info, Map<String, List<Double>> metrics) {
Map<String, Double> thresholds = new HashMap<>();
Map<String, StatisticsResult> statistics = new HashMap<>();
// 计算阈值和统计结果
calculateThresholdAndStats(metrics, thresholds, statistics);
// 保存结果子类实现
saveThresholdResults(info, thresholds, statistics);
log.info("台站 {} 处理完成dataType={},生成 {} 个阈值结果",
info.getStationId(), getCurrentDataType(), thresholds.size());
}
/**
* 计算统计值中位数25分位数75分位数
*
* @param values 有效浓度值列表
* @param nuclideName 核素名称
* @return 统计结果实体
*/
protected StatisticsResult calculateStatistics(List<Double> values, String nuclideName) {
// 排序
List<Double> sortedValues = new ArrayList<>(values);
Collections.sort(sortedValues);
int n = sortedValues.size();
StatisticsResult result = new StatisticsResult();
result.setNuclideName(nuclideName);
result.setDataCount(n);
// 计算中位数
double median = calculatePercentile(sortedValues, 50);
result.setMedian(median);
// 计算25分位数和75分位数
result.setPercentile25(calculatePercentile(sortedValues, 25));
result.setPercentile75(calculatePercentile(sortedValues, 75));
return result;
}
/**
* 计算分位数
*/
protected double calculatePercentile(List<Double> sortedValues, double percentile) {
int n = sortedValues.size();
if (n == 0) return 0.0;
if (n == 1) return sortedValues.get(0);
double index = (percentile / 100.0) * (n - 1);
int lower = (int) Math.floor(index);
int upper = lower + 1;
if (upper >= n) return sortedValues.get(lower);
double weight = index - lower;
return sortedValues.get(lower) * (1 - weight) + sortedValues.get(upper) * weight;
}
/**
* 科学计数法字符串转double
*/
protected double toDouble(String scientific, int precision) {
if (!StringUtils.hasText(scientific)) {
log.warn("科学计数法转换失败:输入字符串为空");
return 0.0;
}
BigDecimal bd;
try {
bd = new BigDecimal(scientific.trim());
} catch (NumberFormatException e) {
log.error("科学计数法转换失败:输入{}格式无效", scientific, e);
return 0.0;
}
// 边界检查
if (bd.abs().compareTo(BigDecimal.valueOf(Double.MAX_VALUE)) > 0) {
log.warn("数值{}超出double最大值返回无穷大", scientific);
return bd.signum() > 0 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
}
// 精度控制
bd = bd.setScale(precision, RoundingMode.HALF_UP);
bd = safeValue(bd);
return bd.doubleValue();
}
/**
* 确保数值在数据库支持范围内
*/
protected BigDecimal safeValue(BigDecimal value) {
if (value == null) {
return BigDecimal.ZERO;
}
return isOutOfDbRange(value) ? BigDecimal.ZERO : value;
}
/**
* 检查数值是否超出数据库支持范围
*/
protected boolean isOutOfDbRange(BigDecimal value) {
if (value == null) {
return false;
}
// 检查数值边界
if (value.compareTo(DB_MAX_VALUE) > 0 || value.compareTo(DB_MIN_VALUE) < 0) {
log.trace("数值{}超出范围[{},{}]", value, DB_MIN_VALUE, DB_MAX_VALUE);
return true;
}
// 检查整数部分位数
BigDecimal integerPart = value.setScale(0, RoundingMode.DOWN).abs();
if (integerPart.precision() > DB_INTEGER_PLACES) {
log.trace("数值{}整数部分{}位,超出最大{}位", value, integerPart.precision(), DB_INTEGER_PLACES);
return true;
}
return false;
}
}

View File

@ -1,8 +0,0 @@
package org.jeecg.modules.base.service.impl;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.base.service.IThresholdResultHisService;
public abstract class ThresholdResultHisBaseService <M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements IThresholdResultHisService {
}

View File

@ -1,12 +1,8 @@
package org.jeecg.modules.entity.vo;
import cn.hutool.core.util.ObjectUtil;
import lombok.Data;
import org.jeecg.common.util.NumUtil;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
@Data
@ -52,39 +48,4 @@ public class CalMDCInfo implements Serializable {
*/
private Double yield;
private Double mda;
private String halfLifeStr = "";
private String mdcStr = "";
private String mdaStr = "";
public void format(){
if (ObjectUtil.isNotNull(halflife))
halfLifeStr = halfLifeStr(halflife);
if (ObjectUtil.isNotNull(mdc))
mdcStr = NumUtil.keep6ScienceStr(mdc);
if (ObjectUtil.isNotNull(mda))
mdaStr = NumUtil.keep6ScienceStr(mda);
}
private String halfLifeStr(Double halflife){
String units = "D";
if (halflife >= 1000) {
halflife = halflife / 365.25;
units = "A";
} else if (halflife < 0.1 && halflife >= 1.0 / 1440.0) {
halflife = halflife * 1440.0;
units = "M";
} else if (halflife <= 1.0 / 1440.0 && halflife > 0.0) {
halflife = halflife * 86400.0;
units = "S";
}
if (halflife < 1000)
return String.format("%.3f", halflife) + units;
NumberFormat numberFormat = new DecimalFormat("0.###E0");
return numberFormat.format(halflife) + units;
}
}

View File

@ -3,7 +3,10 @@ package org.jeecg.modules.entity.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@Data
public class GStoreMiddleProcessData implements Serializable {
@ -228,8 +231,6 @@ public class GStoreMiddleProcessData implements Serializable {
//SpecSetup
public SpecSetup setting_specSetup;
public List<CalMDCInfo> mdcInfos;
public GStoreMiddleProcessData(){
dbWriteFlag = false;
dbWriteStatusFlag = "";
@ -418,7 +419,6 @@ public class GStoreMiddleProcessData implements Serializable {
Collection_Station_Comments = "";
NDC_Analysis_General_Comments = "";
setting_specSetup = new SpecSetup();
mdcInfos = new ArrayList<>();
}
}

View File

@ -2,10 +2,8 @@ package org.jeecg.modules.entity.vo;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class PeakInfo implements Serializable {
@ -63,17 +61,11 @@ public class PeakInfo implements Serializable {
public List<String> nuclides;
/**
* 记录peak中被删除的核素interactiveTool
*/
public Map<Double, List<String>> deletedNuclideMap;
public PeakInfo(){
nuclides = new LinkedList<>();
comments = "";
recoilBetaChan = "nan";
recoilDeltaChan = "nan";
deletedNuclideMap = new HashMap<>();
}
}

View File

@ -1,23 +0,0 @@
package org.jeecg.modules.entity.vo.QCFlagParmData;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class ParamConfig {
@XmlElement(name = "collectionTime")
private RuleGroup collectionTime;
@XmlElement(name = "acquisitionTime")
private RuleGroup acquisitionTime;
@XmlElement(name = "xeVolume")
private RuleGroup xeVolume;
@XmlElement(name = "airVolume")
private RuleGroup airVolume;
}

View File

@ -1,16 +0,0 @@
package org.jeecg.modules.entity.vo.QCFlagParmData;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "config")
@XmlAccessorType(XmlAccessType.FIELD)
public class QCFlagParam {
@XmlElement(name = "sauna")
public ParamConfig sauna;
@XmlElement(name = "sauna2")
public ParamConfig sauna2;
}

View File

@ -1,20 +0,0 @@
package org.jeecg.modules.entity.vo.QCFlagParmData;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Rule {
@XmlAttribute(name = "min")
private double min;
@XmlAttribute(name = "max")
private Double max; // 使用Double以便可以为null表示没有上限
@XmlAttribute(name = "color")
private String color;
}

View File

@ -1,15 +0,0 @@
package org.jeecg.modules.entity.vo.QCFlagParmData;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class RuleGroup {
@XmlElement(name = "Rule")
List<Rule> rules;
}

View File

@ -1,22 +1,11 @@
package org.jeecg.modules.entity.vo;
import lombok.Data;
import org.jeecg.common.properties.ParameterProperties;
import org.jeecg.modules.base.enums.StationDetailType;
import org.jeecg.modules.entity.vo.QCFlagParmData.QCFlagParam;
import org.jeecg.modules.entity.vo.QCFlagParmData.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import static org.jeecg.modules.base.enums.StationDetailType.*;
@Data
public class Sections implements Serializable {
@ -28,17 +17,7 @@ public class Sections implements Serializable {
private List<Double> airVolumeSections;
//region QC-Flag参数
private List<Rule> collectionTimeRules;
private List<Rule> acquisitionTimeRules;
private List<Rule> xeVolumeRules;
private List<Rule> airVolumeRules;
//endregion
public Sections() {
public Sections(){
collectionTimeSections = new LinkedList<>();
collectionTimeSections.add(0.0);
collectionTimeSections.add(6.0);
@ -64,34 +43,4 @@ public class Sections implements Serializable {
airVolumeSections.add(10.0);
}
public Sections(StationDetailType sectionsType,String pathname) {
try {
// 创建JAXB上下文
JAXBContext context = JAXBContext.newInstance(QCFlagParam.class);
// 创建Unmarshaller
Unmarshaller unmarshaller = context.createUnmarshaller();
File file = new File(pathname);
QCFlagParam config = (QCFlagParam) unmarshaller.unmarshal(file);
switch (sectionsType) {
case SAUNA:
collectionTimeRules = config.sauna.getCollectionTime().getRules();
acquisitionTimeRules = config.sauna.getAcquisitionTime().getRules();
xeVolumeRules = config.sauna.getXeVolume().getRules();
airVolumeRules = config.sauna.getAirVolume().getRules();
break;
case SAUNA2:
collectionTimeRules = config.sauna2.getCollectionTime().getRules();
acquisitionTimeRules = config.sauna2.getAcquisitionTime().getRules();
xeVolumeRules = config.sauna2.getXeVolume().getRules();
airVolumeRules = config.sauna2.getAirVolume().getRules();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,7 +1,6 @@
package org.jeecg.modules.entity.vo;
import lombok.Data;
import org.jeecg.common.util.NumUtil;
import java.io.Serializable;
@ -18,7 +17,4 @@ public class TableWidget implements Serializable {
private String fwhmKeV;
public void setChannel(Double channel) {
this.channel = NumUtil.fixedMax(6, channel);
}
}

View File

@ -7,19 +7,14 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.RedisConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.dto.NameValue;
import org.jeecg.modules.entity.DailyEmailChartDataVO;
import org.jeecg.modules.entity.EmailChartDataVO;
import org.jeecg.modules.service.ISysEmailLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@ -35,11 +30,11 @@ public class SysEmailLogController {
@GetMapping("status")
@ApiOperation("邮箱服务器状态")
public Result<?> status(@RequestParam("emailId") String emailId) {
public Result<?> status(@RequestParam("emailId") String emailId){
String statusKey = RedisConstant.EMAIL_STATUS;
NameValue nameValue = (NameValue) redisUtil.hget(statusKey, emailId);
boolean online = false;
if (ObjectUtil.isNotNull(nameValue)) {
if (ObjectUtil.isNotNull(nameValue)){
Boolean value = nameValue.getValue();
if (ObjectUtil.isNotNull(value))
online = value;
@ -49,75 +44,27 @@ public class SysEmailLogController {
@GetMapping("space")
@ApiOperation("邮箱服务器空间")
public Result<?> space(@RequestParam("emailId") String emailId) {
public Result<?> space(@RequestParam("emailId") String emailId){
return Result.OK(sysEmailLogService.space(emailId));
}
@GetMapping("total")
@ApiOperation("今天|昨天|过去一周邮件量")
public Result<?> totalEmail(@RequestParam("emailId") String emailId) {
public Result<?> totalEmail(@RequestParam("emailId") String emailId){
return sysEmailLogService.totalEmail(emailId);
}
@GetMapping("today")
@ApiOperation("今日邮件接收量")
public Result<?> today(@RequestParam("emailId") String emailId) {
public Result<?> today(@RequestParam("emailId") String emailId){
return sysEmailLogService.todayMin(emailId);
}
@GetMapping("analysis")
@ApiOperation("根据日期统计-折线图")
public Result<?> analysis(@RequestParam("emailId") String emailId,
@RequestParam("startDate") String startDate,
@RequestParam("endDate") String endDate) {
return sysEmailLogService.analysis(emailId, startDate, endDate);
@RequestParam("startDate") String startDate,
@RequestParam("endDate") String endDate){
return sysEmailLogService.analysis(emailId, startDate, endDate);
}
@GetMapping("getMinus")
public Integer getMinus(@RequestParam("emailId") String emailId) {
return sysEmailLogService.getMinus(emailId);
}
/**
* 获取当天昨天的报警,每小时统计的数量
*
* @param emailId 邮件ID
* 开始时间 00:00:00
* 结束时间 23:59:59
* @return Result
*/
@GetMapping("getRecentEmailDatas")
@ApiOperation("获取当天、昨天的每小时统计的数量")
public Result<?> getRecentEmailDatas(@RequestParam("emailId") String emailId) {
try {
EmailChartDataVO data = sysEmailLogService.getDashboardHourlyStats(emailId);
return Result.OK(data);
} catch (Exception e) {
return Result.error("错误:" + e.getMessage());
}
}
/**
* 获取一月的邮件信息
* @param emailId 邮件ID
* @param startDate 开始时间
* @param endDate 结束时间
* @return DailyEmailChartDataVO
*/
@GetMapping("getDashboardDailyStats")
@ApiOperation("获取一月的邮件信息")
public Result<?> getDashboardDailyStats(@RequestParam("emailId") String emailId,
@RequestParam("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@RequestParam("endDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
try {
DailyEmailChartDataVO data = sysEmailLogService.getDashboardDailyStats(emailId, startDate, endDate);
return Result.OK(data);
} catch (Exception e) {
return Result.error("错误:" + e.getMessage());
}
}
}

View File

@ -1,25 +0,0 @@
package org.jeecg.modules.entity;
import lombok.Data;
import java.util.List;
@Data
public class DailyEmailChartDataVO {
/**
* X轴日期类目 (例如 2025-12-05, 2025-12-06, ...)
*/
private List<String> categories;
/**
* Y轴数据系列
*/
private DailySeriesData series;
@Data
public static class DailySeriesData {
private List<Long> alarm; // 告警量
private List<Long> process; // 邮件处理量
}
}

View File

@ -1,24 +0,0 @@
package org.jeecg.modules.entity;
import lombok.Data;
import java.time.LocalDate;
/**
* 每日统计数据传输对象 (DailyStatDTO)
*
*/
@Data
public class DailyStatDTO {
/**
* 日期键对应 SQL 中的 day_key ( 2025-12-10)
*/
private LocalDate dayKey;
/**
* 当天的记录总数
*/
private long countVal;
}

View File

@ -1,26 +0,0 @@
package org.jeecg.modules.entity;
import lombok.Data;
import java.util.List;
/**
* 图表数据视图对象 (VO)
* 统一返回给前端包含所有时间序列数据
*/
@Data
public class EmailChartDataVO {
/** X轴时间类目 (00:00 - 23:00) */
private List<String> categories;
/** Y轴数据系列 */
private SeriesData series;
@Data
public static class SeriesData {
private List<Long> todayAlarm; // 今天告警量
private List<Long> todayProcess; // 今天邮件处理量
private List<Long> yesterdayAlarm; // 昨天告警量
private List<Long> yesterdayProcess;// 昨天邮件处理量
}
}

View File

@ -1,22 +0,0 @@
package org.jeecg.modules.entity;
import lombok.Data;
/**
* 统计数据传输对象 (StatDTO)
* 用于承载数据库按小时分组统计后的结果
* 对应 SQL: SELECT EXTRACT(HOUR FROM ...) AS hour_key, COUNT(*) AS count_val
*/
@Data
public class StatDTO {
/**
* 小时键0 - 23对应 SQL 中的 hour_key
*/
private int hourKey;
/**
* 该小时的记录总数对应 SQL 中的 count_val
*/
private long countVal;
}

View File

@ -43,7 +43,5 @@ public interface SystemClient {
@PostMapping("/sys/appMessage/pushMessageToSingle")
void pushMessageToSingle(@RequestBody MessageDTO messageDTO, @RequestParam String groupId);
/* GardsSampleDataController下相关接口 */
@GetMapping("/gardsSampleData/getDetectorId")
String getDetectorId(@RequestParam String sampleId);
}

View File

@ -15,7 +15,6 @@ public class NucliedAvgJob implements Job{
@Override
@Scheduled(cron = "${task.period-avg:0 2 0 * * ?}")
// @Scheduled(cron = "${task.period-avg:0/59 0/1 * * * ? }")
public void execute() {
calculateConcService.calcAndSave();
}

View File

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.ConcDtoXe;
import org.jeecg.modules.base.dto.SampNucl;
import org.jeecg.modules.base.entity.rnauto.GardsNuclIded;
import java.util.List;
@ -16,5 +15,5 @@ public interface GardsNuclIdedAutoMapper extends BaseMapper<GardsNuclIded> {
List<ConcDto> getConc(Map<String,Object> param);
List<SampNucl> sampNucl(String stationId, String detectorId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -3,7 +3,6 @@ package org.jeecg.modules.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.SampNucl;
import org.jeecg.modules.base.entity.rnman.GardsNuclIded;
import java.util.List;
@ -13,7 +12,7 @@ import java.util.Set;
@Mapper
public interface GardsNuclIdedManMapper extends BaseMapper<GardsNuclIded> {
List<ConcDto> getConc(Map<String, Object> param);
List<ConcDto> getConc(Map<String,Object> param);
List<SampNucl> sampNucl(String stationId, String detectorId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.ConcDtoXe;
import org.jeecg.modules.base.dto.SampNucl;
import org.jeecg.modules.base.entity.rnauto.GardsXeResults;
import java.util.List;
@ -16,5 +15,5 @@ public interface GardsXeResultsAutoMapper extends BaseMapper<GardsXeResults> {
List<ConcDtoXe> getConc(Map<String,Object> params);
List<SampNucl> sampNucl(String stationId, String detectorId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.ConcDtoXe;
import org.jeecg.modules.base.dto.SampNucl;
import org.jeecg.modules.base.entity.rnman.GardsXeResults;
import java.util.List;
@ -16,5 +15,5 @@ public interface GardsXeResultsManMapper extends BaseMapper<GardsXeResults> {
List<ConcDtoXe> getConc(Map<String,Object> params);
List<SampNucl> sampNucl(String stationId, String detectorId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -1,15 +1,7 @@
package org.jeecg.modules.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.base.entity.postgre.SysEmailLog;
import org.jeecg.modules.entity.AlarmHistory;
import org.jeecg.modules.entity.DailyStatDTO;
import org.jeecg.modules.entity.StatDTO;
import java.util.List;
import java.util.Map;
/**
* 系统邮件日志
@ -19,46 +11,4 @@ import java.util.Map;
*/
public interface SysEmailLogMapper extends BaseMapper<SysEmailLog> {
/**
* 获取邮件告警信息
* @param emailIds 邮件ID集合
* @param startDate 开始时间
* @param endDate 结束时间
* @return List<AlarmHistory>
*/
List<AlarmHistory> findAlarmHistory( @Param("emailIds") List<String> emailIds,
@Param("startDate") String startDate,
@Param("endDate") String endDate);
List<StatDTO> selectHourlyStats(@Param("emailId") String emailId,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
List<StatDTO> findAlarmHistoryStats(@Param("emailId") String emailId,
@Param("startDate") String startDate,
@Param("endDate") String endDate);
List<DailyStatDTO> selectDailyProcessStats(@Param("emailId") String emailId,
@Param("startDate") String startDate,
@Param("endDate") String endDate);
List<DailyStatDTO> findDailyAlarmStats(@Param("emailId") String emailId,
@Param("startDate") String startDate,
@Param("endDate") String endDate);
}

View File

@ -3,7 +3,6 @@
<mapper namespace="org.jeecg.modules.mapper.GardsNuclIdedAutoMapper">
<select id="getConc" resultType="org.jeecg.modules.base.dto.ConcDto">
SELECT
DISTINCT samp.SAMPLE_ID,
nucl.NUCLIDENAME,
nucl.CONCENTRATION AS CONC,
ana.ANALYSISBEGIN
@ -11,65 +10,31 @@
RNAUTO.GARDS_NUCL_IDED nucl
INNER JOIN RNAUTO.GARDS_ANALYSES ana ON ana.IDANALYSIS = nucl.IDANALYSIS
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA samp ON samp.SAMPLE_ID = nucl.SAMPLE_ID
INNER JOIN RNAUTO.GARDS_QC_CHECK qc ON samp.SAMPLE_ID = qc.SAMPLE_ID
<trim prefix="where" suffixOverrides="or">
<where>
ana.ANALYSISBEGIN BETWEEN to_date(#{startDate},'yyyy-mm-dd hh24:mi:ss')
AND to_date(#{endDate},'yyyy-mm-dd hh24:mi:ss')
AND samp.DATA_TYPE = 'S' AND samp.STATUS IN ('P', 'R')
AND samp.STATION_ID = #{stationId}
AND samp.SPECTRAL_QUALIFIE = 'FULL'
<if test="nuclideName != null and nuclideName.size() > 0">
AND nucl.NUCLIDENAME IN
<foreach collection="nuclideName" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
<if test="(colTime != null and colTime.size() > 0) || (acqTime != null and acqTime.size() > 0) ||
airFlow != null || decayTime != null || sampVol != null || be7FWHM != null || ba140MDC != null || xe133MDC != null">
<trim prefix="and(" suffixOverrides="or" suffix=")">
<if test="colTime != null and colTime.size() > 0">
(qc.qc_name = 'col_time' and qc.qc_value between #{colTime[0]} and #{colTime[1]} ) or
</if>
<if test="acqTime != null and acqTime.size() > 0">
(qc.qc_name = 'acq_time' and qc.qc_value = #{acqTime[0]}) or
</if>
<if test="airFlow != null">
(qc.qc_name = 'airFlow' and qc.qc_value &lt; #{airFlow} ) or
</if>
<if test="decayTime != null">
(qc.qc_name = 'decay_time' and qc.qc_value &lt; #{decayTime} ) or
</if>
<if test="sampVol != null">
(qc.qc_name = 'samp_vol' and qc.qc_value &lt; #{sampVol} ) or
</if>
<if test="be7FWHM != null">
(qc.qc_name = 'Be7-FWHM' and qc.qc_value &lt; #{be7FWHM} ) or
</if>
<if test="ba140MDC != null">
(qc.qc_name = 'Ba140-MDC' and qc.qc_value &lt; #{ba140MDC} ) or
</if>
<if test="xe133MDC != null">
(qc.qc_name = 'Xe133-MDC' and qc.qc_value &lt; #{xe133MDC} ) or
</if>
</trim>
</if>
</trim>
</where>
</select>
<select id="sampNucl" resultType="org.jeecg.modules.base.dto.SampNucl">
<select id="nuclideNames" resultType="java.lang.String">
SELECT
n.SAMPLE_ID,
n.NUCLIDENAME AS nuclideName
NUCLIDENAME
FROM
ORIGINAL.GARDS_SAMPLE_DATA s
INNER JOIN RNAUTO.GARDS_NUCL_IDED n ON s.SAMPLE_ID = n.SAMPLE_ID
WHERE s.STATION_ID = #{stationId} AND s.DETECTOR_ID = #{detectorId}
<if test="nuclideNames != null and nuclideNames.size() > 0">
AND n.NUCLIDENAME IN
<foreach collection="nuclideNames" open="(" close=")" index="index" item="item" separator=",">
#{item}
RNAUTO.GARDS_NUCL_IDED
WHERE
NUCLIDENAME IN
<foreach collection="nuclideNames" separator="," item="nuclideName" index="index" open="(" close=")">
#{nuclideName}
</foreach>
</if>
AND n.CONCENTRATION &gt; n.MDC
GROUP BY
NUCLIDENAME
</select>
</mapper>

View File

@ -3,72 +3,38 @@
<mapper namespace="org.jeecg.modules.mapper.GardsNuclIdedManMapper">
<select id="getConc" resultType="org.jeecg.modules.base.dto.ConcDto">
SELECT
DISTINCT samp.SAMPLE_ID,
nucl.NUCLIDENAME,
nucl.CONCENTRATION AS CONC,
ana.ANALYSISBEGIN
FROM
RNMAN.GARDS_NUCL_IDED nucl
RNMAN.GARDS_NUCL_IDED nucl
INNER JOIN RNMAN.GARDS_ANALYSES ana ON ana.IDANALYSIS = nucl.IDANALYSIS
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA samp ON samp.SAMPLE_ID = nucl.SAMPLE_ID
INNER JOIN RNMAN.GARDS_QC_CHECK qc ON samp.SAMPLE_ID = qc.SAMPLE_ID
<where>
ana.ANALYSISBEGIN BETWEEN to_date(#{startDate},'yyyy-mm-dd hh24:mi:ss')
AND to_date(#{endDate},'yyyy-mm-dd hh24:mi:ss')
AND samp.DATA_TYPE = 'S' AND samp.STATUS IN ('P', 'R')
AND samp.STATION_ID = #{stationId}
AND samp.SPECTRAL_QUALIFIE = 'FULL'
<if test="nuclideName != null and nuclideName.size() > 0">
AND nucl.NUCLIDENAME IN
<foreach collection="nuclideName" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
<if test="(colTime != null and colTime.size() > 0) || (acqTime != null and acqTime.size() > 0) ||
airFlow != null || decayTime != null || sampVol != null || be7FWHM != null || ba140MDC != null || xe133MDC != null">
<trim prefix="and(" suffixOverrides="or" suffix=")">
<if test="colTime != null and colTime.size() > 0">
(qc.qc_name = 'col_time' and qc.qc_value between #{colTime[0]} and #{colTime[1]} ) or
</if>
<if test="acqTime != null and acqTime.size() > 0">
(qc.qc_name = 'acq_time' and qc.qc_value = #{acqTime[0]}) or
</if>
<if test="airFlow != null">
(qc.qc_name = 'airFlow' and qc.qc_value &lt; #{airFlow} ) or
</if>
<if test="decayTime != null">
(qc.qc_name = 'decay_time' and qc.qc_value &lt; #{decayTime} ) or
</if>
<if test="sampVol != null">
(qc.qc_name = 'samp_vol' and qc.qc_value &lt; #{sampVol} ) or
</if>
<if test="be7FWHM != null">
(qc.qc_name = 'Be7-FWHM' and qc.qc_value &lt; #{be7FWHM} ) or
</if>
<if test="ba140MDC != null">
(qc.qc_name = 'Ba140-MDC' and qc.qc_value &lt; #{ba140MDC} ) or
</if>
<if test="xe133MDC != null">
(qc.qc_name = 'Xe133-MDC' and qc.qc_value &lt; #{xe133MDC} ) or
</if>
</trim>
</if>
</where>
</select>
<select id="sampNucl" resultType="org.jeecg.modules.base.dto.SampNucl">
<select id="nuclideNames" resultType="java.lang.String">
SELECT
n.SAMPLE_ID,
n.NUCLIDENAME AS nuclideName
NUCLIDENAME
FROM
ORIGINAL.GARDS_SAMPLE_DATA s
INNER JOIN RNMAN.GARDS_NUCL_IDED n ON s.SAMPLE_ID = n.SAMPLE_ID
WHERE s.STATION_ID = #{stationId} AND s.DETECTOR_ID = #{detectorId}
<if test="nuclideNames != null and nuclideNames.size() > 0">
AND n.NUCLIDENAME IN
<foreach collection="nuclideNames" open="(" close=")" index="index" item="item" separator=",">
#{item}
RNMAN.GARDS_NUCL_IDED
WHERE
NUCLIDENAME IN
<foreach collection="nuclideNames" separator="," item="nuclideName" index="index" open="(" close=")">
#{nuclideName}
</foreach>
</if>
AND n.CONCENTRATION &gt; n.MDC
GROUP BY
NUCLIDENAME
</select>
</mapper>

View File

@ -2,93 +2,39 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.mapper.GardsXeResultsAutoMapper">
<select id="getConc" resultType="org.jeecg.modules.base.dto.ConcDtoXe">
SELECT * FROM (
SELECT
samp.SAMPLE_ID,
SELECT
xe.NUCLIDE_NAME,
xe.CONC,
ana.ANALYSISBEGIN,
xe.NID_FLAG
FROM
RNAUTO.GARDS_XE_RESULTS xe
INNER JOIN RNAUTO.GARDS_ANALYSES ana ON ana.IDANALYSIS = xe.IDANALYSIS
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA samp ON samp.SAMPLE_ID = xe.SAMPLE_ID
INNER JOIN ORIGINAL.GARDS_SAMPLE_AUX aux ON samp.SAMPLE_ID = aux.SAMPLE_ID
<where>
ana.ANALYSISBEGIN BETWEEN to_date(#{startDate},'yyyy-mm-dd hh24:mi:ss')
AND to_date(#{endDate},'yyyy-mm-dd hh24:mi:ss')
AND samp.DATA_TYPE = 'S' AND samp.STATUS IN ('P', 'R')
AND samp.STATION_ID = #{stationId}
AND samp.SPECTRAL_QUALIFIE = 'FULL'
<if test="nuclideName != null and nuclideName.size() > 0">
AND xe.NUCLIDE_NAME IN
<foreach collection="nuclideName" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
<if test="colTime != null and colTime.size() > 0">
and ((TO_NUMBER(samp.COLLECT_STOP - samp.COLLECT_START) * 24) between #{colTime[0]} and #{colTime[1]} )
</if>
<if test="acqTime != null and acqTime.size() > 0">
and (samp.ACQUISITION_LIVE_SEC / 3600 between #{colTime[0]} and #{colTime[1]} )
</if>
<if test="XeVol != null">
AND (aux.XE_VOLUME &gt; #{XeVol} )
</if>
<if test="Xe133MDC != null and Xe133MDC.size() > 0">
AND (xe.NUCLIDE_NAME = 'Xe133m' AND MDC between #{Xe133MDC[0]} AND #{Xe133MDC[1]} )
</if>
</where>
) a
<trim prefix="where" suffixOverrides="or">
<choose>
<when test="Xe133mFlag != null">
(a.NUCLIDE_NAME = 'Xe133m' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe133m' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
<choose>
<when test="Xe133Flag != null">
(a.NUCLIDE_NAME = 'Xe133' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe133' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
<choose>
<when test="Xe131mFlag != null">
(a.NUCLIDE_NAME = 'Xe131m' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe131m' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
<choose>
<when test="Xe135Flag != null">
(a.NUCLIDE_NAME = 'Xe135' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe135' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
</trim>
</select>
<select id="sampNucl" resultType="org.jeecg.modules.base.dto.SampNucl">
SELECT
n.SAMPLE_ID,
n.NUCLIDE_NAME
ana.ANALYSISBEGIN
FROM
ORIGINAL.GARDS_SAMPLE_DATA s
INNER JOIN RNAUTO.GARDS_XE_RESULTS n ON s.SAMPLE_ID = n.SAMPLE_ID
WHERE s.STATION_ID = #{stationId} AND s.DETECTOR_ID = #{detectorId}
<if test="nuclideNames != null and nuclideNames.size() > 0">
AND n.NUCLIDE_NAME IN
<foreach collection="nuclideNames" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
AND n.NID_FLAG = 1
RNAUTO.GARDS_XE_RESULTS xe
INNER JOIN RNAUTO.GARDS_ANALYSES ana ON ana.IDANALYSIS = xe.IDANALYSIS
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA samp ON samp.SAMPLE_ID = xe.SAMPLE_ID
<where>
ana.ANALYSISBEGIN BETWEEN to_date(#{startDate},'yyyy-mm-dd hh24:mi:ss')
AND to_date(#{endDate},'yyyy-mm-dd hh24:mi:ss')
AND samp.DATA_TYPE = 'S' AND samp.STATUS IN ('P', 'R')
AND samp.STATION_ID = #{stationId}
<if test="nuclideName != null and nuclideName.size() > 0">
AND xe.NUCLIDE_NAME IN
<foreach collection="nuclideName" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
</where>
</select>
<select id="nuclideNames" resultType="java.lang.String">
SELECT
NUCLIDE_NAME
FROM
RNAUTO.GARDS_XE_RESULTS
WHERE
NUCLIDE_NAME IN
<foreach collection="nuclideNames" separator="," item="nuclideName" index="index" open="(" close=")">
#{nuclideName}
</foreach>
GROUP BY
NUCLIDE_NAME
</select>
</mapper>

View File

@ -2,81 +2,39 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.mapper.GardsXeResultsManMapper">
<select id="getConc" resultType="org.jeecg.modules.base.dto.ConcDtoXe">
SELECT * FROM (
SELECT
samp.SAMPLE_ID,
SELECT
xe.NUCLIDE_NAME,
xe.CONC,
ana.ANALYSISBEGIN,
xe.NID_FLAG
FROM
RNMAN.GARDS_XE_RESULTS xe
INNER JOIN RNMAN.GARDS_ANALYSES ana ON ana.IDANALYSIS = xe.IDANALYSIS
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA samp ON samp.SAMPLE_ID = xe.SAMPLE_ID
INNER JOIN ORIGINAL.GARDS_SAMPLE_AUX aux ON samp.SAMPLE_ID = aux.SAMPLE_ID
<where>
ana.ANALYSISBEGIN BETWEEN to_date(#{startDate},'yyyy-mm-dd hh24:mi:ss')
AND to_date(#{endDate},'yyyy-mm-dd hh24:mi:ss')
AND samp.DATA_TYPE = 'S' AND samp.STATUS IN ('P', 'R')
AND samp.STATION_ID = #{stationId}
AND samp.SPECTRAL_QUALIFIE = 'FULL'
<if test="nuclideName != null and nuclideName.size() > 0">
AND xe.NUCLIDE_NAME IN
<foreach collection="nuclideName" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
</where>
)a
<trim prefix="where" suffixOverrides="or">
<choose>
<when test="Xe133mFlag != null">
(a.NUCLIDE_NAME = 'Xe133m' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe133m' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
<choose>
<when test="Xe133Flag != null">
(a.NUCLIDE_NAME = 'Xe133' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe133' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
<choose>
<when test="Xe131mFlag != null">
(a.NUCLIDE_NAME = 'Xe131m' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe131m' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
<choose>
<when test="Xe135Flag != null">
(a.NUCLIDE_NAME = 'Xe135' AND a.NID_FLAG = 1 ) or
</when>
<otherwise>
(a.NUCLIDE_NAME = 'Xe135' AND (a.NID_FLAG = 1 AND a.NID_FLAG = 0) ) or
</otherwise>
</choose>
</trim>
</select>
<select id="sampNucl" resultType="org.jeecg.modules.base.dto.SampNucl">
SELECT
n.SAMPLE_ID,
n.NUCLIDE_NAME
ana.ANALYSISBEGIN
FROM
ORIGINAL.GARDS_SAMPLE_DATA s
INNER JOIN RNMAN.GARDS_XE_RESULTS n ON s.SAMPLE_ID = n.SAMPLE_ID
WHERE s.STATION_ID = #{stationId} AND s.DETECTOR_ID = #{detectorId}
<if test="nuclideNames != null and nuclideNames.size() > 0">
AND n.NUCLIDE_NAME IN
<foreach collection="nuclideNames" open="(" close=")" index="index" item="item" separator=",">
#{item}
RNMAN.GARDS_XE_RESULTS xe
INNER JOIN RNMAN.GARDS_ANALYSES ana ON ana.IDANALYSIS = xe.IDANALYSIS
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA samp ON samp.SAMPLE_ID = xe.SAMPLE_ID
<where>
ana.ANALYSISBEGIN BETWEEN to_date(#{startDate},'yyyy-mm-dd hh24:mi:ss')
AND to_date(#{endDate},'yyyy-mm-dd hh24:mi:ss')
AND samp.DATA_TYPE = 'S' AND samp.STATUS IN ('P', 'R')
AND samp.STATION_ID = #{stationId}
<if test="nuclideName != null and nuclideName.size() > 0">
AND xe.NUCLIDE_NAME IN
<foreach collection="nuclideName" open="(" close=")" index="index" item="item" separator=",">
#{item}
</foreach>
</if>
</where>
</select>
<select id="nuclideNames" resultType="java.lang.String">
SELECT
NUCLIDE_NAME
FROM
RNMAN.GARDS_XE_RESULTS
WHERE
NUCLIDE_NAME IN
<foreach collection="nuclideNames" separator="," item="nuclideName" index="index" open="(" close=")">
#{nuclideName}
</foreach>
</if>
AND n.NID_FLAG = 1
GROUP BY
NUCLIDE_NAME
</select>
</mapper>

View File

@ -2,91 +2,4 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.mapper.SysEmailLogMapper">
<select id="findAlarmHistory" resultType="org.jeecg.modules.entity.AlarmHistory">
SELECT
e.name,
l.alarm_start_date,
l.alarm_info,
r.operator,
l.alarm_value
FROM
sys_email e
INNER JOIN alarm_rule r ON r.source_id = e.id
INNER JOIN alarm_log l ON l.rule_id = r.id
<where>
<if test="emailIds != null and emailIds.size() > 0">
e.id IN
<foreach collection="emailIds" index="index" open="(" close=")" item="item" separator=",">
#{item}
</foreach>
</if>
<if test="startDate != null and startDate != ''">
AND l.alarm_start_date &gt;= #{startDate}
</if>
<if test="endDate != null and endDate != ''">
AND l.alarm_start_date &lt;= #{endDate}
</if>
</where>
ORDER BY alarm_start_date DESC
</select>
<select id="selectHourlyStats" resultType="org.jeecg.modules.entity.StatDTO">
SELECT
-- EXTRACT(HOUR FROM receive_time) 提取小时数 (0-23)
EXTRACT(HOUR FROM receive_time) AS hour_key,
COUNT(id) AS count_val
FROM sys_email_log
WHERE email_id = #{emailId}
-- PostgreSQL 的时间范围查询 (使用::timestamp显式转换)
AND receive_time BETWEEN #{startTime}::timestamp
AND #{endTime}::timestamp
-- 按小时分组
GROUP BY hour_key
ORDER BY hour_key
</select>
<select id="findAlarmHistoryStats" resultType="org.jeecg.modules.entity.StatDTO">
SELECT
EXTRACT(HOUR FROM l.alarm_start_date) AS hour_key,
COUNT(l.id) AS count_val
FROM
sys_email e
INNER JOIN alarm_rule r ON r.source_id = e.id
INNER JOIN alarm_log l ON l.rule_id = r.id
<where>
e.id = #{emailId}
AND l.alarm_start_date BETWEEN #{startDate}::timestamp AND #{endDate}::timestamp
</where>
GROUP BY hour_key
ORDER BY hour_key
</select>
<select id="selectDailyProcessStats" resultType="org.jeecg.modules.entity.DailyStatDTO">
SELECT
-- 按天截断时间戳,得到日期
DATE_TRUNC('day', receive_time) AS day_key,
COUNT(id) AS count_val
FROM sys_email_log
WHERE email_id = #{emailId}
AND receive_time BETWEEN #{startDate}::timestamp AND #{endDate}::timestamp
GROUP BY day_key
ORDER BY day_key
</select>
<select id="findDailyAlarmStats" resultType="org.jeecg.modules.entity.DailyStatDTO">
SELECT
DATE_TRUNC('day', l.alarm_start_date) AS day_key,
COUNT(l.id) AS count_val
FROM
sys_email e
INNER JOIN alarm_rule r ON r.source_id = e.id
INNER JOIN alarm_log l ON l.rule_id = r.id
WHERE
e.id = #{emailId}
AND l.alarm_start_date BETWEEN #{startDate}::timestamp AND #{endDate}::timestamp
GROUP BY day_key
ORDER BY day_key
</select>
</mapper>

View File

@ -36,7 +36,6 @@
e.is_qiye,
e.enabled,
e.email_server_address,
e.email_server_type,
COUNT (l.id) AS alarms
FROM
sys_email e

View File

@ -5,20 +5,21 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.constant.RedisConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.SampleType;
import org.jeecg.common.util.*;
import org.jeecg.common.util.dynamic.db.FreemarkerParseFactory;
import org.jeecg.modules.base.dto.NuclideInfo;
import org.jeecg.modules.base.dto.Info;
import org.jeecg.modules.base.entity.postgre.AlarmAnalysisLog;
@ -38,11 +39,14 @@ import org.springframework.stereotype.Component;
import static org.jeecg.common.constant.enums.MessageTypeEnum.*;
import static org.jeecg.common.util.TokenUtils.getTempToken;
import static org.jeecg.modules.base.enums.Template.ANALYSIS_NUCLIDE;
import static org.jeecg.modules.base.enums.Template.ANALYSIS_NUCLIDE;
import static org.jeecg.modules.base.enums.Template.MONITOR_EMAIL;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Data
@ -61,7 +65,6 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
private IAlarmAnalysisRuleService ruleService;
private AnalysisResultService analysisResultService;
private IAlarmAnalysisNuclideAvgService nuclideAvgService;
private RedisUtil redisUtil;
private final String COMMA = SymbolConstant.COMMA;
@ -95,7 +98,7 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
redisStreamUtil.del(streamKey, recordId.getValue());
}
}catch (Exception e){
log.error("AnalysisConsumer消费异常: ", e);
log.error("AnalysisConsumer消费异常: {}", e.getMessage());
}finally {
destroy();
}
@ -106,11 +109,10 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
String sampleId = info.getSampleId();
String fullOrPrel = info.getFullOrPrel();
String datasource = info.getDatasource();
Map<String, String> infoNuclideMap = info.getNuclides();
Map<String, String> nuclides = info.getNuclides();
if (StrUtil.isBlank(stationId)) return;
if (StrUtil.isBlank(sampleId)) return;
if (MapUtil.isEmpty(infoNuclideMap)) return;
if (MapUtil.isEmpty(nuclides)) return;
List<AlarmAnalysisRule> rules = ruleService.allAnalysisRule();
for (AlarmAnalysisRule rule : rules) {
// 当前规则是否有报警条件
@ -132,36 +134,18 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
// 是否有当前规则关注的核素
String nuclidesStr = rule.getNuclides();
if (StrUtil.isBlank(nuclidesStr)) continue;
Set<String> names = infoNuclideMap.keySet();
Set<String> names = nuclides.keySet();
List<String> follow = ListUtil.toList(nuclidesStr.split(COMMA));
// 因数据库 Xe核素名称 M大小写不统一先统一大小写再进行比较
Collection<String> follows = follow.stream().map(f -> {
if(f.toLowerCase().contains("xe")){
return f.replace("M", "m");
}
return f;
}).collect(Collectors.toList());
// 推送过来的核素集合与所关注核素集合取交集
Collection<String> cross = CollectionUtil.intersection(names, follows);
Collection<String> cross = CollectionUtil.intersection(names, follow);
if (CollUtil.isEmpty(cross)) continue;
Map<String, String> nuclidesCross = infoNuclideMap.entrySet().stream()
Map<String, String> nuclidesCross = nuclides.entrySet().stream()
.filter(entry -> cross.contains(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
// 开始对交集中的核素进行条件判断
info.setRuleId(rule.getId());
info.setGroupId(rule.getContactGroup());
info.setConditions(rule.getConditions());
if (null != rule.getIdentifyNuclides()) {
String[] inSplit = rule.getIdentifyNuclides().split(",");
if (inSplit.length >= 1) {
info.setIdentifyNuclideSet(Arrays.stream(inSplit).map(f -> {
if(f.toLowerCase().contains("xe")){
return f.replace("M", "m");
}
return f;
}).collect(Collectors.toSet()));
}
}
judge(info, nuclidesCross);
}
}
@ -172,37 +156,27 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
String betaOrGamma = info.getBetaOrGamma();
String datasource = info.getDatasource();
String stationId = info.getStationId();
String stationCode="";
HashMap<String, Object> stationMap = (HashMap<String, Object>)redisUtil.get(RedisConstant.STATION_CODE_MAP);
String sampleId = info.getSampleId();
String sampleName = info.getSampleName();
Set<String> identifyNuclideSet = info.getIdentifyNuclideSet();
// 获取谱文件采样日期 如果为null 则默认为LocalDate.now()
LocalDate collDate = ObjectUtil.isNull(info.getCollectionDate()) ? LocalDate.now() :
info.getCollectionDate().toLocalDate();
List<String> conditions = ListUtil.toList(conditionStr.split(COMMA));
List<NuclideInfo> firstDetected = new ArrayList<>(); // 首次发现
List<String> firstDetected = new ArrayList<>(); // 首次发现
List<NuclideInfo> moreThanAvg = new ArrayList<>(); // 超浓度均值
List<NuclideInfo> meanWhile = new ArrayList<>(); // 同时出现两种及以上核素
Map<String, NuclideInfo> nuclideInfoMap = Maps.newHashMap();
List<NuclideInfo> identifyNuclideResult = new ArrayList<>();
List<String> meanwhile = new ArrayList<>(); // 同时出现两种及以上核素
for (String con : conditions) {
Condition condition = Condition.valueOf1(con);
if (ObjectUtil.isNull(condition)) continue;
switch (condition){
case FIRST_FOUND: // 首次发现该元素
firstDetected = this.firstDetected(betaOrGamma, datasource, stationId, sampleId, nuclidesCross);
firstDetected = firstDetected(betaOrGamma, datasource, nuclideNames);
break;
case ABOVE_AVERAGE: // 元素浓度高于均值
moreThanAvg = this.moreThanAvg(datasource, stationId, collDate, nuclidesCross);
moreThanAvg = moreThanAvg(datasource, stationId, collDate, nuclidesCross);
break;
case MEANWHILE: // 同时出现两种及以上核素
meanWhile = this.meanWhile(betaOrGamma, datasource, sampleId, nuclidesCross);
if (meanWhile.size() < 2) meanWhile = ListUtil.empty();
break;
case IDENTIFY_NUCLIDES: // 识别到某个核素
identifyNuclideResult = this.meanWhile(info.getNuclides(), datasource, identifyNuclideSet);
if (CollUtil.isNotEmpty(nuclideNames) && nuclideNames.size() >= 2)
meanwhile.addAll(nuclideNames);
break;
default:
break;
@ -210,54 +184,19 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
}
// 构建预警信息
DataTool dataTool = DataTool.getInstance();
if (CollUtil.isNotEmpty(firstDetected)) {
String above = firstDetected.stream()
.map(NuclideInfo::getNuclide)
.collect(Collectors.joining(StrUtil.COMMA + StrUtil.SPACE));
dataTool.put("firstDetected", above);
for (NuclideInfo nuclideInfo : firstDetected) {
nuclideInfoMap.put(nuclideInfo.getNuclide(), nuclideInfo);
}
}
if (CollUtil.isNotEmpty(meanWhile)){
String above = meanWhile.stream()
.map(NuclideInfo::getNuclide)
.collect(Collectors.joining(StrUtil.COMMA + StrUtil.SPACE));
dataTool.put("meanwhile", above);
for (NuclideInfo nuclideInfo : meanWhile) {
nuclideInfoMap.put(nuclideInfo.getNuclide(), nuclideInfo);
}
}
if (CollUtil.isNotEmpty(identifyNuclideResult)){
String above = identifyNuclideResult.stream()
.map(NuclideInfo::getNuclide)
.collect(Collectors.joining(StrUtil.COMMA + StrUtil.SPACE));
dataTool.put("identifyNuclide", above);
for (NuclideInfo nuclideInfo : identifyNuclideResult) {
nuclideInfoMap.put(nuclideInfo.getNuclide(), nuclideInfo);
}
}
if (CollUtil.isNotEmpty(firstDetected))
dataTool.put("firstDetected", CollUtil.join(firstDetected, StrUtil.COMMA + StrUtil.SPACE));
if (CollUtil.isNotEmpty(moreThanAvg)){
String above = moreThanAvg.stream()
.map(item -> item.getNuclide() + "(" + item.getValue() + ")" + " > " + item.getThreshold())
.collect(Collectors.joining(StrUtil.COMMA + StrUtil.SPACE));
dataTool.put("moreThanAvg", above);
for (NuclideInfo nuclideInfo : moreThanAvg) {
nuclideInfoMap.put(nuclideInfo.getNuclide(), nuclideInfo);
}
}
if (CollUtil.isNotEmpty(meanwhile))
dataTool.put("meanwhile", CollUtil.join(meanwhile, StrUtil.COMMA + StrUtil.SPACE));
// 如果报警数据为空 则不需要发送报警信息和生成报警日志
if (MapUtil.isEmpty(dataTool.get())) return;
// 产生报警信息的Sample信息
if (CollUtil.isNotEmpty(stationMap))
{
stationCode=stationMap.get(stationId).toString();
}
dataTool.put("sampleId", sampleId).put("sampleName", sampleName);
DataTool titleData = DataTool.getInstance();
titleData.put("stationCode",stationCode);
// 构建预警信息实例 准备发送预警信息,20250327--修改模版
MessageDTO messageDTO = TemplateUtil.parse1(ANALYSIS_NUCLIDE.getCode(), dataTool.get(),titleData.get());
MessageDTO messageDTO = TemplateUtil.parse1(ANALYSIS_NUCLIDE.getCode(), dataTool.get());
// 保存报警日志
AlarmAnalysisLog logInfo = new AlarmAnalysisLog();
BeanUtil.copyProperties(info, logInfo);
@ -265,13 +204,8 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
if (ObjectUtil.isNotNull(sampleType))
logInfo.setSampleType(sampleType.getValue());
logInfo.setAlarmInfo(messageDTO.getContent());
// 报警信息中核素列表
if (MapUtil.isNotEmpty(nuclideInfoMap)) {
List<NuclideInfo> nuclideInfoList = Lists.newArrayList();
nuclideInfoMap.forEach((key, value) -> nuclideInfoList.add(nuclideInfoMap.get(key)));
logInfo.setNuclideInfoList(nuclideInfoList);
}
if (CollUtil.isNotEmpty(moreThanAvg))
logInfo.setNuclideInfoList(moreThanAvg);
logService.saveLog(logInfo);
// 发送报警信息
String groupId = info.getGroupId();
@ -282,32 +216,13 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
/**
* 首次发现该核素
*/
private List<NuclideInfo> firstDetected(String betaOrGamma, String dataSourceType,
String stationId, String sampleId, Map<String,String> nuclidesCross){
List<NuclideInfo> result = Lists.newArrayList();
/* 查询用户关注的核素是否存在 如果不存在则为首次发现该核素
判断核素是否存在的条件: 该核素的Conc值是否大于MDC值
*/
String detectorId = systemClient.getDetectorId(sampleId);
if (StrUtil.isBlank(detectorId)) {
throw new RuntimeException("detectorId is null or empty");
}
Set<String> nuclideNames = nuclidesCross.keySet();
List<String> list = analysisResultService.nuclideFirst(betaOrGamma, dataSourceType, stationId,
detectorId, sampleId, nuclideNames);
if(CollUtil.isNotEmpty(list)){
for (Map.Entry<String, String> f : nuclidesCross.entrySet()) {
if(list.contains(f.getKey())){
NuclideInfo nuclideInfo = new NuclideInfo();
nuclideInfo.setNuclide(f.getKey());
nuclideInfo.setDatasource(DSType.typeOf(dataSourceType));
// 对浓度值保留五位小数
nuclideInfo.setValue(NumUtil.keepStr(f.getValue(), 5));
result.add(nuclideInfo);
}
}
}
return result;
private List<String> firstDetected(String betaOrGamma,
String dataSourceType,
Set<String> nuclideNames){
List<String> existNames = analysisResultService
.nuclideNames(betaOrGamma, dataSourceType, nuclideNames);
// 两个集合元素相减
return CollUtil.subtractToList(nuclideNames, existNames);
}
/**
@ -325,6 +240,8 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
String nuclideName = nuclide.getKey();
String concValue = nuclide.getValue();// 浓度值
String avgValue = nuclideAvgs.get(nuclideName);// 浓度均值
if (StrUtil.isBlank(concValue) || StrUtil.isBlank(avgValue))
continue;
if (!NumberUtil.isNumber(concValue) || !NumberUtil.isNumber(avgValue))
continue;
BigDecimal conc = new BigDecimal(concValue);
@ -343,52 +260,6 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
return nuclideInfos;
}
/*
* 是否同时存在两种及以上核素
* */
private List<NuclideInfo> meanWhile(String betaOrGamma, String dataSourceType,
String sampleId, Map<String,String> nuclidesCross){
List<NuclideInfo> result = Lists.newArrayList();
/* 查询用户关注的核素中 该谱中是否存在两种及以上核素
判断核素是否存在的条件: 该核素的Conc值是否大于MDC值
*/
Set<String> nuclideNames = nuclidesCross.keySet();
List<String> list = analysisResultService.nuclideExist(betaOrGamma, dataSourceType, sampleId, nuclideNames);
if(CollUtil.isNotEmpty(list)){
for (Map.Entry<String, String> f : nuclidesCross.entrySet()) {
if(list.contains(f.getKey())){
NuclideInfo nuclideInfo = new NuclideInfo();
nuclideInfo.setNuclide(f.getKey());
nuclideInfo.setDatasource(DSType.typeOf(dataSourceType));
// 对浓度值保留五位小数
nuclideInfo.setValue(NumUtil.keepStr(f.getValue(), 5));
result.add(nuclideInfo);
}
}
}
return result;
}
/*
* 是否同时存在两种及以上核素
* */
private List<NuclideInfo> meanWhile(Map<String,String> nuclideMap, String dataSourceType, Set<String> nuclideNames){
List<NuclideInfo> result = Lists.newArrayList();
/* 查询用户关注的核素中 该谱中是否存在两种及以上核素
判断核素是否存在的条件: 该核素的Conc值是否大于MDC值
*/
for (String name : nuclideNames) {
if(nuclideMap.containsKey(name)){
NuclideInfo nuclideInfo = new NuclideInfo();
nuclideInfo.setNuclide(name);
nuclideInfo.setDatasource(DSType.typeOf(dataSourceType));
// 对浓度值保留五位小数
nuclideInfo.setValue(NumUtil.keepStr(nuclideMap.get(name), 5));
result.add(nuclideInfo);
}
}
return result;
}
private void init() {
// start 生成临时Token到线程中
UserTokenContext.setToken(getTempToken());
@ -398,7 +269,6 @@ public class AnalysisConsumer implements StreamListener<String, ObjectRecord<Str
ruleService = SpringContextUtils.getBean(IAlarmAnalysisRuleService.class);
analysisResultService = SpringContextUtils.getBean(AnalysisResultService.class);
nuclideAvgService = SpringContextUtils.getBean(IAlarmAnalysisNuclideAvgService.class);
redisUtil = SpringContextUtils.getBean(RedisUtil.class);
}
private void destroy(){

View File

@ -5,10 +5,7 @@ import java.util.Set;
public interface AnalysisResultService {
List<String> nuclideExist(String betaOrGamma, String dataSourceType,
String sampleId, Set<String> nuclideNames);
List<String> nuclideFirst(String betaOrGamma, String dataSourceType,
String stationId, String detectorId,
String sampleId, Set<String> nuclideNames);
List<String> nuclideNames(String betaOrGamma,
String dataSourceType,
Set<String> nuclideNames);
}

View File

@ -2,6 +2,7 @@ package org.jeecg.modules.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.ConcDtoXe;
import org.jeecg.modules.base.entity.rnauto.GardsNuclIded;
import java.util.List;
@ -12,8 +13,5 @@ public interface IGardsNuclIdedAutoService extends IService<GardsNuclIded> {
List<ConcDto> getConc(Map<String,Object> params);
List<String> nuclideExist(String sampleId, Set<String> nuclideNames);
List<String> nuclideFirst(String stationId, String detectorId,
String sampleId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -10,10 +10,7 @@ import java.util.Set;
public interface IGardsNuclIdedManService extends IService<GardsNuclIded> {
List<ConcDto> getConc(Map<String, Object> params);
List<ConcDto> getConc(Map<String,Object> params);
List<String> nuclideExist(String sampleId, Set<String> nuclideNames);
List<String> nuclideFirst(String stationId, String detectorId,
String sampleId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.ConcDtoXe;
import org.jeecg.modules.base.entity.rnauto.GardsXeResults;
@ -12,8 +13,5 @@ public interface IGardsXeResultsAutoService extends IService<GardsXeResults> {
List<ConcDtoXe> getConc(Map<String,Object> params, Set<String> nuclides);
List<String> nuclideExist(String sampleId, Set<String> nuclideNames);
List<String> nuclideFirst(String stationId, String detectorId,
String sampleId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.dto.ConcDto;
import org.jeecg.modules.base.dto.ConcDtoXe;
import org.jeecg.modules.base.entity.rnman.GardsXeResults;
@ -12,8 +13,5 @@ public interface IGardsXeResultsManService extends IService<GardsXeResults> {
List<ConcDtoXe> getConc(Map<String,Object> params, Set<String> nuclides);
List<String> nuclideExist(String sampleId, Set<String> nuclideNames);
List<String> nuclideFirst(String stationId, String detectorId,
String sampleId, Set<String> nuclideNames);
List<String> nuclideNames(Set<String> nuclideNames);
}

View File

@ -3,45 +3,17 @@ package org.jeecg.modules.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.base.entity.postgre.SysEmailLog;
import org.jeecg.modules.entity.DailyEmailChartDataVO;
import org.jeecg.modules.entity.EmailChartDataVO;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public interface ISysEmailLogService extends IService<SysEmailLog> {
Result<?> totalEmail(String emailId);
Map<String, Object> space(String emailId);
Map<String,Object> space(String emailId);
/**
* 获取当天的告警数据
* @param emailId
* @return
*/
Map<String, Long> todayHour(String emailId);
Result<?> todayHour(String emailId);
Result<?> todayMin(String emailId);
Result<?> analysis(String emailId, String startDate, String endDate);
Integer getMinus(String emailId);
/**
* 获取最近的邮件信息
* @param emailId 邮箱ID
* @return EmailChartDataVO
*/
EmailChartDataVO getDashboardHourlyStats(String emailId);
/**
* 获取一个月的邮件信息
* @param emailId 邮箱ID
* @param startDate 开始时间
* @param endDate 结束时间
* @return DailyEmailChartDataVO
*/
DailyEmailChartDataVO getDashboardDailyStats(String emailId, LocalDate startDate, LocalDate endDate);
}

View File

@ -135,9 +135,6 @@ public class AlarmAnalysisRuleServiceImpl extends ServiceImpl<AlarmAnalysisRuleM
@Override
public Result add(AlarmAnalysisRule alarmAnalysisRule) {
String name = alarmAnalysisRule.getName();
if (null != alarmAnalysisRule.getIdentifyNuclides()) {
alarmAnalysisRule.setConditions(alarmAnalysisRule.getConditions() + ",4");
}
if (ObjectUtil.isNotNull(getByName(name)))
return Result.error("Rule Name" + Prompt.NOT_REPEAT);
boolean success = save(alarmAnalysisRule);
@ -153,11 +150,6 @@ public class AlarmAnalysisRuleServiceImpl extends ServiceImpl<AlarmAnalysisRuleM
String id = alarmAnalysisRule.getId();
String name = alarmAnalysisRule.getName();
String original = getById(id).getName();
if (null != alarmAnalysisRule.getIdentifyNuclides() && !alarmAnalysisRule.getConditions().contains("4")) {
alarmAnalysisRule.setConditions(alarmAnalysisRule.getConditions() + ",4");
} else if(null == alarmAnalysisRule.getIdentifyNuclides() && alarmAnalysisRule.getConditions().contains("4")) {
alarmAnalysisRule.setConditions(alarmAnalysisRule.getConditions().replace("4", ""));
}
if (!StrUtil.equalsIgnoreCase(name,original)){
if (ObjectUtil.isNotNull(getByName(name)))
return Result.error("Rule Name" + Prompt.NOT_REPEAT);
@ -191,30 +183,6 @@ public class AlarmAnalysisRuleServiceImpl extends ServiceImpl<AlarmAnalysisRuleM
List<String> conditionChecked = ListUtil
.toList(analysisRule.getConditions().split(comma));
analysisRuleInfo.setConditionChecked(conditionChecked);
if (null != analysisRule.getColTime()) {
List<String> colTimes = ListUtil
.toList(analysisRule.getColTime().split(comma));
analysisRuleInfo.setColTime(colTimes);
}
if (null != analysisRule.getAcqTime()) {
List<String> acqTimes = ListUtil
.toList(analysisRule.getAcqTime().split(comma));
analysisRuleInfo.setAcqTime(acqTimes);
}
if (null != analysisRule.getXe133MDC()) {
List<String> xe133MDC = ListUtil
.toList(analysisRule.getXe133MDC().split(comma));
analysisRuleInfo.setXe133MDC(xe133MDC);
}
if (null != analysisRule.getIdentifyNuclides()) {
List<String> inList = ListUtil
.toList(analysisRule.getIdentifyNuclides().split(comma));
analysisRuleInfo.setIdentifyNuclidesChecked(inList);
}
return Result.OK(analysisRuleInfo);
}

Some files were not shown because too many files have changed in this diff Show More