JRT质控数据录入

2024-04-23 04:12
文章标签 数据录入 jrt 质控

本文主要是介绍JRT质控数据录入,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前有时间做了质控物维护界面,有了维护之后就应该提供可以录入业务数据的功能了,当时给质控物预留了一个“项目批次业务数据”的功能说是业务数据会给每天拷贝维护数据。这次一起补上,展示JRT怎么写质控数据录入的界面。

界面如下,需要实现一个面板式的录入界面,每个项目-浓度最多显示15个(总耗时3小时):
在这里插入图片描述

在这里插入图片描述
质控物维护可以看到运行时数据和批量修改运行时数据,到时候业务界面也都连接运行时查询和修改来达到调整业务的目的
在这里插入图片描述

在这里插入图片描述

这个界面要求把业务数据按“项目-浓度”每天铺开,保存的时候又按表存储,存在一个表行到15列的转换。界面新增和修改数据是一体的,没有明确具体是新增还是修改,实现起来比一般的存数据界面麻烦点。

表数据到多列数据
在这里插入图片描述

实体到前端的转换
在这里插入图片描述

前端到实体的转换
在这里插入图片描述
生成运行时维护数据
在这里插入图片描述

筛选判断
在这里插入图片描述

后台全代码:

import JRT.Core.CustomAttributes.Trans;
import JRT.Core.Dto.HashParam;
import JRT.Core.Dto.OutValue;
import JRT.Core.MultiPlatform.JRTContext;
import JRT.Core.Socket.MachManager;
import JRT.Core.Util.Convert;
import JRT.DAL.ORM.EntityManager.EntityManagerImpl;
import JRT.DAL.ORM.EntityManager.IEntityManager;
import JRT.Model.Bussiness.Sessions;
import JRT.Model.Entity.*;
import JRTBLLBase.BaseHttpHandler;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;/*** 质控数据录入界面的后台,为质控数据录入界面服务*/
public class ashQCDataInput extends BaseHttpHandler {/*** 查询结果数据,面板结构的** @return*/public String QueryTestResultData() throws Exception {int StartDate = Helper.ValidParam(JRTContext.GetRequest(Request, "StartDate"), 0);int EndDate = Helper.ValidParam(JRTContext.GetRequest(Request, "EndDate"), 0);String LevelNo = Helper.ValidParam(JRTContext.GetRequest(Request, "LevelNo"), "");int MaterialDR = Helper.ValidParam(JRTContext.GetRequest(Request, "MaterialDR"), 0);int TestCodeDR = Helper.ValidParam(JRTContext.GetRequest(Request, "TestCodeDR"), 0);BTQCMaterial matObj = EntityManager().DolerGet(BTQCMaterial.class, MaterialDR);HashParam hs = new HashParam();hs.Add("MaterialDR", MaterialDR);//得到质控浓度List<BTQCMaterialLevel> levList = EntityManager().FindByColVal(BTQCMaterialLevel.class, "MaterialDR", MaterialDR);//判断浓度HashMap levMap = Helper.GetSplitMap(LevelNo, ",");hs.Add("TestCodeDR", TestCodeDR);hs.Add("TestDate", StartDate);hs.Add("TestDate", EndDate);List<String> operater = new ArrayList<>();operater.add("=");operater.add("=");operater.add(">=");operater.add("<=");List<String> joiner = new ArrayList<>();//查询得到数据List<QCTestResult> resList = EntityManager().FindAllSimple(QCTestResult.class, hs, "TestDate asc,TestTime asc", 1000, joiner, operater);//要返回的数据List<QCTestResultDto> retList = new ArrayList<>();//按映射找返回的数据对象HashMap<String, QCTestResultDto> retMap = new HashMap<>();//得到所有日期List<Integer> allDateList = Helper.GetDatesBetween(StartDate, EndDate);//按日期组装返回的数据for (Integer curDate : allDateList) {for (BTQCMaterialLevel lev : levList) {//不是查询的浓度退出if (levMap.size() > 0 && !levMap.containsKey(String.valueOf(lev.LevelNo))) {continue;}//创建一行数据QCTestResultDto one = new QCTestResultDto();one.MaterialDR = MaterialDR;one.TestDate = Helper.DateIntToStr(curDate);one.TestDateInt = curDate;one.LevelNo = lev.LevelNo;one.LevelNoName = lev.CName;one.LevelColor = lev.Color;one.MachineParameterDR = matObj.MachineDR;one.TestCodeDR = TestCodeDR;one.ResultList = new ArrayList<>();//填充当前的维护参数one.DealCurBTPara(EntityManager());//有对应日期的维护就添加到返回if (one.CurBTParaObj != null) {retList.add(one);String key = one.TestDateInt + "-" + one.LevelNo;//方便业务数据找到组织实体retMap.put(key, one);}}}//业务数据处理进入返回实体if (resList != null && resList.size() > 0) {for (QCTestResult one : resList) {String key = one.TestDate + "-" + one.LevelNo;if (retMap.containsKey(key)) {QCTestResultDto perDto = retMap.get(key);//把业务数据塞入列表if (perDto.ResultList.size() < 15) {perDto.ResultList.add(one);}}}}//处理数据for (QCTestResultDto one : retList) {one.DealResultList(EntityManager(), UserLogin());}return Helper.Object2Json(retList);}/*** 批量保存质控数据** @return*/@Transpublic String SaveTestResult() throws Exception {//前台提交的报错Json串String AllRowsJson = Helper.ValidParam(JRTContext.GetRequest(Request, "AllRowsJson"), "");//转换得到业务对象List<QCTestResultDto> saveList = Helper.Json2List(AllRowsJson, QCTestResultDto.class);if (saveList != null && saveList.size() > 0) {//循环处理修改、增加和删除for (QCTestResultDto one : saveList) {//把结果传回归到Listone.DealResStrToList(EntityManager(), UserLogin());//单行有结果if (one.ResultList.size() > 0) {int index = -1;//遍历进行结果保存for (QCTestResult res : one.ResultList) {index++;//修改数据if (res.RowID > 0) {//获得数据库的数据QCTestResult dbRes = EntityManager().DolerGet(QCTestResult.class, res.RowID);//数据变化就修改数据if ((dbRes.Result != res.Result) || (dbRes.TextRes != res.TextRes)) {//保存直接结果int ret = EntityManager().Update(res, null);if (ret != 1) {throw new Exception("修改质控数据异常:" + Err.GetString());}}//数据为空就删除数据else if (dbRes.Result.isEmpty()) {int ret = EntityManager().Remove(res, ErrRet());if (ret != 1) {throw new Exception("删除质控数据异常:" + Err.GetString());}}}//新增的数据else {//非空的结果就存if (res.Result != null && !res.Result.isEmpty()) {HashParam hs = new HashParam();hs.Add("MaterialDR", res.MaterialDR);hs.Add("TestCodeDR", res.TestCodeDR);hs.Add("LevelNo", res.LevelNo);hs.Add("TestDate", res.TestDate);QCResMaterialTestCode bllPara = null;//查询数据库有的数据List<QCResMaterialTestCode> dbParaList = EntityManager().FindAllSimple(QCResMaterialTestCode.class, hs);//有业务参数就不插入数据if (dbParaList != null && dbParaList.size() > 0) {bllPara = dbParaList.get(0);} else {bllPara = new QCResMaterialTestCode();Helper.CopyProperties(one.CurBTParaObj, bllPara);bllPara.TestDate = one.TestDateInt;OutValue key = new OutValue();//保存业务参数int retbll = EntityManager().Save(bllPara, key, ErrRet());if (retbll != 1) {throw new Exception("插入质控数据业务参数异常:" + Err.GetString());}bllPara.RowID = key.GetInerger();}//数据参照业务配置参数res.ResMaterialTestCodeDR = bllPara.RowID;res.TestTime = res.TestTime + index;//保存直接结果int ret = EntityManager().Save(res, ErrRet());if (ret != 1) {throw new Exception("插入质控数据异常:" + Err.GetString());}}}}}}}return Helper.Success();}/*** 查询工作组数据** @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);HashParam hs = new HashParam();hs.Add("StartDate", StartDate);List<String> operators = new ArrayList<>();operators.add("<=");//先找小于开始日期的最近数据List<BTQCMaterialTestCode> lastData = EntityManager().FindAllSimple(BTQCMaterialTestCode.class, hs, "StartDate desc", 1, null, operators);//然后安装最近开始日期和结束日期找模板数据HashParam hsFind = new HashParam();//结束日期hsFind.Add("StartDate", EndDate);List<String> operatorsFind = new ArrayList<>();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);//返回的数据List<BTQCMaterialTestCodeDto> retData = new ArrayList<>();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(perData);}/*** 查询质控浓度数据** @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 QueryMatRules() throws Exception {int MaterialDR = Helper.ValidParam(JRTContext.GetRequest(Request, "MaterialDR"), 0);List<BTQCMaterialRulesDto> retList = EntityManager().FindByColVal(BTQCMaterialRulesDto.class, "MaterialDR", MaterialDR);if (retList != null && retList.size() > 0) {for (BTQCMaterialRulesDto one : retList) {BTQCRules ruleDto = EntityManager().DolerGet(BTQCRules.class, one.QCRulesDR);one.QCRulesName = ruleDto.CName;}}return Helper.Object2Json(retList);}/*** 质控数据业务实体,返回和保存质控数据录入界面的数据*/public static class QCTestResultDto {/*** 处理定性结果转换** @param resOdb 结果对象* @param map    转换图* @param resStr 结果串*/private void DealTrans(QCTestResult resOdb, HashMap<String, String> map, String resStr) {if (resStr == null || resStr.isEmpty()) {resOdb.TextRes = "";resOdb.Result = "";return;}if (map.containsKey(resStr)) {resOdb.TextRes = resStr;resOdb.Result = map.get(resStr);} else {resOdb.TextRes = resStr;resOdb.Result = resStr;}}/*** 把结果传回归到列表对象*/public void DealResStrToList(IEntityManager EntityManager, Sessions UserLogin) throws Exception {//得到定性转换数据List<BTQCResultToNumber> transList = EntityManager.FindByColVal(BTQCResultToNumber.class, "MachineParameterDR", MachineParameterDR);HashMap<String, String> map = new HashMap();if (transList != null && transList.size() > 0) {for (BTQCResultToNumber tran : transList) {map.put(tran.OldResult, tran.NewResult);}}//补全数据到15if (ResultList.size() < 15) {int addNum = 15 - ResultList.size();for (int i = 0; i < addNum; i++) {QCTestResult newObj = new QCTestResult();newObj.LevelNo = LevelNo;newObj.AddDate = Helper.GetNowDate();newObj.AddTime = Helper.GetNowTime();newObj.AddUserDR = Convert.ToInt32(UserLogin.UserID);newObj.MaterialDR = MaterialDR;newObj.TestCodeDR = TestCodeDR;newObj.TestDate = TestDateInt;newObj.TestTime = Helper.GetNowTime();newObj.MachineParameterDR = MachineParameterDR;ResultList.add(newObj);}}DealTrans(ResultList.get(0), map, Result1);DealTrans(ResultList.get(1), map, Result2);DealTrans(ResultList.get(2), map, Result3);DealTrans(ResultList.get(3), map, Result4);DealTrans(ResultList.get(4), map, Result5);DealTrans(ResultList.get(5), map, Result6);DealTrans(ResultList.get(6), map, Result7);DealTrans(ResultList.get(7), map, Result8);DealTrans(ResultList.get(8), map, Result9);DealTrans(ResultList.get(9), map, Result10);DealTrans(ResultList.get(10), map, Result11);DealTrans(ResultList.get(11), map, Result12);DealTrans(ResultList.get(12), map, Result13);DealTrans(ResultList.get(13), map, Result14);DealTrans(ResultList.get(14), map, Result15);}/*** 得到当前维护的参数** @param EntityManager* @throws Exception*/public void DealCurBTPara(IEntityManager EntityManager) throws Exception {Mean = 0.0;SD = 0.0;//得到当前维护的质控参数HashParam hs = new HashParam();hs.Add("MaterialDR", MaterialDR);hs.Add("StartDate", TestDateInt);List operater = new ArrayList();operater.add("=");operater.add("<=");List<BTQCMaterialTestCode> qcMatTsList = EntityManager.FindAllSimple(BTQCMaterialTestCode.class, hs, "StartDate desc", 1, null, operater);if (qcMatTsList != null && qcMatTsList.size() > 0) {CurBTParaObj = qcMatTsList.get(0);Mean = CurBTParaObj.Mean;SD = CurBTParaObj.SD;Precision = String.valueOf(CurBTParaObj.Precision);}}/*** 处理结果列表的值到结果*/public void DealResultList(IEntityManager EntityManager, Sessions UserLogin) throws Exception {Result1 = "";Result2 = "";Result3 = "";Result4 = "";Result5 = "";Result6 = "";Result7 = "";Result8 = "";Result9 = "";Result10 = "";Result11 = "";Result12 = "";Result13 = "";Result14 = "";Result15 = "";AutUserName = "";//处理业务数据相关数据if (ResultList != null && ResultList.size() > 0) {//查询当前数据的对应维护BllParaObj = EntityManager.DolerGet(QCResMaterialTestCode.class, ResultList.get(0).ResMaterialTestCodeDR);Mean = BllParaObj.Mean;SD = BllParaObj.SD;Precision = String.valueOf(BllParaObj.Precision);if (ResultList.get(0).AuthUserDR != null) {SYSUser usrDto = EntityManager.DolerGet(SYSUser.class, ResultList.get(0).AuthUserDR);AutUserName = usrDto.CName;}//按位置放结果for (int i = 0; i < ResultList.size(); i++) {if (i == 0) {Result1 = ResultList.get(i).Result;} else if (i == 1) {Result2 = ResultList.get(i).Result;} else if (i == 2) {Result3 = ResultList.get(i).Result;} else if (i == 3) {Result4 = ResultList.get(i).Result;} else if (i == 4) {Result5 = ResultList.get(i).Result;} else if (i == 5) {Result6 = ResultList.get(i).Result;} else if (i == 6) {Result7 = ResultList.get(i).Result;} else if (i == 7) {Result8 = ResultList.get(i).Result;} else if (i == 8) {Result9 = ResultList.get(i).Result;} else if (i == 9) {Result10 = ResultList.get(i).Result;} else if (i == 10) {Result11 = ResultList.get(i).Result;} else if (i == 11) {Result12 = ResultList.get(i).Result;} else if (i == 12) {Result13 = ResultList.get(i).Result;} else if (i == 13) {Result14 = ResultList.get(i).Result;} else if (i == 14) {Result15 = ResultList.get(i).Result;}}}}/*** 质控物*/public int MaterialDR;/*** 测试日期*/public int TestDateInt;/*** 测试日期*/public String TestDate;/*** 浓度*/public int LevelNo;/*** 项目*/public int TestCodeDR;/*** 仪器*/public int MachineParameterDR;/*** 浓度名称*/public String LevelNoName;/*** 浓度颜色*/public String LevelColor;/*** 精度*/public String Precision;/*** 当前的维护参数对象*/public BTQCMaterialTestCode CurBTParaObj;/*** 当前的业务参数对象*/public QCResMaterialTestCode BllParaObj;/*** 结果1*/public String Result1;/*** 结果2*/public String Result2;/*** 结果3*/public String Result3;/*** 结果4*/public String Result4;/*** 结果5*/public String Result5;/*** 结果6*/public String Result6;/*** 结果7*/public String Result7;/*** 结果8*/public String Result8;/*** 结果9*/public String Result9;/*** 结果10*/public String Result10;/*** 结果11*/public String Result11;/*** 结果12*/public String Result12;/*** 结果13*/public String Result13;/*** 结果14*/public String Result14;/*** 结果15*/public String Result15;/*** 靶值*/public Double Mean;/*** SD*/public Double SD;/*** 审核者*/public String AutUserName;/*** 结果列表*/public List<QCTestResult> ResultList;}/*** 质控规则*/public static class BTQCMaterialRulesDto extends BTQCMaterialRules {/*** 规则名称*/public String QCRulesName;}/*** 查询批次项目实体*/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;}
}

整个代码比较符合JRT的特色,只有扁平化的业务脚本、不用SQL级联、使用DolerGet解决多级取数据、业务内定义Dto顶替视图。

这篇关于JRT质控数据录入的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/927753

相关文章

消化学科的领军人物陈烨教授在会议上作了《幽门螺杆菌的规范检测与质控》的专题报告

由广东省药学会主办的“第十九届消化疾病诊疗会暨胃肠疾病药物临床研究交流会”于2024年8月8日-9日在广东省深圳市召开。陈烨教授,作为消化学科的领军人物、中华医学会消化病学分会的常务委员,以及全国幽门螺杆菌学组的组长,在会议上作了《幽门螺杆菌的规范检测与质控》的专题报告。 知识点一 尿素呼气试验(UBT) 是临床最常用的非侵入性诊断方法,具有操作简便、准确性较高和不受H.pylori在

ES单条数据录入操作

录入数据时先在库里进行查询,如果数据存在的话,进行更新数据;如果库里面此条数据不存在的话,进行插入数据以下是封装的完整代码可以参考 from elasticsearch import Elasticsearchurl = 'http://%s:%s/' % ('ip', 'port')ES = Elasticsearch(url)query = {"query": {"bool": {"mus

NetSuite 禁止用户在数据录入时增加列表值,例如客户区域列表,在新建客户时只能选择,不能新增

NetSuite 禁止用户在数据录入时增加列表值,例如客户区域列表,在新建客户时只能选择,不能新增 在项目实施过程中,一般会遇到新增字段,然后字段类型为列表的情形。这种情况一般又要求用户填写时只能选择,不能手动输入。但是在NetSuite中,另一个问题是用户在选择列表值界面,是可以新增可选值的。这虽然增加了系统的灵活性,但是一般管理员还是要求只能让用户选择,新增的权限保留的管理员处,避免最后列表

全外显子测序分析流程1 - Fastq质控与去接头、低质量和引物序列

全外显子测序分析流程1 - Fastq质控与去接头、低质量和引物序列 1. 运行实例 # -d 样本根目录# -s 样本名称python trim_fastq.py -d /result/WES/sample -s sample 2. fastqc质控报告与去接头、低质量序列主程序 对raw fastq和clean fastq生成质控QC报告trim_galore去接头、低质量序列和

jrt从量变到质变

又是一个加班的周末,上周把台式机代码和数据库环境弄好了,这周进行大数据测试,直接把标本、标本医嘱、报告、报告结果、药敏结果等数据插入到1亿的规模,跑了一天一夜插入了5000多万个标本,后面接着补剩下的到一亿。 演示视频 为什么测试1亿数据? 1.按标本两万的医院算,平均每天40万结果,一年数据大概就是1亿出头,一亿没性能问题那么可以保证业务库停留一年数据 2.我的磁盘只有350G,只能存大概1

Pajek的数据录入与参数计算

Pajek----数据录入   *Vertices N n     “k”                                     ----节点编号为n,名称为k …… *Arcslist a     b     c                                 ----弧从点a到点b,权重为c *Edgeslist a     b     c

JRT连接希森美康出图

上一篇用JRT连设备实现了比较有难度的Sebia绘图设备和TCP模式连接。这次连接最常见的检验设备(西森美康),读文件和图上传出图。 视频演示 结果格式 通道对应 接口设置 接口处理实现,JRT设备连接全部采用CMD驱动方式实现,所以需要客户端执行对应操作返回对应CMD即可。客户端对CMD负责,实现了对应的CMD执行器。 import JRT.Core.Dto.CmdDto;i

VBA技术资料MF153:利用ComboBox进行多列数据录入

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解,从简单的入门、到入门后的提高、到数据库、到字典、到Word VBA的应用、到高级网抓及类的应用、一直讲到程序的分发。另外,为了方便大家在写代码是方便查找,“VBA语言専攻”又推出了一部V

生信学习笔记:测序数据质控

文章目录 测序数据质控1.原始数据统计2.质控数据统计 测序数据质控 Illumina 测序属于第二代测序技术,单次运行能产生数十亿级的reads,如此海量的数据无法逐个展示每条read的质量情况;运用统计学的方法,对所测序列进行统计和质控,可以从宏观上直观地反映出样本的文库构建质量和测序质量。 1.原始数据统计 1)原始数据获得 Illumina 平台通过将测序图像信号

JRT质控打印

最近客户端打磨完了,又来推进质控了。之前演示的打印都是Demo示例,这次真正的写质控图的打印,数据就是质控数据录入界面录入的数据。其中质控图打印应该算最复杂的类型了。涉及JS的绘图,打印表格等,表格比较简单、还没做,难点是把JS的绘图和模板融合。 效果,这里打印和Web一体的优势就出来了,可以实现在线预览: 模板维护 质控图 打印虚拟M import JRT.Core.DataGr