JRT1.6发布

经过51的三天努力,完成基于JRT的质控核心部分。框架部分已经达到了第一个可生产版本。

可生产包括以下部分:
1.Web开发基础和发布运维基础
2.Linux和WIndows客户端浏览器
3.Linux和WIndows客户端打印导出程序
4.Linux和WIndows初始化程序
5.Linux和WIndows仪器接口程序
6.打印模板设计器
7.菜单权限基础
8.文件服务
9.核心质控验证程序

能够实现的效果有:
模板设计
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

质控图在线打印预览
在这里插入图片描述
质控图打印预览
在这里插入图片描述
质控图打印
在这里插入图片描述
质控月报的横纵向预览和打印
在这里插入图片描述

在这里插入图片描述

质控月报复杂的Excel模板导出
在这里插入图片描述

在这里插入图片描述

环境下载
在这里插入图片描述

码表
在这里插入图片描述
开发和运维调试端
在这里插入图片描述

在这里插入图片描述
jrt运维命令
在这里插入图片描述
代码生成器和SQL执行器
在这里插入图片描述

以前业务脚本基本上是孤岛,提供新api加强业务脚本之间的联系
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

基本涵盖开发业务系统需要的方方面面,始终坚持业务脚本化、环境简单化、开发高效化的理念。开发基于IRIS数据库,开发完成后然后用M一键生成PostGreSql和人大金仓构造库的SQL脚本用网站执行来在PostGreSql和人大金仓上构建数据库。业务因为不写SQL语句,所有迁移数据库不需要改动任何一行业务代码,为了实现真正的多数据库支持(而不是口号),ORM只支持基础数据类型、不允许使用Datetime类似、比特类型,就没有数据库差异性问题,所以理论是支持所有JDBC的数据库而不需要改业务代码的。

选择质控来验证架构,一是因为质控独立性好,二是质控无论是表关系还是业务复杂性都够了,三是质控的打印足够复杂,既有JS绘图部分,也有表格部分,多方糅合,比较考验基础层。四是质控规则判断和月报数据计算足够复杂来验证框架的可靠性。五是质控我熟,可以很快实现。整体开发下来开发效率比M高很多、执行效率和M不差什么、可以媲美一下Cache的效率了。有了DolerGet之后,关系库在多维业务处理上也不在是那么弱鸡的存在了,最难突破的是思想,有一年多的时间我也觉得关系库永远实现不到我用Cache也业务的效果。

质控图查询与规则判断的核心代码:

import JRT.Core.Dto.HashParam;
import JRT.Core.Dto.OutValue;
import JRT.Core.Util.Convert;
import JRT.Core.Util.TimeParser;
import JRT.Model.Bussiness.Parameters;
import JRT.Model.Entity.*;
import JRTBLLBase.BaseHttpHandler;
import JRTBLLBase.Helper;import java.util.*;/*** 画质控图公共查询逻辑,所有的质控图都通过虚拟M调过来,该类实现规则判断、对接月报累计值计算等等*/
public class QCDrawCommon extends BaseHttpHandler {/*** 质控绘图公共查数据* @param Param* @param Session* @param Output* @return* @throws Exception*/public String QueryQcDrawData(Parameters Param, OutValue Session, OutValue Output) throws Exception {int StartDate= Helper.ValidParam(Param.P0,0);int EndDate=Helper.ValidParam(Param.P1,0);int MachineParameterDR= Convert.ToInt32(Param.P2);int TestCodeDR=Convert.ToInt32(Param.P3);String Level=Param.P4;String QcRule=Param.P5;String PointRange=Param.P6;String MaterialDR=Param.P7;String UseFL=Param.P8;String LotNo=Param.P9;HashParam hs=new HashParam();hs.Add("MachineParameterDR",MachineParameterDR);hs.Add("TestCodeDR",TestCodeDR);List<String> operater=new ArrayList<>();operater.add("=");operater.add("=");hs.Add("TestDate",StartDate);hs.Add("TestDate",EndDate);operater.add(">=");operater.add("<=");//质控物浓度映射HashMap<Integer,BTQCMaterialLevel> matLevMap=new HashMap<>();//存计算的月报数据HashMap<String,HashMap> calMonthData=new HashMap<>();//筛选质控物if(!MaterialDR.isEmpty()){int MaterialDRInt=Convert.ToInt32(MaterialDR);hs.Add("MaterialDR",MaterialDRInt);//质控浓度List<BTQCMaterialLevel> levList=EntityManager().FindByColVal(BTQCMaterialLevel.class,"MaterialDR",Convert.ToInt32(MaterialDR));if(levList!=null&&levList.size()>0){for(BTQCMaterialLevel lev:levList){matLevMap.put(lev.LevelNo,lev);//计算质控规则CalQCRule(StartDate,EndDate,MaterialDRInt,TestCodeDR,lev.LevelNo,PointRange,"");//得到月报的计算数据List<HashMap> monthData=(List<HashMap>)Helper.GetBllMethodData("qc.ashx.ashQCDataCalMonth","CalOneMonthData",StartDate,EndDate,MaterialDRInt,TestCodeDR,lev.LevelNo,PointRange,true);if(monthData!=null&&monthData.size()>0){//按计算键把月报数据存起来for(HashMap one:monthData){String calKey=one.get("CalKey").toString();calMonthData.put(calKey,one);}}}}}//浓度筛选图HashMap levMap=Helper.GetSplitMap(Level,",");//查询仪器、项目、日期范围的所有质控数据List<QCTestResultDto> allData=EntityManager().FindAllSimple(QCTestResultDto.class,hs,"LevelNo asc,TestDate asc,TestTime asc",-1,null,operater);//存处理后的数据List<QCTestResultDto> dealedData=new ArrayList<>();//1:所有质控点 2:去除排除点 6:所有在控点 11:去除平行点 12:仅平行点 4:去除复查点 10:只查最后一点//7:最好点连线 8:最后一点连线 9:只查最好点//辅助判断复查点HashMap redoMap=new HashMap();//最好点的图HashMap<String,QCTestResultDto> bestMap=new HashMap();HashMap<Integer, Boolean> bestRowIDMap=new HashMap();//最后点的图HashMap<String,QCTestResultDto> lastMap=new HashMap();HashMap<Integer, Boolean> lastRowIDMap=new HashMap();//按点类型筛选数据dealedData=FilterDataByPointType(allData,levMap,matLevMap,PointRange);//补全计算值和累计值if(dealedData!=null&&dealedData.size()>0){for(QCTestResultDto one:dealedData){//排除颜色if(one.ExcludeType.equals("2")){one.CurRuleColour="#549cc7";}//平行质控颜色if(one.IsParallel!=null&&one.IsParallel==true){one.CurRuleColour="#8A2BE2";}//计算的键,相同的键算一批String calKey=one.LotNo;//没维护批号的按靶值和SD相同的算if(calKey.isEmpty()){calKey=one.TCX+"-"+one.TCSD;}calKey=one.MaterialDR+"-"+one.TestCodeDR+"-"+one.LevelNo+"-"+calKey;//放入月报计算数据if(calMonthData.containsKey(calKey)){HashMap oneMonthData=calMonthData.get(calKey);one.CalX=oneMonthData.get("CalMean").toString();one.CalSD=oneMonthData.get("CalSD").toString();one.CalCV=oneMonthData.get("CalCV").toString();one.AccMean=oneMonthData.get("AccMean").toString();one.AccSD=oneMonthData.get("AccSD").toString();one.AccCV=oneMonthData.get("AccCV").toString();}}}return Helper.Object2Json(dealedData);}/*** 计算质控规则* @param startDate 开始日期* @param endDate 结束日期* @param materialDR 质控物* @param testCodeDR 项目浓度* @param levelNo 浓度* @param fPointType 点类型* @param useFL 是否使用浮动* @throws Exception*/public void CalQCRule(int startDate,int endDate,int materialDR, int testCodeDR, int levelNo, String fPointType,String useFL) throws Exception{//从前12天数据开始查询,最大到12x规则int qryStartDate=Helper.AddDays(startDate,-12);HashParam hs=new HashParam();hs.Add("MaterialDR",materialDR);hs.Add("TestCodeDR",testCodeDR);hs.Add("LevelNo",levelNo);hs.Add("TestDate",qryStartDate);hs.Add("TestDate",endDate);List<String> operater=new ArrayList<>();operater.add("=");operater.add("=");operater.add("=");operater.add(">");operater.add("<=");//查询结果List<QCTestResultDto> resList=EntityManager().FindAllSimple(QCTestResultDto.class,hs,"TestDate asc,TestTime asc",-1,null,operater);//质控使用的规则List<BTQCRules> useRules=new ArrayList<>();//项目单独维护的规则List<BTQCMaterialTCRules> tcRules=EntityManager().FindByColVal(BTQCMaterialTCRules.class,"MaterialDR",materialDR);//有项目规则就用项目的规则if(tcRules!=null&&tcRules.size()>0){for(BTQCMaterialTCRules one:tcRules){BTQCRules rule=EntityManager().DolerGet(BTQCRules.class,one.QCRulesDR);useRules.add(rule);}}//否则用质控物上的规则else{List<BTQCMaterialRules> rules=EntityManager().FindByColVal(BTQCMaterialRules.class,"MaterialDR",materialDR);if(rules!=null&&rules.size()>0){for(BTQCMaterialRules one:rules){BTQCRules rule=EntityManager().DolerGet(BTQCRules.class,one.QCRulesDR);useRules.add(rule);}}}//按序号排序规则useRules.sort(new Comparator<BTQCRules>() {@Overridepublic int compare(BTQCRules p1, BTQCRules p2) {return p1.Sequence - p2.Sequence;}});//判断规则if(resList!=null&&resList.size()>0&&useRules!=null&&useRules.size()>0){List<String> upCol=new ArrayList<>();upCol.add("QCRulesDR");upCol.add("DQIV_Status");upCol.add("ResColor");//计算方差SD,每个点偏离靶值的SD倍数先计算好CalDeviationSD(resList);//延迟更新HashMap<Integer,QCTestResultDto> lazyUpdataMap=new HashMap<>();//遍历检查每个结果for(int i=0;i<resList.size();i++){QCTestResultDto res=resList.get(i);//是否更新了质控规则,没更新的最后如果有规则就清空boolean hasUpdateRule=false;//遍历判断每个规则for(BTQCRules rule:useRules){//判断1-1S########################################一个质控测定值超过X±1S质控限。if(rule.Code.equals("Y")){int numPos=CheckSameSide(resList,i,1,1.0,true);int numNeg=CheckSameSide(resList,i,1,-1.0,false);if(numPos+numNeg>0){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}//判断1-2S########################################一个质控测定值超过X±2S质控限。else if(rule.Code.equals("A")){int numPos=CheckSameSide(resList,i,1,2.0,true);int numNeg=CheckSameSide(resList,i,1,-2.0,false);if(numPos+numNeg>0){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}//判断1-3S########################################一个质控测定值超过X±3S质控限。else if(rule.Code.equals("B")){int numPos=CheckSameSide(resList,i,1,3.0,true);int numNeg=CheckSameSide(resList,i,1,-3.0,false);if(numPos+numNeg>0){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}//判断2-2S########################################两个连续的质控测定值同时超过X-2S或同时超过X+2S质控限,或同一天不同水平超过±2S,都要求同侧.else if(rule.Code.equals("C")){int numPos=CheckSameSide(resList,i,2,2.0,true);int numNeg=CheckSameSide(resList,i,2,-2.0,false);//两个连续的质控测定值同时超过X-2S或X+2S质控限if(numPos==2||numNeg==2){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}else if(numPos==1||numNeg==1){List<QCTestResultDto> otherRes=GetOtherLevRes(res);if(otherRes!=null&&otherRes.size()>0) {//正向检查其他浓度if(numPos==1){int otNum=otherRes.size();int numPosOT=CheckSameSide(otherRes,otNum-1,otNum,2.0,true);if(numPosOT>=1){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}//反向检查其他浓度else if(numNeg==1){int otNum=otherRes.size();int numNegOT=CheckSameSide(otherRes,otNum-1,otNum,-2.0,false);if(numNegOT>=1){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}}}}//判断R-4S########################################同批连续质控点一个超过+2S,一个超过-2S,或者同一天不同浓度的超过±2S。要求不同侧else if(rule.Code.equals("R")){int numPos=CheckSameSide(resList,i,2,2.0,true);int numNeg=CheckSameSide(resList,i,2,-2.0,false);//同批连续质控点一个超过+2S,一个超过-2Sif(numPos==1&&numNeg==1){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}//或者同一天不同浓度的超过±2Selse{List<QCTestResultDto> otherRes=GetOtherLevRes(res);if(otherRes!=null&&otherRes.size()>0) {//正向检查其他浓度if(numPos==1){int otNum=otherRes.size();int numNegOT=CheckSameSide(otherRes,otNum-1,otNum,-2.0,false);if(numNegOT>=1){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}//反向检查其他浓度else if(numNeg==1){int otNum=otherRes.size();int numPosOT=CheckSameSide(otherRes,otNum-1,otNum,2.0,true);if(numPosOT>=1){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}}}}//判断R4S_########################################两个连续的测定值之差超过4S。else if(rule.Code.equals("T")){if(i>0){Double preOffset=resList.get(i-1).Offset;Double curOffset=resList.get(i).Offset;Double calDV=Math.abs(preOffset-curOffset);if(calDV>4){hasUpdateRule=true;//更新质控规则UpdateRule(res,rule,lazyUpdataMap);//终止判断if(rule.IsEnd==true){break;}}}}//判断4-1S########################################四个连续的质控测定值同时超过X-1S或X+1S。(同侧)else if(rule.Code.equals("E")){int numPos=CheckSameSide(resList,i,4,1.0,true);int numNeg=CheckSameSide(resList,i,4,-1.0,false);//四个点大于1s或-1sif(numPos==4||numNeg==4){int numPos2S=CheckSameSide(resList,i,4,2.0,true);int numNeg2S=CheckSameSide(resList,i,4,-2.0,false);//有一个点大于1-2Sif(numPos2S>1||numNeg2S>1) {hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//判断3-1S########################################三个连续的质控测定值同时超过X-1S或X+1S。else if(rule.Code.equals("D")){int numPos=CheckSameSide(resList,i,3,1.0,true);int numNeg=CheckSameSide(resList,i,3,-1.0,false);//三个点大于1s或-1sif(numPos==3||numNeg==3){int numPos2S=CheckSameSide(resList,i,3,2.0,true);int numNeg2S=CheckSameSide(resList,i,3,-2.0,false);//有一个点大于1-2Sif(numPos2S>1||numNeg2S>1) {hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//判断10X########################################十个连续的质控测定值落在靶值(X)的同一侧。1-2S触发else if(rule.Code.equals("G")){int numPos=CheckSameSide(resList,i,10,0.0,true);int numNeg=CheckSameSide(resList,i,10,0.0,false);//十个连续的质控测定值落在靶值(X)的同一侧if(numPos==10||numNeg==10){int numPos2S=CheckSameSide(resList,i,10,2.0,true);int numNeg2S=CheckSameSide(resList,i,10,-2.0,false);//有一个点大于1-2Sif(numPos2S>1||numNeg2S>1) {hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//判断5X########################################五个连续的质控测定值落在靶值(X)的同一侧。1-2S触发else if(rule.Code.equals("F")){int numPos=CheckSameSide(resList,i,5,0.0,true);int numNeg=CheckSameSide(resList,i,5,0.0,false);//5个连续的质控测定值落在靶值(X)的同一侧if(numPos==5||numNeg==5){int numPos2S=CheckSameSide(resList,i,5,2.0,true);int numNeg2S=CheckSameSide(resList,i,5,-2.0,false);//有一个点大于1-2Sif(numPos2S>1||numNeg2S>1) {hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//判判断8X########################################八个连续的质控测定值落在靶值(X)的同一侧。1-2S触发else if(rule.Code.equals("Q")){int numPos=CheckSameSide(resList,i,8,0.0,true);int numNeg=CheckSameSide(resList,i,8,0.0,false);//8个连续的质控测定值落在靶值(X)的同一侧if(numPos==8||numNeg==8){int numPos2S=CheckSameSide(resList,i,8,2.0,true);int numNeg2S=CheckSameSide(resList,i,8,-2.0,false);//有一个点大于1-2Sif(numPos2S>1||numNeg2S>1) {hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//判断12X########################################十二个连续的质控测定值落在靶值(X)的同一侧。1-2S触发else if(rule.Code.equals("S")){int numPos=CheckSameSide(resList,i,12,0.0,true);int numNeg=CheckSameSide(resList,i,12,0.0,false);//十个连续的质控测定值落在靶值(X)的同一侧if(numPos==12||numNeg==12){int numPos2S=CheckSameSide(resList,i,12,2.0,true);int numNeg2S=CheckSameSide(resList,i,12,-2.0,false);//有一个点大于1-2Sif(numPos2S>1||numNeg2S>1) {hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//判断7T########################################七个连续的质控测定值呈现出向上或向下的趋势else if(rule.Code.equals("P")){int numPos=CheckTrend(resList,i,7,true);int numNeg=CheckTrend(resList,i,7,false);//十个连续的质控测定值落在靶值(X)的同一侧if(numPos==7||numNeg==7){hasUpdateRule = true;//更新质控规则UpdateRule(res, rule, lazyUpdataMap);//终止判断if (rule.IsEnd == true) {break;}}}}//没有更新规则的,如果数据里面有规则就清空if(hasUpdateRule==false&&res.QCRulesDR!=null){UpdateRule(res,null,lazyUpdataMap);}}Iterator<HashMap.Entry<Integer, QCTestResultDto>> iterator = lazyUpdataMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<Integer, QCTestResultDto> entry = iterator.next();QCTestResultDto cur=entry.getValue();//变化了才更新if(cur.NewRuleDR!=cur.QCRulesDR) {cur.QCRulesDR=cur.NewRuleDR;cur.DQIV_Status=cur.NewRuleStatus;if(cur.NewRuleDR==null){cur.ResColor="";}int ret = EntityManager().Update(cur, upCol);}}}}/*** 查找当天其他浓度的数据* @param res 当前结果* @return 当前结果时间之前的其他浓度结果*/private List<QCTestResultDto> GetOtherLevRes(QCTestResultDto res) throws Exception{HashParam hs=new HashParam();hs.Add("MaterialDR",res.MaterialDR);hs.Add("TestCodeDR",res.TestCodeDR);hs.Add("TestDate",res.TestDate);hs.Add("TestTime",res.TestTime);List<String> operater=new ArrayList<>();operater.add("=");operater.add("=");operater.add("=");operater.add("<=");List<QCTestResultDto> resList=EntityManager().FindAllSimple(QCTestResultDto.class,hs,"TestTime asc",-1,null,operater);List<QCTestResultDto> retList=new ArrayList<>();if(resList!=null&&resList.size()>0){for(QCTestResultDto one:resList){if(one.LevelNo==res.LevelNo){continue;}QCResMaterialTestCode para=EntityManager().DolerGet(QCResMaterialTestCode.class,one.ResMaterialTestCodeDR);one.RunPara=para;if(para.SD!=0) {one.Offset = (Convert.ToDouble(res.Result) - para.Mean) / para.SD;}else{one.Offset=0.0;}retList.add(one);}}return retList;}/*** 更新质控规则* @param res 结果* @param rule 规则* @param lazyMap 延迟更新* @throws Exception*/private void UpdateRule(QCTestResultDto res,BTQCRules rule,HashMap<Integer,QCTestResultDto> lazyMap) throws Exception{if(rule==null){res.NewRuleDR=null;res.NewRuleStatus="";lazyMap.put(res.RowID,res);}else{res.NewRuleDR = rule.RowID;res.NewRuleStatus = rule.Status;lazyMap.put(res.RowID,res);}}/*** 检测向上和向下趋势* @param resList* @param start* @param checkNum* @param isPos* @return*/public int CheckTrend(List<QCTestResultDto> resList,int start,int checkNum,boolean isPos){int retNum=0;Double preOffset=null;//检测数据for(int i=start;i>=0;i--){QCTestResultDto res=resList.get(i);checkNum--;if(preOffset!=null){//连续向下if(isPos==true){if(preOffset<res.Offset){retNum++;}else{break;}}//连续向下else{if(preOffset>res.Offset){retNum++;}else{break;}}}//检测数量if(checkNum==0){break;}}return retNum;}/*** 检测在一侧的点数* @param resList 所有结果* @param start 开始位置* @param checkNum 往前找的数量* @param sd sd值* @param isPos 是否正向* @return*/public int CheckSameSide(List<QCTestResultDto> resList,int start,int checkNum,Double sd,boolean isPos){int retNum=0;//检测数据for(int i=start;i>=0;i--){QCTestResultDto res=resList.get(i);checkNum--;if(isPos==true&&res.Offset>sd){retNum++;}else if(isPos==false&&res.Offset<sd){retNum++;}//检测数量if(checkNum==0){break;}}return retNum;}/*** 计算每个点的偏差SD* @param resList 结果集合*/public void CalDeviationSD(List<QCTestResultDto> resList) throws Exception{for(QCTestResultDto res:resList){//获得参数QCResMaterialTestCode para=EntityManager().DolerGet(QCResMaterialTestCode.class,res.ResMaterialTestCodeDR);res.RunPara=para;if(para.SD!=0) {res.Offset = (Convert.ToDouble(res.Result) - para.Mean) / para.SD;}else{res.Offset=0.0;}}}/*** 按点类型筛选数据* @param allData 所有数据* @param levMap 浓度* @param matLevMap 质控物浓度* @param pointRange 点类型* @return* @throws Exception*/public List<QCTestResultDto>  FilterDataByPointType(List<QCTestResultDto> allData,HashMap levMap,HashMap<Integer,BTQCMaterialLevel> matLevMap,String pointRange) throws Exception{//存处理后的数据List<QCTestResultDto> dealedData=new ArrayList<>();//1:所有质控点 2:去除排除点 6:所有在控点 11:去除平行点 12:仅平行点 4:去除复查点 10:只查最后一点//7:最好点连线 8:最后一点连线 9:只查最好点//辅助判断复查点HashMap redoMap=new HashMap();//最好点的图HashMap<String,QCTestResultDto> bestMap=new HashMap();HashMap<Integer, Boolean> bestRowIDMap=new HashMap();//最后点的图HashMap<String,QCTestResultDto> lastMap=new HashMap();HashMap<Integer, Boolean> lastRowIDMap=new HashMap();if(allData!=null&&allData.size()>0){for(QCTestResultDto one:allData){//不是数字的不参与if(!Helper.IsNumeric(one.Result)){continue;}//筛选浓度if(levMap.size()>0&&!levMap.containsKey(String.valueOf(one.LevelNo))){continue;}//去除排除点if(pointRange.equals("2")&&one.ExcludeType.equals("2")){continue;}//所有在控点if(pointRange.equals("6")&&one.CurRuleStatus.equals("R")){continue;}//仅平行点if(pointRange.equals("11")&&!one.IsParallel.equals("!")){continue;}//去除平行点if(pointRange.equals("12")&&one.IsParallel.equals("!")){continue;}//去除复查点if(pointRange.equals("4")&&redoMap.containsKey(one.LevelNo+"-"+one.TestDate)){continue;}//当天第一个数据redoMap.put(one.LevelNo+"-"+one.TestDate,true);one.CurLevelNo=one.LevelNo;one.CurPointType="";one.Num=1;one.CurdateNum=Helper.DateIntToStr(one.TestDate);one.TestRTime=Helper.TimeIntToStr(one.TestTime);one.UserName="";if(one.AddUserDR!=null){SYSUser user=EntityManager().DolerGet(SYSUser.class,one.AddUserDR);one.UserName=user.CName;}one.PicResult=one.Result;one.PicX=one.PicResult;one.CurRuleCode="";one.CurRuleColour="";one.CurRuleStatus="";one.CurRuleName="";if(one.QCRulesDR!=null){BTQCRules rule=EntityManager().DolerGet(BTQCRules.class,one.QCRulesDR);one.CurRuleCode=rule.Code;one.CurRuleColour=rule.Color;one.CurRuleStatus=rule.Status;one.CurRuleName=rule.CName;}//参数QCResMaterialTestCode para=EntityManager().DolerGet(QCResMaterialTestCode.class,one.ResMaterialTestCodeDR);//结果和均值的差one.Offset=Math.abs(Convert.ToInt32(one.Result)-para.Mean);//找到最好结果if(!bestMap.containsKey(one.LevelNo+"-"+one.TestDate)){bestMap.put(one.LevelNo+"-"+one.TestDate,one);}else{QCTestResultDto pre=bestMap.get(one.LevelNo+"-"+one.TestDate);if(pre.Offset>one.Offset){bestMap.put(one.LevelNo+"-"+one.TestDate,one);}}//最后点lastMap.put(one.LevelNo+"-"+one.TestDate,one);one.TCX=String.valueOf(para.Mean);one.TCSD=String.valueOf(para.SD);BTTestCode testCode=EntityManager().DolerGet(BTTestCode.class,one.TestCodeDR);one.TCName=testCode.CName;one.CurTestCode=testCode.Code;one.CurLevelName=matLevMap.get(one.LevelNo).CName;one.TCCV=String.valueOf(para.SetCV);one.CalX="";one.CalSD="";one.CalCV="";one.CalcType="";one.AccMean="";one.AccSD="";one.AccCV="";one.SetCV=String.valueOf(para.SetCV);one.TargetCV=para.TargetCV;one.LotNo=para.LotNo;one.Event="";one.ReagentLot=para.RgLot;one.ResRemark=one.Remark;one.AutUserName="";one.OriginalRes=one.TextRes;one.TransactionRemark="";one.TransactionMethod="";one.TransactionRes="";one.TransactionType="";one.TransactionUser="";one.LotNoAll=para.LotNo;dealedData.add(one);}//转换成主键mapfor (Map.Entry<String,QCTestResultDto> entry : bestMap.entrySet()) {bestRowIDMap.put(entry.getValue().RowID,true);}//转换成主键mapfor (Map.Entry<String,QCTestResultDto> entry : lastMap.entrySet()) {lastRowIDMap.put(entry.getValue().RowID,true);}//第二次处理数据for(int i=0;i<dealedData.size();i++){//只查最好点if(pointRange.equals("9")){if(!bestRowIDMap.containsKey(dealedData.get(i).RowID)){dealedData.remove(i);i--;continue;}}//只查最后点if(pointRange.equals("10")){if(!lastRowIDMap.containsKey(dealedData.get(i).RowID)){dealedData.remove(i);i--;continue;}}//最好点连线if(pointRange.equals("7")){if(!bestRowIDMap.containsKey(dealedData.get(i).RowID)){dealedData.get(i).CurPointType="0";}}//最后点连线else{if(!lastRowIDMap.containsKey(dealedData.get(i).RowID)){dealedData.get(i).CurPointType="0";}}}}return dealedData;}/*** 查询日间质控图数据* @param Param* @param Session* @param Output* @return* @throws Exception*/public String QueryQcDrawDataDay(Parameters Param, OutValue Session, OutValue Output) throws Exception {int StartDate= Helper.ValidParam(Param.P0,0);int EndDate=Helper.ValidParam(Param.P1,0);int MachineParameterDR= Convert.ToInt32(Param.P2);String TestCodeDRS=Param.P3;String MaterialDRS=Param.P4;String Level=Param.P5;String LastPoint=Param.P6;String LotNo=Param.P7;HashParam hs=new HashParam();hs.Add("MachineParameterDR",MachineParameterDR);List<String> operater=new ArrayList<>();operater.add("=");hs.Add("TestDate",StartDate);hs.Add("TestDate",EndDate);operater.add(">=");operater.add("<=");//浓度筛选图HashMap levMap=Helper.GetSplitMap(Level,",");//项目筛选图HashMap tsMap=Helper.GetSplitMap(TestCodeDRS,",");//质控物筛选图HashMap matMap=Helper.GetSplitMap(MaterialDRS,",");String [] tsArr=TestCodeDRS.split(",");String [] matArr=MaterialDRS.split(",");String [] levArr=Level.split(",");//计算质控规则for(int i=0;i<tsArr.length;i++){int TestCodeDR=Convert.ToInt32(tsArr[i]);int MaterialDR=Convert.ToInt32(matArr[i]);List<BTQCMaterialLevel> levList=EntityManager().FindByColVal(BTQCMaterialLevel.class,"MaterialDR",MaterialDR);for(BTQCMaterialLevel lev:levList){//筛选浓度if(levMap.size()>0&&!levMap.containsKey(String.valueOf(lev.LevelNo))){continue;}//计算质控规则CalQCRule(StartDate,EndDate,MaterialDR,TestCodeDR,lev.LevelNo,"1","");}}//查询仪器、项目、日期范围的所有质控数据List<QCTestResultDto> allData=EntityManager().FindAllSimple(QCTestResultDto.class,hs,"LevelNo asc,TestDate asc,TestTime asc",-1,null,operater);//存处理后的数据List<QCTestResultDto> dealedData=new ArrayList<>();HashMap lastMap=new HashMap();if(allData!=null&&allData.size()>0){for(QCTestResultDto one:allData){//筛选浓度if(levMap.size()>0&&!levMap.containsKey(String.valueOf(one.LevelNo))){continue;}//筛选质控物if(matMap.size()>0&&!matMap.containsKey(String.valueOf(one.MaterialDR))){continue;}//筛选项目if(tsMap.size()>0&&!tsMap.containsKey(String.valueOf(one.TestCodeDR))){continue;}//最后点if(LastPoint.equals("1")) {String key = one.MaterialDR + "-" + one.TestCodeDR + "-" + one.LevelNo + "-" + one.TestDate;lastMap.put(key, one);}else{dealedData.add(one);}}//最后点if(LastPoint.equals("1")) {dealedData.addAll(lastMap.values());}//统计失控数量int lossControlNum=0;for(QCTestResultDto one:dealedData) {if(one.DQIV_Status.equals("R")){lossControlNum++;}}//补全数据for(QCTestResultDto one:dealedData){BTQCMaterial matDto=EntityManager().DolerGet(BTQCMaterial.class,one.MaterialDR);BTMIMachineParameter machDto=EntityManager().DolerGet(BTMIMachineParameter.class,matDto.MachineDR);one.CurMachName=machDto.CName;one.TestCodeNum=tsMap.size()+"";one.LossControlNum=lossControlNum+"";one.CurLevelNo=one.LevelNo;one.CurPointType="";one.Num=1;one.CurdateNum=Helper.DateIntToStr(one.TestDate);one.TestRTime=Helper.TimeIntToStr(one.TestTime);one.UserName="";if(one.AddUserDR!=null){SYSUser user=EntityManager().DolerGet(SYSUser.class,one.AddUserDR);one.UserName=user.CName;}one.PicResult=one.Result;one.PicX=one.PicResult;one.CurRuleCode="";one.CurRuleColour="";one.CurRuleStatus="";one.CurRuleName="";if(one.QCRulesDR!=null){BTQCRules rule=EntityManager().DolerGet(BTQCRules.class,one.QCRulesDR);one.CurRuleCode=rule.Code;one.CurRuleColour=rule.Color;one.CurRuleStatus=rule.Status;one.CurRuleName=rule.CName;}//参数QCResMaterialTestCode para=EntityManager().DolerGet(QCResMaterialTestCode.class,one.ResMaterialTestCodeDR);//结果和均值的差one.Offset=Math.abs(Convert.ToInt32(one.Result)-para.Mean);//最后点lastMap.put(one.LevelNo+"-"+one.TestDate,one);one.TCX=String.valueOf(para.Mean);one.TCSD=String.valueOf(para.SD);BTTestCode testCode=EntityManager().DolerGet(BTTestCode.class,one.TestCodeDR);one.TCName=testCode.CName;one.CurTestCode=testCode.Code;one.CurLevelName="";one.TCCV=String.valueOf(para.SetCV);one.CalX="";one.CalSD="";one.CalCV="";one.CalcType="";one.AccMean="";one.AccSD="";one.AccCV="";one.SetCV=String.valueOf(para.SetCV);one.TargetCV=para.TargetCV;one.LotNo=para.LotNo;one.Event="";one.ReagentLot=para.RgLot;one.ResRemark=one.Remark;one.AutUserName="";one.OriginalRes=one.TextRes;one.TransactionRemark="";one.TransactionMethod="";one.TransactionRes="";one.TransactionType="";one.TransactionUser="";one.LotNoAll=para.LotNo;}}return Helper.Object2Json(dealedData);}/*** 返回到前台的数据实体*/public static class QCTestResultDto extends QCTestResult{/*** 当前浓度*/public int CurLevelNo;/*** 点类型*/public String CurPointType;/*** 数量*/public int Num;/*** 日期*/public String CurdateNum;/*** 测试时间*/public String TestRTime;/*** 用户名*/public String UserName;/*** 画图结果*/public String PicResult;/*** 结果*/public String PicX;/*** 规则代码*/public String CurRuleCode;/*** 规则颜色*/public String CurRuleColour;/*** 规则状态*/public String CurRuleStatus;/*** 规则名称*/public String CurRuleName;/*** 靶值*/public String TCX;/*** SD*/public String TCSD;/*** 项目名称*/public String TCName;/*** 项目代码*/public String CurTestCode;/*** 浓度名称*/public String CurLevelName;/*** CV*/public String TCCV;/*** 计算均值*/public String CalX;/*** 计算SD*/public String CalSD;/*** 计算CV*/public String CalCV;/*** 计算类型*/public String CalcType;/*** 计算均值*/public String AccMean;/*** 计算均值*/public String AccSD;/*** 计算均值*/public String AccCV;/*** 计算均值*/public String SetCV;/*** 计算均值*/public String TargetCV;/*** 计算均值*/public String LotNo;/*** 计算均值*/public String Event;/*** 计算均值*/public String ReagentLot;/*** 计算均值*/public String ResRemark;/*** 计算均值*/public String AutUserName;/*** 计算均值*/public String OriginalRes;/*** 失控处理说明*/public String TransactionRemark;/*** 失控类型*/public String TransactionType;/*** 处理方法*/public String TransactionMethod;/*** 失控处理结果*/public String TransactionRes;/*** 失控处理人*/public String TransactionUser;/*** 全部批号*/public String LotNoAll;/*** 结果和靶值的偏差*/public Double Offset;/*** 运行参数*/public QCResMaterialTestCode RunPara;/*** 仪器名称*/public String CurMachName="";/*** 测试项目数量*/public String TestCodeNum="";/*** 失控数量*/public String LossControlNum="";/*** 新判断的规则*/public Integer NewRuleDR;/*** 新规则状态*/public String NewRuleStatus;}
}

质控月报的核心逻辑

import JRT.Core.Debug.DebugSession;
import JRT.Core.Dto.HashParam;
import JRT.Core.Dto.OutValue;
import JRT.Core.MultiPlatform.JRTContext;
import JRT.Core.Util.Convert;
import JRT.Core.Util.TimeParser;
import JRT.Model.Bussiness.Parameters;
import JRT.Model.Entity.*;
import JRTBLLBase.BaseHttpHandler;
import JRTBLLBase.Helper;import java.util.*;/*** 质控月报后台*/
public class ashQCDataCalMonth extends BaseHttpHandler {/*** 查询质控月报数据* @return* @throws Exception*/public String QueryTestResultMonthData() throws Exception{//开始日期String StartDate = Helper.ValidParam(JRTContext.GetRequest(Request,"StartDate"),"");//结束日期String EndDate = Helper.ValidParam(JRTContext.GetRequest(Request,"EndDate"),"");//仪器String MachineParameterDR = Helper.ValidParam(JRTContext.GetRequest(Request,"MachineParameterDR"),"");//浓度String Leavel = Helper.ValidParam(JRTContext.GetRequest(Request,"Leavel"),"");//项目String TestCodeDRS = Helper.ValidParam(JRTContext.GetRequest(Request,"TestCodeDRS"),"");//排除规则String QcRule = Helper.ValidParam(JRTContext.GetRequest(Request,"QcRule"),"");//质控物String MaterialDRS = Helper.ValidParam(JRTContext.GetRequest(Request,"MaterialDRS"),"");String PointType = Helper.ValidParam(JRTContext.GetRequest(Request,"PointType"), "");String LotType = Helper.ValidParam(JRTContext.GetRequest(Request,"LotType"), "");String FLots = Helper.ValidParam(JRTContext.GetRequest(Request,"FLots"), "");Parameters param=new Parameters();param.P0=StartDate;param.P1=EndDate;param.P2=MachineParameterDR;param.P3=Leavel;param.P4=TestCodeDRS;param.P5=QcRule;param.P6=MaterialDRS;param.P7=PointType;param.P8=LotType;param.P9=FLots;OutValue session=new OutValue();session.Value=UserLogin().SessionStr;OutValue output=new OutValue();return  QueryQCMonthData(param,session,output);}/*** 查询质控月报数据的虚拟M方法** @param Param* @param Session* @param Output* @return*/public String QueryQCMonthData(Parameters Param, OutValue Session, OutValue Output) throws Exception {String SessionStr=Session.GetString();String [] sessArr=SessionStr.split("\\^");BTHospital hosDto=EntityManager().DolerGet(BTHospital.class,Convert.ToInt32(sessArr[4]));SYSUser userDto=EntityManager().DolerGet(SYSUser.class,Convert.ToInt32(sessArr[0]));Session.Value=hosDto.CName+"检验科";Session.Value+="^"+Helper.GetNowDateStr();Session.Value+="^"+"";Session.Value+="^"+"质控月报导出";Session.Value+="^"+userDto.CName;Session.Value+="^"+Helper.GetNowDateStr().substring(1,7);//开始日期String StartDate = Param.P0;//结束日期String EndDate = Param.P1;//仪器int MachineParameterDR = Helper.ValidParam(Param.P2,0);BTMIMachineParameter machDto=EntityManager().DolerGet(BTMIMachineParameter.class,MachineParameterDR);Session.Value+="^"+machDto.CName;BTWorkGroupMachine wgmDto=EntityManager().DolerGet(BTWorkGroupMachine.class,machDto.WorkGroupMachineDR);Session.Value+="^"+wgmDto.CName;BTWorkGroup wgDto=EntityManager().DolerGet(BTWorkGroup.class,wgmDto.WorkGroupDR);Session.Value+="^"+wgDto.CName;//浓度String Leavel = Param.P3;//项目String TestCodeDRS = Param.P4;//排除规则String QcRule = Param.P5;//质控物String MaterialDRS = Param.P6;String PointType = Param.P7;String LotType = Param.P8;String FLots = Param.P9;//计算项目String [] tsArr=TestCodeDRS.split(",");//计算质控物String [] matArr=MaterialDRS.split(",");//浓度图HashMap levMap=Helper.GetSplitMap(Leavel,",");List<QCMonthRetDto> retList=new ArrayList<>();//存所有的质控规则HashMap<Integer,Boolean> ruleMap=new HashMap();//循环计算每个项目的月报数据for(int i=0;i<tsArr.length;i++){String MaterialDR=matArr[i];//得到质控物的规则List<BTQCMaterialRules> ruleList=EntityManager().FindByColVal(BTQCMaterialRules.class,"MaterialDR",Convert.ToInt32(MaterialDR));if(ruleList!=null&&ruleList.size()>0){for(BTQCMaterialRules rule:ruleList){ruleMap.put(rule.QCRulesDR,true);}}//得到质控物的浓度数据List<BTQCMaterialLevel> levList=EntityManager().FindByColVal(BTQCMaterialLevel.class,"MaterialDR",Convert.ToInt32(MaterialDR));for(BTQCMaterialLevel lev:levList) {String levStr=String.valueOf(lev.LevelNo);if(levMap.size()>0&&!levMap.containsKey(levStr)){continue;}//计算一个项目浓度的月报数据List<HashMap> calResList=CalOneMonthData(Helper.ValidParam(StartDate,0),Helper.ValidParam(EndDate,0),Convert.ToInt32(MaterialDR),Convert.ToInt32(tsArr[i]),Convert.ToInt32(levStr),PointType,false);for(HashMap one:calResList){QCMonthRetDto oneMon=new QCMonthRetDto();Helper.CopyProperties(one.get("LastPara"),oneMon);BTQCMaterial matDto=EntityManager().DolerGet(BTQCMaterial.class,oneMon.MaterialDR);oneMon.MatName=matDto.CName;oneMon.YearMonth=Helper.DateIntToStr(oneMon.TestDate).substring(0,7);oneMon.AccMean=String.valueOf(one.get("AccMean"));oneMon.AccSD=String.valueOf(one.get("AccSD"));oneMon.AccCV=String.valueOf(one.get("AccCV"));oneMon.AccMax=String.valueOf(one.get("AccMax"));oneMon.AccMin=String.valueOf(one.get("AccMin"));oneMon.AccNum=String.valueOf(one.get("AccNum"));oneMon.AccResStr=String.valueOf(one.get("AccResStr"));oneMon.CalMean=String.valueOf(one.get("CalMean"));oneMon.CalSD=String.valueOf(one.get("CalSD"));oneMon.CalCV=String.valueOf(one.get("CalCV"));oneMon.CalMax=String.valueOf(one.get("CalMax"));oneMon.CalMin=String.valueOf(one.get("CalMin"));oneMon.CalNum=String.valueOf(one.get("CalNum"));oneMon.CalResStr=String.valueOf(one.get("CalResStr"));oneMon.CalLossNum=String.valueOf(one.get("CalLossNum"));oneMon.CalWaringNum=String.valueOf(one.get("CalWaringNum"));oneMon.CalDealNum=String.valueOf(one.get("CalDealNum"));oneMon.CalLossRate=String.valueOf(one.get("CalLossRate"));oneMon.CalDealRate=String.valueOf(one.get("CalDealRate"));oneMon.CalWaringRate=String.valueOf(one.get("CalWaringRate"));oneMon.CalDealWRate=String.valueOf(one.get("CalDealWRate"));oneMon.CalInMean=String.valueOf(one.get("CalInMean"));oneMon.CalInSD=String.valueOf(one.get("CalInSD"));oneMon.CalInCV=String.valueOf(one.get("CalInCV"));oneMon.CalInMax=String.valueOf(one.get("CalInMax"));oneMon.CalInMin=String.valueOf(one.get("CalInMin"));oneMon.CalInNum=String.valueOf(one.get("CalInNum"));oneMon.CalInResStr=String.valueOf(one.get("CalInResStr"));if(!oneMon.CalCV.isEmpty()&&!oneMon.TargetCV.isEmpty()){if(Convert.ToDouble(oneMon.CalCV)<Convert.ToDouble(oneMon.TargetCV)){oneMon.IsQualified="通过";}}BTTestCode tsDto=EntityManager().DolerGet(BTTestCode.class,oneMon.TestCodeDR);oneMon.Synonym=tsDto.Synonym;oneMon.TCName=tsDto.CName;oneMon.LevelName=lev.CName;retList.add(oneMon);}}}//所有的质控规则String AllRuleName="";Iterator<HashMap.Entry<Integer, Boolean>> iterator = ruleMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<Integer, Boolean> entry = iterator.next();BTQCRules rule=EntityManager().DolerGet(BTQCRules.class,entry.getKey());if(AllRuleName.isEmpty()){AllRuleName=rule.CName;}else{AllRuleName+=","+rule.CName;}}Session.Value+="^"+AllRuleName;return Helper.Object2Json(retList);}/*** 计算一个项目浓度的月报数据* @param StartDate 开始日期* @param EndDate 结束日期* @param MaterialDR 质控物* @param TestCodeDR 项目* @param LevelNo 浓度* @param PointType 点类型* @param isQCMap 是否是质控画图,画图不需要计算失控处理率相关东西* @return 计算数据* @throws Exception*/public List<HashMap> CalOneMonthData(int StartDate,int EndDate,int MaterialDR,int TestCodeDR,int LevelNo,String PointType,boolean isQCMap) throws Exception {//返回的数据List<HashMap> retList=new ArrayList<>();//往前推一年取数据算累计数据int accStartData=Helper.AddDays(StartDate,-365);HashParam hs=new HashParam();hs.Add("MaterialDR",MaterialDR);hs.Add("TestCodeDR",TestCodeDR);hs.Add("LevelNo",LevelNo);hs.Add("TestDate",accStartData);hs.Add("TestDate",EndDate);List<String> operater=new ArrayList<>();operater.add("=");operater.add("=");operater.add("=");operater.add(">");operater.add("<=");//查询结果List<QCTestResultDto> resList=EntityManager().FindAllSimple(QCTestResultDto.class,hs,"TestDate asc,TestTime asc",-1,null,operater);//筛选点类型数据resList=FilterDataByPointType(resList,PointType);//按批号分别计算HashMap<String,CalDto> calMap=new HashMap<>();//前一个计算键String preCalKey="";if(resList!=null&&resList.size()>0){for(int i=resList.size()-1;i>=0;i--){QCTestResultDto one=resList.get(i);//计算的键,相同的键算一批String calKey=one.RunPara.LotNo;//没维护批号的按靶值和SD相同的算if(calKey.isEmpty()){calKey=one.RunPara.Mean+"-"+one.RunPara.SD;}calKey=one.MaterialDR+"-"+one.TestCodeDR+"-"+one.LevelNo+"-"+calKey;//按计算键得到计算实体CalDto curCalDto=null;//创建新的计算实体if(!calMap.containsKey(calKey)){CalDto newCal=new CalDto();newCal.LastPara=one.RunPara;calMap.put(calKey,newCal);curCalDto=newCal;}else{curCalDto=calMap.get(calKey);}//查询是否有失控处理,质控图不统计失控处理率那些if((isQCMap!=true)&&(one.DQIV_Status.equals("R")||one.DQIV_Status.equals("W"))){HashParam hsTran=new HashParam();hsTran.Add("TestResultDR",one.RowID);if(EntityManager().CheckHasData(QCTestResultTransaction.class,hsTran,null,null)==true){one.HasDeal=true;}}//算本次信息if(one.TestDate>=StartDate){//加入月数据curCalDto.AddCalRes(one);preCalKey=calKey;}//小于开始日期的就是累计数据,如果和前一个计算键不同就说明批号不是一个,就不往前找了else if(one.TestDate<StartDate){if(!calKey.equals(preCalKey)){break;}}//加入累计数据curCalDto.AddAccRes(one);}//使用迭代器遍历计算数据Iterator<HashMap.Entry<String, CalDto>> iterator = calMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<String, CalDto> entry = iterator.next();HashMap calRes=entry.getValue().GetCalRes();//计算唯一键calRes.put("CalKey",entry.getKey());retList.add(calRes);}}return retList;}/*** 处理点范围* @param allData 所有数据* @param pointRange 点类型* @return 处理后的数据* @throws Exception*/public List<QCTestResultDto>  FilterDataByPointType(List<QCTestResultDto> allData,String pointRange) throws Exception{//存处理后的数据List<QCTestResultDto> dealedData=new ArrayList<>();//1:所有质控点 2:去除排除点 6:所有在控点 11:去除平行点 12:仅平行点 4:去除复查点 10:只查最后一点//7:最好点连线 8:最后一点连线 9:只查最好点//辅助判断复查点HashMap redoMap=new HashMap();//最好点的图HashMap<String,QCTestResultDto> bestMap=new HashMap();HashMap<Integer, Boolean> bestRowIDMap=new HashMap();//最后点的图HashMap<String,QCTestResultDto> lastMap=new HashMap();HashMap<Integer, Boolean> lastRowIDMap=new HashMap();if(allData!=null&&allData.size()>0){for(QCTestResultDto one:allData){//不是数字的不参与if(!Helper.IsNumeric(one.Result)){continue;}//去除排除点if(pointRange.equals("2")&&one.ExcludeType.equals("2")){continue;}//仅平行点if(pointRange.equals("11")&&!one.IsParallel.equals("!")){continue;}//去除平行点if(pointRange.equals("12")&&one.IsParallel.equals("!")){continue;}//去除复查点if(pointRange.equals("4")&&redoMap.containsKey(one.LevelNo+"-"+one.TestDate)){continue;}//只查最后一点if(pointRange.equals("10")&&redoMap.containsKey(one.LevelNo+"-"+one.TestDate)){continue;}//取规则状态if(one.QCRulesDR!=null){BTQCRules ruleDto=EntityManager().DolerGet(BTQCRules.class,one.QCRulesDR);one.CurRuleStatus=ruleDto.Status;}//所有在控点if(pointRange.equals("6")&&one.CurRuleStatus.equals("R")){continue;}//当天第一个数据redoMap.put(one.LevelNo+"-"+one.TestDate,true);//参数QCResMaterialTestCode para=EntityManager().DolerGet(QCResMaterialTestCode.class,one.ResMaterialTestCodeDR);//结果和均值的差one.Offset=Math.abs(Convert.ToInt32(one.Result)-para.Mean);//找到最好结果if(!bestMap.containsKey(one.LevelNo+"-"+one.TestDate)){bestMap.put(one.LevelNo+"-"+one.TestDate,one);}else{QCTestResultDto pre=bestMap.get(one.LevelNo+"-"+one.TestDate);if(pre.Offset>one.Offset){bestMap.put(one.LevelNo+"-"+one.TestDate,one);}}//最后点lastMap.put(one.LevelNo+"-"+one.TestDate,one);one.RunPara=para;dealedData.add(one);}//转换成主键mapfor (Map.Entry<String,QCTestResultDto> entry : bestMap.entrySet()) {bestRowIDMap.put(entry.getValue().RowID,true);}//转换成主键mapfor (Map.Entry<String,QCTestResultDto> entry : lastMap.entrySet()) {lastRowIDMap.put(entry.getValue().RowID,true);}//第二次处理数据for(int i=0;i<dealedData.size();i++){QCTestResultDto one=dealedData.get(i);//只查最好点if(pointRange.equals("9")){if(!bestRowIDMap.containsKey(one.RowID)){dealedData.remove(i);i--;continue;}}//只查最后点if(pointRange.equals("10")){if(!lastRowIDMap.containsKey(one.RowID)){dealedData.remove(i);i--;continue;}}}}return dealedData;}/*** 返回到前台的数据实体*/public static class QCTestResultDto extends QCTestResult {/*** 运行参数*/public QCResMaterialTestCode RunPara;/*** 规则状态*/public String CurRuleStatus;/*** 结果和靶值的偏差*/public Double Offset;/*** 是否进行失控处理*/public Boolean HasDeal;}/*** 计算计算均值、SD、累计均值、SD用到的承载实体*/public static class CalDto{/*** 最后的参数*/public QCResMaterialTestCode LastPara;/*** 失控数*/private int CalLossNum=0;/*** 警告数*/private int CalWaringNum=0;/*** 处理数*/private int CalDealNum=0;/*** 警告处理数*/private int CalDealWNum=0;/*** 失控数*/private int AccLossNum=0;/*** 警告数*/private int AccWaringNum=0;/*** 处理数*/private int AccDealNum=0;/*** 警告处理数*/private int AccDealWNum=0;/*** 总和*/private Double CalSumTotal=0.0;/*** 平方和*/private Double CalQuadraticSum=0.0;/*** 数据数量*/private int CalNum=0;/*** 存计算的结果*/private List<Double> CalResList=new ArrayList<>();/*** 在控数据总和*/private Double CalInSumTotal=0.0;/*** 在控数据平方和*/private Double CalInQuadraticSum=0.0;/*** 在控数据数据数量*/private int CalInNum=0;/*** 在控数据存计算的结果*/private List<Double> CalInResList=new ArrayList<>();/*** 总和*/private Double AccSumTotal=0.0;/*** 平方和*/private Double AccQuadraticSum=0.0;/*** 数据数量*/private int AccNum=0;/*** 存计算的结果*/private List<Double> AccResList=new ArrayList<>();/*** 添加累计结果* @param one 质控结果*/public void AddAccRes(QCTestResultDto one){Double res=Convert.ToDouble(one.Result,LastPara.Precision);//累计只算非失控的if(!one.DQIV_Status.equals("R")){AccResList.add(res);AccSumTotal+=res;AccNum++;}}/*** 添加当前结果* @param one 质控结果*/public void AddCalRes(QCTestResultDto one){Double res=Convert.ToDouble(one.Result,LastPara.Precision);//失控数if(one.DQIV_Status.equals("R")) {CalLossNum++;if(one.HasDeal==true){CalDealNum++;}}//警告数else if(one.DQIV_Status.equals("W")) {CalWaringNum++;if(one.HasDeal==true){CalDealWNum++;}}CalResList.add(res);CalSumTotal+=res;CalNum++;//本月在控数据if(!one.DQIV_Status.equals("R")) {CalInResList.add(res);CalInSumTotal+=res;CalInNum++;}}/*** 计算月均值和累计均值等信息* @return*/public HashMap GetCalRes(){//依次返回:计算值:均值、SD、CV、Min、Max、Num、ResStr 累计值:均值、SD、CV、Min、Max、Num、ResStrHashMap hsRet=new HashMap();hsRet.put("CalLossNum",CalLossNum);hsRet.put("CalWaringNum",CalWaringNum);hsRet.put("CalDealNum",CalDealNum);if(CalNum>0) {hsRet.put("CalLossRate", CalLossNum / CalNum);}else{hsRet.put("CalLossRate", "");}if(CalLossNum>0) {hsRet.put("CalDealRate", CalDealNum / CalLossNum);}else{hsRet.put("CalDealRate", "");}if(CalLossNum>0) {hsRet.put("CalWaringRate", CalWaringNum / CalNum);}else{hsRet.put("CalWaringRate", "");}if(CalWaringNum>0) {hsRet.put("CalDealWRate", CalDealWNum / CalWaringNum);}else{hsRet.put("CalDealWRate", "");}hsRet.put("CalMean","");hsRet.put("CalSD","");hsRet.put("CalCV","");hsRet.put("CalMin","");hsRet.put("CalMax","");hsRet.put("CalNum","");hsRet.put("CalResStr","");hsRet.put("CalInMean","");hsRet.put("CalInSD","");hsRet.put("CalInCV","");hsRet.put("CalInMin","");hsRet.put("CalInMax","");hsRet.put("CalInNum","");hsRet.put("CalInResStr","");hsRet.put("AccMean","");hsRet.put("AccSD","");hsRet.put("AccCV","");hsRet.put("AccMin","");hsRet.put("AccMax","");hsRet.put("AccNum","");hsRet.put("AccResStr","");hsRet.put("LastPara",LastPara);if(CalNum>1) {Double calAve = Convert.ToDouble(CalSumTotal / CalNum,LastPara.Precision);if(calAve>0) {Double maxVal=CalResList.get(0);Double minVal=CalResList.get(0);StringBuilder allResSB=new StringBuilder();int index=-1;for (Double res : CalResList) {CalQuadraticSum += (res - calAve) * (res - calAve);if(maxVal<res){maxVal=res;}if(minVal>res){minVal=res;}index++;if(index==0){allResSB.append(String.valueOf(res));}else{allResSB.append(","+String.valueOf(res));}}Double SD = Convert.ToDouble(Math.sqrt(CalQuadraticSum / (CalNum - 1)),LastPara.Precision);Double CV = Convert.ToDouble(SD / calAve * 100,LastPara.Precision);hsRet.put("CalMean",Helper.FormatNumber(calAve,LastPara.Precision));hsRet.put("CalSD",Helper.FormatNumber(SD,LastPara.Precision));hsRet.put("CalCV",Helper.FormatNumber(CV,LastPara.Precision));hsRet.put("CalMin",Helper.FormatNumber(minVal,LastPara.Precision));hsRet.put("CalMax",Helper.FormatNumber(maxVal,LastPara.Precision));hsRet.put("CalNum",String.valueOf(CalNum));hsRet.put("CalResStr",allResSB.toString());}}if(CalInNum>1) {Double calAve = Convert.ToDouble(CalInSumTotal / CalInNum,LastPara.Precision);if(calAve>0) {Double maxVal=CalInResList.get(0);Double minVal=CalInResList.get(0);StringBuilder allResSB=new StringBuilder();int index=-1;for (Double res : CalInResList) {CalInQuadraticSum += (res - calAve) * (res - calAve);if(maxVal<res){maxVal=res;}if(minVal>res){minVal=res;}index++;if(index==0){allResSB.append(String.valueOf(res));}else{allResSB.append(","+String.valueOf(res));}}Double SD = Convert.ToDouble(Math.sqrt(CalQuadraticSum / (CalNum - 1)),LastPara.Precision);Double CV = Convert.ToDouble(SD / calAve * 100,LastPara.Precision);hsRet.put("CalInMean",Helper.FormatNumber(calAve,LastPara.Precision));hsRet.put("CalInSD",Helper.FormatNumber(SD,LastPara.Precision));hsRet.put("CalInCV",Helper.FormatNumber(CV,LastPara.Precision));hsRet.put("CalInMin",Helper.FormatNumber(minVal,LastPara.Precision));hsRet.put("CalInMax",Helper.FormatNumber(maxVal,LastPara.Precision));hsRet.put("CalInNum",String.valueOf(CalInNum));hsRet.put("CalInResStr",allResSB.toString());}}if(AccNum>1) {Double accAve = Convert.ToDouble(AccSumTotal / AccNum,LastPara.Precision);if(accAve>0) {Double maxVal=AccResList.get(0);Double minVal=AccResList.get(0);StringBuilder allResSB=new StringBuilder();int index=-1;for (Double res : AccResList) {AccQuadraticSum += (res - accAve) * (res - accAve);if(maxVal<res){maxVal=res;}if(minVal>res){minVal=res;}index++;if(index==0){allResSB.append(String.valueOf(res));}else{allResSB.append(","+String.valueOf(res));}}Double SD = Convert.ToDouble(Math.sqrt(AccQuadraticSum / (AccNum - 1)),LastPara.Precision);Double CV = Convert.ToDouble(SD / accAve * 100,LastPara.Precision);hsRet.put("AccMean",Helper.FormatNumber(accAve,LastPara.Precision));hsRet.put("AccSD",Helper.FormatNumber(SD,LastPara.Precision));hsRet.put("AccCV",Helper.FormatNumber(CV,LastPara.Precision));hsRet.put("AccMin",Helper.FormatNumber(minVal,LastPara.Precision));hsRet.put("AccMax",Helper.FormatNumber(maxVal,LastPara.Precision));hsRet.put("AccNum",String.valueOf(CalNum));hsRet.put("AccResStr",allResSB.toString());}}return hsRet;}}/*** 查询质控浓度数据** @return*/public String QueryQCLeaveData() throws Exception {int MaterialDR = Helper.ValidParam(JRTContext.GetRequest(Request, "MaterialDR"), 0);List<BTQCMaterialLevel> retList = EntityManager().FindByColVal(BTQCMaterialLevel.class, "MaterialDR", MaterialDR);return Helper.Object2Json(retList);}/*** 查询仪器的批号* @return* @throws Exception*/public String QryMachineLot() throws Exception{//返回的数据List<String> retData = new ArrayList<>();int MachineParameterDR = Helper.ValidParam(JRTContext.GetRequest(Request,"MachineParameterDR"), 0);String MaterialDR = Helper.ValidParam(JRTContext.GetRequest(Request,"MaterialDR"), "");int StartDate = Helper.ValidParam(JRTContext.GetRequest(Request,"StartDate"), 0);int EndDate = Helper.ValidParam(JRTContext.GetRequest(Request,"EndDate"), 0);//查询仪器的所有质控物List<BTQCMaterial> matList=EntityManager().FindByColVal(BTQCMaterial.class,"MachineDR",MachineParameterDR);//查询每个质控物下的项目for(BTQCMaterial mat:matList) {List<String> operators = new ArrayList<>();HashParam hs = new HashParam();hs.Add("MaterialDR", mat.RowID);operators.add("=");hs.Add("StartDate", StartDate);operators.add("<=");//先找小于开始日期的最近数据List<BTQCMaterialTestCode> lastData = EntityManager().FindAllSimple(BTQCMaterialTestCode.class, hs, "StartDate desc", 1, null, operators);//然后安装最近开始日期和结束日期找模板数据List<String> operatorsFind = new ArrayList<>();HashParam hsFind = new HashParam();hsFind.Add("MaterialDR", mat.RowID);operatorsFind.add("=");//结束日期hsFind.Add("StartDate", EndDate);operatorsFind.add("<=");List<String> joinerFind = new ArrayList<>();if (lastData != null && lastData.size() > 0) {joinerFind.add("and");operatorsFind.add(">=");//开始日期hsFind.Add("StartDate", lastData.get(0).StartDate);}//目标数据List<BTQCMaterialTestCodeDto> perData = EntityManager().FindAllSimple(BTQCMaterialTestCodeDto.class, hsFind, "StartDate asc", -1, joinerFind, operatorsFind);HashMap map = new HashMap();if (perData != null && perData.size() > 0) {for (BTQCMaterialTestCodeDto one : perData) {if (!map.containsKey(one.LotNo)) {retData.add(one.LotNo);map.put(one.LotNo, true);}}}}return Helper.Object2Json(retData);}/*** 查询工作组数据** @return*/public String QueryWorkGroupData() throws Exception {//得到用户的角色List<SYSUserRoleDto> roleList = EntityManager().FindByColVal(SYSUserRoleDto.class, "UserDR", Convert.ToInt32(UserLogin().UserID));if (roleList != null && roleList.size() > 0) {for (SYSUserRoleDto one : roleList) {BTWorkGroup wgDto = EntityManager().DolerGet(BTWorkGroup.class, one.WorkGroupDR);one.WorkGroupName = wgDto.CName;one.CurWorkGroupDR = UserLogin().GroupID;}}return Helper.Object2Json(roleList);}/*** 查询仪器** @return*/public String QryMachineParameter() throws Exception {int WorkGroupDR = Helper.ValidParam(JRTContext.GetRequest(Request, "WorkGroupDR"), 0);List<BTWorkGroupMachine> wgmList = EntityManager().FindByColVal(BTWorkGroupMachine.class, "WorkGroupDR", WorkGroupDR);List<BTMIMachineParameter> retList = new ArrayList<>();if (wgmList != null && wgmList.size() > 0) {for (BTWorkGroupMachine wgm : wgmList) {//查询工作小组下的所有仪器List<BTMIMachineParameter> machList = EntityManager().FindByColVal(BTMIMachineParameter.class, "WorkGroupMachineDR", wgm.RowID);retList.addAll(machList);}}return Helper.Object2Json(retList);}/*** 查询仪器项目** @return*/public String QryMachineTestCode() throws Exception {int MachineParameterDR = Helper.ValidParam(JRTContext.GetRequest(Request, "MachineParameterDR"), 0);int StartDate = Helper.ValidParam(JRTContext.GetRequest(Request, "StartDate"), 0);int EndDate = Helper.ValidParam(JRTContext.GetRequest(Request, "EndDate"), 0);//返回的数据List<BTQCMaterialTestCodeDto> retData = new ArrayList<>();//查询仪器的所有质控物List<BTQCMaterial> matList=EntityManager().FindByColVal(BTQCMaterial.class,"MachineDR",MachineParameterDR);//查询每个质控物下的项目for(BTQCMaterial mat:matList) {List<String> operators = new ArrayList<>();HashParam hs = new HashParam();hs.Add("MaterialDR", mat.RowID);operators.add("=");hs.Add("StartDate", StartDate);operators.add("<=");//先找小于开始日期的最近数据List<BTQCMaterialTestCode> lastData = EntityManager().FindAllSimple(BTQCMaterialTestCode.class, hs, "StartDate desc", 1, null, operators);List<String> operatorsFind = new ArrayList<>();//然后安装最近开始日期和结束日期找模板数据HashParam hsFind = new HashParam();hsFind.Add("MaterialDR", mat.RowID);operatorsFind.add("=");//结束日期hsFind.Add("StartDate", EndDate);operatorsFind.add("<=");List<String> joinerFind = new ArrayList<>();if (lastData != null && lastData.size() > 0) {joinerFind.add("and");operatorsFind.add(">=");//开始日期hsFind.Add("StartDate", lastData.get(0).StartDate);}//目标数据List<BTQCMaterialTestCodeDto> perData = EntityManager().FindAllSimple(BTQCMaterialTestCodeDto.class, hsFind, "StartDate asc", -1, joinerFind, operatorsFind);HashMap map = new HashMap();if (perData != null && perData.size() > 0) {for (BTQCMaterialTestCodeDto one : perData) {BTQCMaterial matDto = EntityManager().DolerGet(BTQCMaterial.class, one.MaterialDR);one.MaterialName = matDto.CName;BTTestCode tsDto = EntityManager().DolerGet(BTTestCode.class, one.TestCodeDR);one.CName = tsDto.CName;one.Code = tsDto.Code;one.Synonym = tsDto.Synonym;if (!map.containsKey(one.MaterialDR + "-" + one.TestCodeDR)) {retData.add(one);map.put(one.MaterialDR + "-" + one.TestCodeDR, true);}}}}return Helper.Object2Json(retData);}/*** 月报查询返回的实体*/public static class QCMonthRetDto extends QCResMaterialTestCode{/*** 月报是否通过,月CV小于目标CV就是通过*/public String IsQualified="";/*** 质控物名称*/public String MatName="";/*** 年月*/public String YearMonth="";/*** 项目缩小*/public String Synonym="";/*** 项目名称*/public String TCName="";/*** 浓度名称*/public String LevelName="";/*** 计算均值*/public String CalMean="";/*** 计算SD*/public String CalSD="";/*** 计算CV*/public String CalCV="";/*** 计算最小值*/public String CalMin="";/*** 计算最大值*/public String CalMax="";/*** 计算数量*/public String CalNum="";/*** 计算结果串*/public String CalResStr="";/*** 在控数据计算均值*/public String CalInMean="";/*** 在控数据计算SD*/public String CalInSD="";/*** 在控数据计算CV*/public String CalInCV="";/*** 在控数据计算最小值*/public String CalInMin="";/*** 在控数据计算最大值*/public String CalInMax="";/*** 在控数据计算数量*/public String CalInNum="";/*** 在控数据计算结果串*/public String CalInResStr="";/*** 累计均值*/public String AccMean="";/*** 累计SD*/public String AccSD="";/*** 累计CV*/public String AccCV="";/*** 累计最小*/public String AccMin="";/*** 累计最大*/public String AccMax="";/*** 累计数量*/public String AccNum="";/*** 累计结果串*/public String AccResStr="";/*** 失控数量*/public String CalLossNum="";/*** 警告数量*/public String CalWaringNum="";/*** 处理数量*/public String CalDealNum="";/*** 失控率*/public String CalLossRate="";/*** 处理率*/public String CalDealRate="";/*** 警告率*/public String CalWaringRate="";/*** 警告处理率*/public String CalDealWRate="";}/*** 查询批次项目实体*/public static class BTQCMaterialTestCodeDto extends BTQCMaterialTestCode {/*** 质控物名称*/public String MaterialName="";/*** 项目名称*/public String CName="";/*** 项目缩写*/public String Synonym="";/*** 项目代码*/public String Code="";}/*** 角色查询实体*/public static class SYSUserRoleDto extends SYSUserRole {//工作组名称public String WorkGroupName="";//当前工作组public String CurWorkGroupDR="";}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/671007.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

i.MX 6ULL 裸机 IAR 环境安装

一. IAR 的安装请自行搜索 二. 使用最新版本的 IAR&#xff0c;需要修改 SDK 1. 在 SDK 的 core_ca7.h 加上 #include "intrinsics.h" /* IAR Intrinsics */ 2. debug 时需要修改每个工程下的 ddr_init.jlinkscript&#xff0c;参考链接 Solved: How to conn…

大厂Java面试题:MyBatis是如何进行分页的?分页插件的实现原理是什么?

大家好&#xff0c;我是王有志。 今天给大家带来的是一道来自京东的关于 MyBatis 实现分页功能的面试题&#xff1a;MyBatis是如何进行分页的&#xff1f;分页插件的实现原理是什么&#xff1f;通常&#xff0c;分页的方式可以分为两种&#xff1a; 逻辑&#xff08;内存&…

智慧园区综合物业管理平台解决方案PPT(130页精品)

我们对智慧园区的理解 智慧园区&#xff0c;是通过信息技术和各类资源的整合&#xff0c;充分降低企业运营成本&#xff0c;提高工作效率&#xff0c;加强各类园区创新、服务和管理能力&#xff0c;为园区铸就一套超强的软实力。智慧园区的实现是多技术融合、多系统融合、多领域…

苹果挖走大量谷歌人才,建立神秘人工智能实验室;李飞飞创业成立「空间智能」公司丨 RTE 开发者日报 Vol.197

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

从简单逻辑到复杂计算:感知机的进化与其在现代深度学习和人工智能中的应用(上)

文章目录 引言第一章&#xff1a;感知机是什么第二章&#xff1a;简单逻辑电路第三章&#xff1a;感知机的实现3.1 简单的与门实现3.2 导入权重和偏置3.3 使用权重和偏置的实现实现与门实现与非门和或门 文章文上下两节 从简单逻辑到复杂计算&#xff1a;感知机的进化与其在现代…

ESG视角下的多期DID构建(2009-2022年)4.5万+数据

随着ESG信息越来越受到重视&#xff0c;一些第三方评级机构开始推出ESG评级产品&#xff0c;目前在第三方数据库能够查到华证、富时罗素、商道融绿、社会价值投资联盟以及Wind自有的ESG评级数据等。其中&#xff0c;商道融绿是中国最早发布ESG评级数据的机构&#xff0c;也是国…

【Linux 基础 IO】文件系统

文章目录 1.初步理解文件2. fopen ( )的详解 1.初步理解文件 &#x1f427;① 打开文件&#xff1a; 本质是进程打开文件&#xff1b; &#x1f427;②文件没有被打开的时候在哪里呢&#xff1f; ----- 在磁盘中&#xff1b; &#x1f427;③进程可以打开很多个文件吗&#xff…

Vue入门到关门之Vue3项目创建

一、vue3介绍 1、为什么要学习vue3&#xff1f; vue3的变化&#xff1a; 首先vue3完全兼容vue2&#xff0c;但是vue3不建议用vue2的写法&#xff1b;其次&#xff0c;vue3拥抱TypeScript&#xff0c;之前vue2使用的JavaScript&#xff0c;ts完全兼容js 最后之前学的vue2 是…

【Linux】操作系统

上一篇博客我们从硬件的角度谈了计算机&#xff0c;我们说到了计算机的效率跟操作系统写的好不好有着直接的关系&#xff0c;那么这篇博客我们从软件的角度&#xff0c;就来谈一谈究竟什么是操作系统&#xff0c;为什么要有操作系统&#xff1f; 首先我们来大体的认识一下操作…

智慧工地)智慧工地标准化方案(107页)

2.2 设计思路 对于某某智慧工地管理系统的建设&#xff0c;绝不是对各个子系统进行简单堆砌&#xff0c;而是在满足各子系统功能的基础上&#xff0c;寻求内部各子系统之间、与外部其它智能化系统之间的完美结合。系统主要依托于智慧工地管理平台&#xff0c;来实现对众多子系统…

27-代码随想录三数之和

15. 三数之和 中等 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重…

Java基础教程 - 4 流程控制

更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 4 流程控制 4.1 分支结构…