在JRT打印元素绘制协议一篇已经介绍过打印把绘图和打印逻辑进行了分离,这是和老设计最大的不同。因为老的设计时候没想着做在线预览功能,是后面硬性扩出来的。这次从最初设计就考虑绘图逻辑各处共用,包括打印预览,在线打印预览等、后面还会再加PDF之类的。
总之:设计很重要,设计不到位后期功能难做,复杂度也会很高。
后台ashx对接绘图
import JRT.Core.Dto.OutValue;
import JRT.Core.MultiPlatform.FileCollection;
import JRT.Model.Bussiness.Parameters;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;
import JRT.Core.Dto.HashParam;
import JRT.Core.Dto.ParamDto;
import JRT.Core.Dto.OutParam;
import JRT.Model.Entity.*;
import JRT.Core.Util.Convert;
import JRT.Core.MultiPlatform.JRTContext;
import JRTPrintDraw.DrawElement;
import JRTPrintDraw.JRTPrintDrawProtocol;
import JRTPrintDraw.JsonDealUtil;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.List;
/**
* 打印绘图在线预览的后台类,对接打印绘图库,由于打印元素绘制协议是完全剥离的,所以很好共用,这样体现了设计的优势
*/
public class ashJRTPrintDrawView extends BaseHttpHandlerNoSession {
/**
* 得到打印画图的图片。分页的话有多张图片,在C#层面对接,返回串自己在前面加data:image/png;base64,后给图片绑定。分页多个图的Base64串以^分隔
* @return
* @throws Exception
*/
public String QryPrintDrawImgs() throws Exception
{
//打印M类名
String ClassName = Helper.ValidParam(JRTContext.GetRequest(Request,"ClassName"), "");
//打印M方法名
String FuncName = Helper.ValidParam(JRTContext.GetRequest(Request,"FuncName"), "");
//绘图宽度
int Width = Helper.ValidParam(JRTContext.GetRequest(Request,"Width"), 827);
//绘图高度
int Height = Helper.ValidParam(JRTContext.GetRequest(Request,"Height"), 583);
//返回类型
String RetType = "BASE64";
//文件名
String FileName = Helper.ValidParam(JRTContext.GetRequest(Request,"FileName"), "PrintImg.bmp");
Parameters param = new Parameters();
param.P0 = Helper.ValidParam(JRTContext.GetRequest(Request,"P0"), "");
param.P1 = Helper.ValidParam(JRTContext.GetRequest(Request,"P1"), "");
param.P2 = Helper.ValidParam(JRTContext.GetRequest(Request,"P2"), "");
param.P3 = Helper.ValidParam(JRTContext.GetRequest(Request,"P3"), "");
param.P4 = Helper.ValidParam(JRTContext.GetRequest(Request,"P4"), "");
param.P5 = Helper.ValidParam(JRTContext.GetRequest(Request,"P5"), "");
param.P6 = Helper.ValidParam(JRTContext.GetRequest(Request,"P6"), "");
param.P7 = Helper.ValidParam(JRTContext.GetRequest(Request,"P7"), "");
param.P8 = Helper.ValidParam(JRTContext.GetRequest(Request,"P8"), "");
param.P9 = Helper.ValidParam(JRTContext.GetRequest(Request,"P9"), "");
param.P10 = Helper.ValidParam(JRTContext.GetRequest(Request,"P10"), "");
param.P11 = Helper.ValidParam(JRTContext.GetRequest(Request,"P11"), "");
param.P12 = Helper.ValidParam(JRTContext.GetRequest(Request,"P12"), "");
param.P13 = Helper.ValidParam(JRTContext.GetRequest(Request,"P13"), "");
String strRet = "";
int rowCount = 0;
String logInfo = "^^^^";
String json = Helper.GetVMData(ClassName, FuncName, param, null, null);
List<DrawElement> elementList = JsonDealUtil.Json2List(json, DrawElement.class);
JRTPrintDrawProtocol PrintHandeler = new JRTPrintDrawProtocol();
int AllPageNum = PrintHandeler.JRTPrintDrawInit(elementList);
for(int p=0;p<AllPageNum;p++)
{
List<DrawElement> onePageData=PrintHandeler.GetOnePageData(p);
float maxY = 0;
for (int j = 0; j < onePageData.size(); j++)
{
DrawElement curRow = onePageData.get(j);
float PrintY = 0;
if (!curRow.PrintY.isEmpty())
{
PrintY = Convert.ToFloat(curRow.PrintY);
}
if (maxY < PrintY)
{
maxY = PrintY;
}
//图片元素
if (curRow.PrintType.equals("Graph"))
{
float PrintHeight = 0;
if (!curRow.PrintHeight.isEmpty())
{
PrintHeight = Convert.ToFloat(curRow.PrintHeight);
}
if (maxY < PrintY+ PrintHeight)
{
maxY = PrintY+ PrintHeight;
}
}
//是外送文件
if (curRow.PrintType.equals("FILE"))
{
if (strRet.isEmpty())
{
strRet = curRow.DataField;
}
else
{
strRet = strRet + "~" + curRow.DataField;
}
}
}
//A4
if (maxY > 583)
{
Height = 1169;
}
BufferedImage img = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
PrintHandeler.DrawOnePage(g, p);
if (strRet.isEmpty())
{
strRet = ImgToBase64(img);
}
else
{
strRet = strRet + "~" + ImgToBase64(img);;
}
}
return strRet;
}
/**
* 图片转Base64串
* @param img
* @return
* @throws Exception
*/
private String ImgToBase64(BufferedImage img) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
byte[] bytes = baos.toByteArray();
String base64Image = Base64.getEncoder().encodeToString(bytes);
return base64Image;
}
}
在线预览界面实现
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>打印绘图预览</title>
<script type="text/javascript">
var sysTheme = '';
</script>
<script src="../../resource/common/js/JRTBSBase.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
SYSPageCommonInfo.Init(true);
var BasePath = '';
var ResourcePath = '';
var WebServicAddress = SYSPageCommonInfo.Data.WebServicAddress;
var SessionStr = SYSPageCommonInfo.Data.SessionStr;
</script>
<script src="../../jrtprint/js/JRTPrint.js" type="text/javascript"></script>
<style type="text/css">
.btnMini {
z-index:9999;
position:relative;
right:10px;
top:0px;
}
</style>
<script type="text/javascript">
//得到传入的打印主参数
var PrintDR = requestUrlParam(location.href, "PrintDR").replace("#", "");
//打印类名
var PrintClassName = requestUrlParam(location.href, "PrintClassName").replace("#", "");
//仅仅浏览模式
var OnlyView = requestUrlParam(location.href, "OnlyView").replace("#", "");
var UserDR = requestUrlParam(location.href, "UserDR").replace("#", "");
var Align = requestUrlParam(location.href, "Align").replace("#", "");
//显示顶部按钮
var ShowTopBtn = requestUrlParam(location.href, "ShowTopBtn").replace("#", "");
var userCode = UserDR;
//1:报告处理打印 2:自助打印 3:医生打印
var paramList = "1";
//所有页面数
var AllPageNum = 1;
var AllPageArr = null;
var AllPageBllIDArr = null;
$(function () {
if (OnlyView == "1") {
//批量预览
if (PrintDR == "") {
PrintDR = localStorage["OnlyViewPrintDR"];
}
$("#btnPrint").hide();
$("#btnPDF").hide();
$("#btnPrintMini").remove();
$("#btnPDFMini").remove();
}
//不显示顶部按钮
if (ShowTopBtn == "0") {
$("#divOper").hide();
}
else {
$(".btnMini").hide();
}
//没传打印类的默认类
if (PrintClassName == null || PrintClassName == "") {
PrintClassName = "vm.test.PrintBarCodeTest";
}
if (Align == "Left") {
$("#divOper").css("margin", "0 0 0 0");
$("#divMian").css("margin", "0 0 0 0");
}
//打印
$("#btnPrint").click(function () {
InvokePrint("1");
});
$("#btnPrintMini").click(function () {
InvokePrint("1");
});
//导出PDF
$("#btnPDF").click(function () {
InvokePrint("3");
});
$("#btnPDFMini").click(function () {
InvokePrint("3");
});
//页数回车
$("#txtCurPage").keydown(function (event) {
if (event.keyCode == "13") {
var curPage = $("#txtCurPage").val();
var curPage = parseInt(curPage);
if (curPage < 1) {
curPage = 1;
}
if (curPage > AllPageNum) {
curPage = AllPageNum;
}
ShowOnePage(curPage);
}
});
//快捷键
$(window).keydown(function (e) {
if (e.key == "PageUp" || e.key == "ArrowUp") {
PrePage();
}
else if (e.key == "ArrowLeft") {
PrePage();
}
else if (e.key == "PageDown" || e.key == "ArrowDown") {
NextPage();
}
else if (e.key == "ArrowRight") {
NextPage();
}
else if (e.key == "F6") {
UnCheckParent();
}
});
//前一页
$("#btnPrePage").click(function () {
PrePage();
});
$("#btnPrePageMini").click(function () {
PrePage();
});
//前一页
function PrePage() {
var curPage = $("#txtCurPage").val();
var curPage = parseInt(curPage);
curPage = curPage - 1;
if (curPage < 1) {
curPage = 1;
}
$("#txtCurPage").val(curPage);
ShowOnePage(curPage);
}
//后一页
$("#btnNextPage").click(function () {
NextPage();
});
$("#btnNextPageMini").click(function () {
NextPage();
});
//下一页
function NextPage() {
var curPage = $("#txtCurPage").val();
var curPage = parseInt(curPage);
curPage = curPage + 1;
if (curPage > AllPageNum) {
curPage = AllPageNum;
}
$("#txtCurPage").val(curPage);
ShowOnePage(curPage);
}
//显示一页
function ShowOnePage(curPage) {
var imgStr = '';
if ((AllPageArr[curPage - 1].toLowerCase().indexOf("../../") > -1) || (AllPageArr[curPage - 1].toLowerCase().indexOf("ftp://") > -1) || (AllPageArr[curPage - 1].toLowerCase().indexOf("http://") > -1) || (AllPageArr[curPage - 1].toLowerCase().indexOf("https://") > -1)) {
if (curPage > 0) {
imgStr += '<div style="font-weight:bold;color:#ff5252;">第' + curPage + '页</div><iframe src="' + DealPdfViewUrl(AllPageArr[curPage - 1]) + '" style="margin-bottom:10px;width:827px;height:1189px;"/>';
}
else {
imgStr += '<iframe src="' + DealPdfViewUrl(AllPageArr[curPage - 1]) + '" style="margin-bottom:10px;width:827px;height:1189px;"/>';
}
}
else {
if (curPage > 0) {
imgStr += '<div style="font-weight:bold;color:#ff5252;">第' + curPage + '页</div><img src="' + "data:image/png;base64," + AllPageArr[curPage - 1] + '" alt="报告" style="margin-bottom:10px;"/>';
}
else {
imgStr += '<img src="' + "data:image/png;base64," + AllPageArr[curPage - 1] + '" alt="报告" style="margin-bottom:10px;"/>';
}
}
$("#divMian").html(imgStr);
}
//校验参数
if (PrintDR == "") {
$("#spPage").html("没按要求传入PrintDR!");
return;
}
//请求打印
$.ajax({
type: "get",
dataType: "text", //text, json, xml
cache: false, //
async: true, //为true时,异步,不等待后台返回值,为false时强制等待;-asir
url: '../ashx/ashJRTPrintDrawView.ashx?Method=QryPrintDrawImgs',
data: { ClassName: PrintClassName, FuncName: "GetData", Width: 827, Height: 583, P0: PrintDR, P1: userCode, P2: paramList, RetBll: "1" },
success: function (data) {
AllPageArr = data.split("~");
var imgStr = '';
AllPageBllIDArr = [];
for (var i = 0; i < AllPageArr.length; i++) {
var onePage = AllPageArr[i];
var onePageArr = onePage.split('^');
var oneBll = "";
if (onePageArr.length > 1) {
oneBll = onePageArr[1];
}
AllPageBllIDArr.push(oneBll);
AllPageArr[i] = onePageArr[0];
}
AllPageNum = AllPageArr.length;
for (var i = 0; i < AllPageArr.length; i++) {
if ((AllPageArr[i].toLowerCase().indexOf("../../") > -1) || (AllPageArr[i].toLowerCase().indexOf("ftp://") > -1) || (AllPageArr[i].toLowerCase().indexOf("http://") > -1) || (AllPageArr[i].toLowerCase().indexOf("https://") > -1)) {
if (i > 0) {
imgStr += '<div style="font-weight:bold;color:#ff5252;">第' + (i + 1) + '页</div><iframe src="' + DealPdfViewUrl(AllPageArr[i]) + '" style="margin-bottom:10px;width:827px;height:1189px;"/>';
}
else {
imgStr += '<iframe src="' + DealPdfViewUrl(AllPageArr[i]) + '" style="margin-bottom:10px;width:827px;height:1189px;"/>';
}
}
else {
if (i > 0) {
imgStr += '<div style="font-weight:bold;color:#ff5252;">第' + (i + 1) + '页</div><img src="' + "data:image/png;base64," + AllPageArr[i] + '" alt="报告" style="margin-bottom:10px;"/>';
}
else {
imgStr += '<img src="' + "data:image/png;base64," + AllPageArr[i] + '" alt="报告" style="margin-bottom:10px;"/>';
}
}
}
$("#spPage").html("当前报告共(" + AllPageArr.length + ")页");
$("#divMian").html(imgStr);
}
});
$("#txtCurPage").focus();
});
//打印
function InvokePrint(type) {
//0:打印所有报告 1:循环打印每一份报告
var printFlag = "0";
var rowids = PrintDR;
//打印用户
var userCode = UserDR;
//PrintOut:打印 PrintPreview打印预览 PDF#地址 【0用户选 -1桌面 具体地址】
//1:报告处理打印 2:自助打印 3:医生打印
var paramList = "LIS";
if (type == null || type == "1") {
//PrintOut:打印 PrintPreview打印预览
var printType = "PrintOut";
}
else if (type == "2") {
//PrintOut:打印 PrintPreview打印预览
var printType = "PrintPreview";
}
else if (type == "3") {
//打印预览
printType = "PDF#0";
}
var Param = printFlag + "@" + WebServicAddress + "@" + rowids + "@" + userCode + "@" + printType + "@" + paramList + "@" + PrintClassName + "@GetData";
JRTBasePrint(Param);
}
</script>
</head>
<body>
<div id="divOper" style="margin: auto auto; width: 850px; background-color: #F5F5F5; text-align: center; padding-top: 5px; padding-bottom: 5px;">
<a id="btnPrint" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left: 10px;">打印</a>  
<a id="btnPDF" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-export',plain:true">导出PDF</a>  
<a id="btnPrePage" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-arrow-left',plain:true" title="PgLeft">上一页</a>  
<a id="btnNextPage" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-arrow-right',plain:true" title="PgRight">下一页</a>  
<input id="txtCurPage" type="text" style="width: 40px;" class="easyui-validatebox" value="1" />  
<span id="spPage" style="font-weight: bold; color: #ff793e; font-size: 14px;"></span>
<span style="font-weight: bold; color: #AAAAAA; font-size: 14px; float: right; margin-right: 10px;">JRT在线浏览</span>
</div>
<div style="margin: auto auto; width: 850px;text-align:center;">
<div class="btnMini">
<a id="btnPrintMini" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-print',plain:true" title="打印"></a>
<span class="jrtsp6>"></span>
<a id="btnPDFMini" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-export',plain:true" title="导出PDF"></a>
<span class="jrtsp6>"></span>
<a id="btnPrePageMini" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-arrow-left',plain:true" title="上一页[PgLeft]"></a>
<span class="jrtsp6>"></span>
<a id="btnNextPageMini" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-arrow-right',plain:true" title="下一页[PgRight]"></a>
<span class="jrtsp6>"></span>
</div>
<div id="divMian" style="margin: auto auto; width: 850px; background-color: #DDDDDD; text-align: center; padding-top: 10px;"></div>
</div>
</body>
</html>
这样就可以实现在线预览功能,客户端不用环境也能进行打印预览,包括一些业务场景可以让用户看到图的效果,提高体验,也方便外部系统看一些报告和各种单据,只需要推送URL即可