经过一点点的业余加班努力,终于实现了客户端跨平台完全体。客户端可以调用打印,调用打印预览,调用打印生成PDF,调用Excel导出。windows下可以驱动模板设计器等。除了摄像头调用部分和监听程序接口部分全部实现。摄像头和监听接口目前还涉及不到linux运行。普通用户正常使用的功能是完事了。主要难度在打印预览实现上。

老winform预览,是打开winform界面做展示预览的,预览逻辑还不少,完全要做界面和服务分离。

//如果是预览
            if (printFlag == "PrintPreviewOld" || printFlag == "PrintPreview")
            {
                PrintPreview.Document = pdDocument;
                PrintPreview.ShowPrinterSettingsBeforePrint = false;
                PrintPreview.ShowPrinterSettingsButton = true;
                PrintPreview.ShowPageSettingsButton = true;
                PrintPreview.PrintPreviewControl.Zoom = 1;
                PrintPreview.WindowState = FormWindowState.Maximized;
                PrintPreview.ShowDialog();
                //确定打印
                if (PrintPreview.printDialogResult == DialogResult.Yes)
                {
                    PrinterSettings setting = pdDocument.PrinterSettings;
                    pdDocument = new PrintDocument();
                    pdDocument.PrinterSettings = setting;
                    iRow = 0;
                    startPage = 0;
                    //订阅BeginPrint事件 
                    pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint);
                    //定义打印内容
                    pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
                    //訂閱EndPrint事件,释放资源 
                    pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint);
                    //打印
                    PrintProxy();
                    string state = GetPrintState();
                    if (state != "")
                    {
                        if (shouldShowErr)
                        {
                            FrmInfo frminfo = new FrmInfo();
                            frminfo.Info = "打印机处于错误状态";
                            frminfo.CoderInfo = state;
                            frminfo.ShowDialog();
                            WriteLog(state);
                        }
                        else
                        {
                            errInfo += state;
                            WriteLog(errInfo);
                        }
                        return;
                    }
                }
                //确定打印
                else if (PrintPreview.printDialogResult == DialogResult.OK)
                {
                    //pdDocument = new PrintDocument();
                    iRow = 0;
                    startPage = 0;
                    int curPage = 0;
                    //当前页开始
                    int preStart = 0;
                    pintPoints.Clear();
                    //循环绘制每行数据
                    for (int i = iRow; i < namesTable.Rows.Count; i++)
                    {
                        if (PrintPreview.CurPage >= 0)
                        {
                            if (curPage == PrintPreview.CurPage + 1)
                            {
                                break;
                            }
                        }
                        //取出当前行数据
                        DataRow dr = namesTable.Rows[i];
                        //打印类型
                        string PrintType = dr["PrintType"].ToString();
                        //换页
                        if (PrintType == "PAGE" || (i == (namesTable.Rows.Count - 1)))
                        {
                            if (curPage < PrintPreview.CurPage)
                            {
                                iRow = i + 1;
                            }
                            else
                            {
                                endRow = i + 1;
                            }
                            curPage++;
                            //打印奇数页
                            if (PrintPreview.CurPage == -1)
                            {
                                if (curPage % 2 != 0)
                                {
                                    if (PrintPreview.RangeStart > 0 && PrintPreview.RangeEnd > 0)
                                    {
                                        if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                        {
                                            pintPoints.Add(new Point(preStart, i));
                                        }
                                    }
                                    else
                                    {
                                        pintPoints.Add(new Point(preStart, i));
                                    }
                                }
                            }
                            //打印偶数页
                            else if (PrintPreview.CurPage == -2)
                            {
                                if (curPage % 2 == 0)
                                {
                                    if (PrintPreview.RangeStart > 0 && PrintPreview.RangeEnd > 0)
                                    {
                                        if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                        {
                                            pintPoints.Add(new Point(preStart, i));
                                        }
                                    }
                                    else
                                    {
                                        pintPoints.Add(new Point(preStart, i));
                                    }
                                }
                            }
                            //打印偶数页逆序
                            else if (PrintPreview.CurPage == -3)
                            {
                                if (curPage % 2 == 0)
                                {
                                    if (PrintPreview.RangeStart > 0 && PrintPreview.RangeEnd > 0)
                                    {
                                        if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                        {
                                            pintPoints.Insert(0, new Point(preStart, i));
                                        }
                                    }
                                    else
                                    {
                                        pintPoints.Insert(0, new Point(preStart, i));
                                    }
                                }
                            }
                            //范围打印
                            else if (PrintPreview.CurPage == -4)
                            {
                                if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                {
                                    pintPoints.Add(new Point(preStart, i));
                                }
                            }
                            //当前页开始位置
                            preStart = i + 1;
                        }
                    }
                    //订阅BeginPrint事件 
                    pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint);
                    //定义打印内容
                    pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
                    //訂閱EndPrint事件,释放资源 
                    pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint);
                    //打印
                    PrintProxy();
                    string state = GetPrintState();
                    if (state != "")
                    {
                        if (shouldShowErr)
                        {
                            FrmInfo frminfo = new FrmInfo();
                            frminfo.Info = "打印机处于错误状态";
                            frminfo.CoderInfo = state;
                            frminfo.ShowDialog();
                            WriteLog(state);
                        }
                        else
                        {
                            errInfo += state;
                            WriteLog(errInfo);
                        }
                        return;
                    }
                }
            }

先抽取界面数据共性,用来在UI和服务传输数据,需要展示预览界面时候服务端给UI发消息,UI展示界面,把用户选择组装消息发回给服务端。在用户确认之前服务端处于线程等待状态。

/// <summary>
    /// 打印预览返回实体
    /// </summary>
    public class PrintPreViewRetDto
    {
        /// <summary>
        /// 选择结果
        /// </summary>
        public string printDialogResult
        {
            get;
            set;
        }

        /// <summary>
        /// 当前页
        /// </summary>
        public int CurPage
        {
            get;
            set;
        }

        /// <summary>
        /// 范围开始
        /// </summary>
        public int RangeStart
        {
            get;
            set;
        }

        /// <summary>
        /// 范围结束
        /// </summary>
        public int RangeEnd
        {
            get;
            set;
        }
    }

对接UI层实现,打印抽象接口

/// <summary>
    /// 操作打印的接口外壳
    /// </summary>
    public interface IOperPrintShell
    {
        /// <summary>
        /// 显示运用程序信息
        /// </summary>
        /// <param name="info"></param>
        /// <param name="coderInfo"></param>
        void ShowAppInfo(string info, string coderInfo);

        /// <summary>
        /// 显示弹窗消息
        /// </summary>
        /// <param name="info"></param>
        /// <param name="title"></param>
        void ShowMsgInfo(string info,string title="");

        /// <summary>
        /// 保存文件对话框
        /// </summary>
        /// <param name="Filter"></param>
        /// <returns></returns>
        string SaveFileDialog(string Filter);

        /// <summary>
        /// 选择文件夹对话框
        /// </summary>
        /// <param name="Title"></param>
        /// <returns></returns>
        string SaveDirDialog(string Title);

        /// <summary>
        /// 显示打印预览
        /// </summary>
        /// <param name="imageJsonName">图片Base64串JSON文件</param>
        /// <returns></returns>
        PrintPreViewRetDto ShowPrintPreview(string imageJsonName);
    }

打印界面接口实现

using DHCLabtrakReportPrint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LISClientMsgDeal
{
    /// <summary>
    /// 操作打印的壳
    /// </summary>
    public class OperPrintShell : DHCLabtrakReportPrint.IOperPrintShell
    {
        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="msg">消息</param>
        /// <param name="buttonNames">按钮名称</param>
        /// <returns></returns>
        public string ShowMsgDialog(string title, string msg, string buttonNames)
        {

            if (MessageServer.UIOper != null)
            {
                return MessageServer.UIOper.ShowMsgDialog(title, msg, buttonNames);
            }
            Console.WriteLine(title+":"+ msg);
            return "0";
        }

        /// <summary>
        /// 从多个文件选一个弹窗
        /// </summary>
        /// <param name="selectStr">用|分割的多个名称</param>
        /// <returns></returns>
        public string SelectFileDialog(string selectStr)
        {

            if (MessageServer.UIOper != null)
            {
                return MessageServer.UIOper.ShowSelectTmpFileDialog(selectStr);
            }
            Console.WriteLine("没有UI,默认选择第一个:");
            string path = selectStr.Split('|')[0];
            return path;
        }

        /// <summary>
        /// 保存文件对话框
        /// </summary>
        /// <param name="Filter"></param>
        /// <returns></returns>
        public string SaveFileDialog(string Filter)
        {
            
            if(MessageServer.UIOper != null)
            {
                return MessageServer.UIOper.ShowSaveFileDialog("保存文件","", Filter);
            }
            Console.WriteLine("请输入要保存的路径:");
            string path = Console.ReadLine();
            return path;
        }

        /// <summary>
        /// 显示App信息
        /// </summary>
        /// <param name="info"></param>
        /// <param name="coderInfo"></param>
        public void ShowAppInfo(string info, string coderInfo)
        {
            string head = DateTime.Now.ToString("hh:mm:ss") + "#";
            Console.WriteLine(head + info);
            Console.WriteLine(head + coderInfo);
        }

        /// <summary>
        /// 显示消息
        /// </summary>
        /// <param name="info"></param>
        /// <param name="title"></param>
        public void ShowMsgInfo(string info, string title = "")
        {
            if (MessageServer.UIOper != null)
            {
                MessageServer.UIOper.ShowMsgDialog(title, info, "确定");
            }
            string head = DateTime.Now.ToString("hh:mm:ss") + "#" + title;
            Console.WriteLine(head + info);
        }

        /// <summary>
        /// 选择文件夹对话框
        /// </summary>
        /// <param name="Title"></param>
        /// <returns></returns>
        public string SaveDirDialog(string Title)
        {
            if (MessageServer.UIOper != null)
            {
                return MessageServer.UIOper.ShowSaveDirDialog("选择要保存的路径","");
            }
            Console.WriteLine("请输入要保存的路径:");
            string path = Console.ReadLine();
            return path;
        }

        /// <summary>
        /// 显示打印预览
        /// </summary>
        /// <param name="imageJsonName">图片Base64串JSON文件</param>
        /// <returns></returns>
        public PrintPreViewRetDto ShowPrintPreview(string imageJsonName)
        {
            if (MessageServer.UIOper != null)
            {
                return MessageServer.UIOper.ShowPrintPreview(imageJsonName);
            }
            string head = DateTime.Now.ToString("hh:mm:ss") + "#" + imageJsonName;
            Console.WriteLine(head);
            PrintPreViewRetDto ret = new PrintPreViewRetDto();
            ret.printDialogResult = "Yes";
            ret.CurPage = 0;
            ret.RangeStart = -1;
            ret.RangeEnd = -1;
            return ret;
        }
    }
}

和electron的UI交互层

using DHCLabtrakReportPrint;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LISClientMsgDeal
{
    public class UIOperElectron : IUIOperInterface
    {
        /// <summary>
        /// 连接,通过该连接和UI通信
        /// </summary>
        public LIS.IWebSocketConnection Socket
        {
            get;
            set;
        }

        /// <summary>
        /// 消息ID
        /// </summary>
        private static int id = 0;

        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="msg">消息</param>
        /// <param name="buttonNames">按钮名称</param>
        /// <returns></returns>
        public string ShowMsgDialog(string title,string msg,string buttonNames)
        {
            if(buttonNames=="")
            {
                buttonNames = "确定|取消";
            }
            UIMsgDto dto = new UIMsgDto();
            dto.Type = "MsgDialog";
            dto.NeedRet = true;
            dto.Paras = new List<string>();
            dto.Paras.Add(title);
            dto.Paras.Add(msg);
            dto.Paras.Add(buttonNames);
            //会阻塞等待返回
            UIMsgDto ret = SenMsgAndWait(dto);
            if (ret != null)
            {
                if (ret.RetParas != null && ret.RetParas.Count > 0)
                {
                    return ret.RetParas[0];
                }
            }
            return "";
        }

        /// <summary>
        /// 显示选择文件对话框
        /// </summary>
        /// <param name="selectStr"></param>
        /// <returns></returns>
        public string ShowSelectTmpFileDialog(string selectStr)
        {
            UIMsgDto dto = new UIMsgDto();
            dto.Type = "SelectTmpFileDialog";
            dto.NeedRet = true;
            dto.Paras = new List<string>();
            dto.Paras.Add(selectStr);
            //会阻塞等待返回
            UIMsgDto ret = SenMsgAndWait(dto);
            if (ret != null)
            {
                if (ret.RetParas != null && ret.RetParas.Count > 0)
                {
                    return ret.RetParas[0];
                }
            }
            return "";
        }

        /// <summary>
        /// 显示保存文件对话框
        /// </summary>
        /// <param name="title">对话框标题</param>
        /// <param name="defaultPath">默认路径</param>
        /// <param name="filter">筛选:"Image Files (*.jpg;*.png)|*.jpg;*.png"</param>
        /// <returns>没选择就返回空,选择了就返回路径</returns>
        public string ShowSaveFileDialog(string title, string defaultPath, string filter)
        {
            UIMsgDto dto = new UIMsgDto();
            dto.Type = "SaveFileDialog";
            dto.NeedRet = true;
            dto.Paras = new List<string>();
            dto.Paras.Add(title);
            dto.Paras.Add(defaultPath);
            dto.Paras.Add(filter);
            //会阻塞等待返回
            UIMsgDto ret = SenMsgAndWait(dto);
            if(ret!=null)
            {
                if(ret.RetParas!=null&& ret.RetParas.Count>0)
                {
                    return ret.RetParas[0];
                }
            }
            return "";
        }

        /// <summary>
        /// 显示选择文件夹对话框
        /// </summary>
        /// <param name="title">对话框标题</param>
        /// <param name="defaultPath">默认路径</param>
        /// <returns>没选择就返回空,选择了就返回路径</returns>
        public string ShowSaveDirDialog(string title, string defaultPath)
        {
            UIMsgDto dto = new UIMsgDto();
            dto.Type = "SaveDirDialog";
            dto.NeedRet = true;
            dto.Paras = new List<string>();
            dto.Paras.Add(title);
            dto.Paras.Add(defaultPath);
            //会阻塞等待返回
            UIMsgDto ret = SenMsgAndWait(dto);
            if (ret != null)
            {
                if (ret.RetParas != null && ret.RetParas.Count > 0)
                {
                    return ret.RetParas[0];
                }
            }
            return "";
        }

        /// <summary>
        /// 显示打印预览
        /// </summary>
        /// <param name="imageJsonName">图片Base64串JSON文件</param>
        /// <returns></returns>
        public PrintPreViewRetDto ShowPrintPreview(string imageJsonName)
        {
            UIMsgDto dto = new UIMsgDto();
            dto.Type = "PrintPreView";
            dto.NeedRet = true;
            dto.Paras = new List<string>();
            dto.Paras.Add(imageJsonName);
            PrintPreViewRetDto retDto = new PrintPreViewRetDto();
            //会阻塞等待返回
            UIMsgDto ret = SenMsgAndWait(dto);
            if (ret != null)
            {
                if (ret.RetParas != null && ret.RetParas.Count > 0)
                {
                    retDto.printDialogResult = ret.RetParas[0];
                    retDto.CurPage = Convert.ToInt32(ret.RetParas[1]);
                    if(ret.RetParas[2]!="")
                    {
                        retDto.RangeStart = Convert.ToInt32(ret.RetParas[2]);
                    }
                    if(ret.RetParas[3]!="")
                    {
                        retDto.RangeEnd = Convert.ToInt32(ret.RetParas[3]);
                    }
                    return retDto;
                }
            }
            retDto.printDialogResult = "Yes";
            retDto.CurPage = 0;
            retDto.RangeStart = -1;
            retDto.RangeEnd = -1;
            return retDto;
        }

        /// <summary>
        /// 发送消息并且等待返回值
        /// </summary>
        /// <param name="dto">消息实体</param>
        /// <returns>返回结果</returns>
        private UIMsgDto SenMsgAndWait(UIMsgDto dto)
        {
            dto.MsgID = id.ToString();
            id++;
            string msgStr = JsonConvert.SerializeObject(dto);
            if(Socket!=null)
            {
                Socket.Send(msgStr);
                if(dto.NeedRet==true)
                {
                    //注册等待
                    UIMessageDeal.WaitReg(Socket.ConnectionInfo.Id.ToString(), dto);
                    int waiteNum = 0;
                    while (true)
                    {
                        UIMsgDto ret=UIMessageDeal.GetUIMsgRet(dto.MsgID);
                        if(ret!=null)
                        {
                            return ret;
                        }
                        else
                        {
                            System.Threading.Thread.Sleep(200);
                        }
                        waiteNum++;
                        if(waiteNum>40000)
                        {
                            break;
                        }
                    }
                }
            }
            return null;
        }

    }
}

界面electron对接层JS,处理服务发来的界面展示消息

//处理服务端后台的消息
function DealMsgServer(data) {
    //保存文件对话框
    if (data.Type == "SaveFileDialog") {
        var filters = [];
        if (data.Paras[2] != "") {
            var arr = data.Paras[2].split('|');
            for (var i = 0; i < arr.length; i += 2) {
                var one = { name: arr[i], extensions: [arr[i + 1].split(".")[1]] };
                filters.push(one);
            }
        }
        dialog.showSaveDialog({
            title: data.Paras[0],
            defaultPath: data.Paras[1],
            filters: filters
        }).then(result => {
            data.RetParas = [];
            data.RetParas.push(result.filePath);
            console.log("UI->S", "uimsg#" + JSON.stringify(data));
            ws.send("uimsg#" + JSON.stringify(data));
        }).catch(err => {
            console.log(err)
        });
    }
    //选择路径对话框
    else if (data.Type == "SaveDirDialog") {
        dialog.showOpenDialog(mainWindow, {
            properties: ['openDirectory']
        }).then(result => {
            data.RetParas = result.filePaths;
            console.log("UI->S", "uimsg#" + JSON.stringify(data));
            ws.send("uimsg#" + JSON.stringify(data));
        }).catch(err => {
            console.log(err)
        });
    }
    //选择模板文件对话框,多选一
    else if (data.Type == "SelectTmpFileDialog") {
        var path = data.Paras[0];
        var pathArr = path.split('|');
        var buttons = [];
        for (var i = 0; i < pathArr.length; i++) {
            var oneArr = pathArr[i].split("/");
            buttons.push(oneArr[oneArr.length-1]);
        }
        var choice = dialog.showMessageBoxSync(mainWindow, {
            type: "info",
            buttons: buttons,
            title: "选择模板对话框",
            message: "请选择要使用的导出模板",
            defaultId: -1,
            cancelId: -1
        });
        //执行菜单逻辑
        if (choice >= 0) {
            data.RetParas = [];
            data.RetParas.push(pathArr[choice]);
            console.log("UI->S", "uimsg#" + JSON.stringify(data));
            ws.send("uimsg#" + JSON.stringify(data));
        }
        else {
            data.RetParas = [];
            data.RetParas.push("");
            console.log("UI->S", "uimsg#" + JSON.stringify(data));
            ws.send("uimsg#" + JSON.stringify(data));
        }
    }
    //选择模板文件对话框,多选一
    else if (data.Type == "MsgDialog") {
        var title = data.Paras[0];
        var msg = data.Paras[1];
        var buttonStr = data.Paras[2];
        var nameArr = buttonStr.split('|');
        var buttons = [];
        for (var i = 0; i < nameArr.length; i++) {
            buttons.push(nameArr[i]);
        }
        var choice = dialog.showMessageBoxSync(mainWindow, {
            type: "info",
            buttons: buttons,
            title: title,
            message: msg,
            defaultId: -1,
            cancelId: -1
        });
        data.RetParas = [];
        data.RetParas.push(choice);
        console.log("UI->S", "uimsg#" + JSON.stringify(data));
        ws.send("uimsg#" + JSON.stringify(data));
    }
    //打印预览对话框
    else if (data.Type == "PrintPreView") {
        var JSONPath = data.Paras[0];
        //创建新的窗口
        var printViewWindow = new BrowserWindow({
            skipTaskbar: false,
            icon: __dirname + dirSplit + 'lis.ico',
            webPreferences: {
                nodeIntegration: true,
                contextIsolation: false
            }
        });
        //最大化
        printViewWindow.maximize();
        printViewWindow.loadFile('main/form/frmPrintView.html', { search: "Json=" + "http://127.0.0.1:8085/UI/" + JSONPath +"&MsgID="+data.MsgID });
    }
}

主进程打开预览界面后接收渲染进程消息

//接收渲染进程消息
    ipcMain.on('printview', (event, msgData) => {
        console.log(msgData);
        if (msgData.Type == "PrintPreView") {
            console.log("UI->S", "uimsg#" + JSON.stringify(msgData));
            ws.send("uimsg#" + JSON.stringify(msgData));
        }
    });

预览界面,把用户选择通过消息发送给主进程,主进程再发送给服务端的websockt让服务端接着执行逻辑

<!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">
        const ipcRenderer = require('electron').ipcRenderer;
        window.nodeRequire = require;
        delete window.require;
        delete window.exports;
        delete window.module;
    </script>
    <script src="../../resource/common/js/lis-commonHISUI.js" type="text/javascript"></script>
    <style type="text/css">
        .ar {
            text-align: right;
            padding-right: 8px;
        }

        .ar6 {
            text-align: right;
            padding-right: 6px;
        }

        .al {
            text-align: left;
            padding-right: 10px;
        }

        .sp {
            display: inline-block;
            width: 15px;
        }

        .sp4 {
            display: inline-block;
            width: 4px;
        }

        .sp6 {
            display: inline-block;
            width: 6px;
        }

        .sp10 {
            display: inline-block;
            width: 10px;
        }

        .sp20 {
            display: inline-block;
            width: 20px;
        }

    </style>
    <script type="text/javascript">
        //得到传入的Json路径
        var Json = requestUrlParam(location.href, "Json").replace("#", "");
        var MsgID = requestUrlParam(location.href, "MsgID").replace("#", "");
        //document.write('<script type="text/javascript" href="' + Json + '"/>');
        var Align = requestUrlParam(location.href, "Align").replace("#", "");
        $(function () {
            if (Align == "Left") {
                $("#divOper").css("margin", "0 0 0 0");
                $("#divMian").css("margin", "0 0 0 0");
            }
            var CurPage = 0;
            var printDialogResult = "";
            var RangeStart = "";
            var RangeEnd = "";
            //默认第一页
            $("#txtCurPage").val("1");
            //打印当前页
            $("#btnPrintCur").click(function () {
                printDialogResult = "Ok";
                SendMsg();
            });
            //打印全部
            $("#btnPrintAll").click(function () {
                printDialogResult = "Yes";
                SendMsg();
            });
            //关闭
            $("#btnClose").click(function () {
                printDialogResult = "Cancel";
            });
            //打印奇数页
            $("#btnPrintOdd").click(function () {
                printDialogResult = "OK";
                CurPage = -1;
                SendMsg();
            });
            //打印偶数页
            $("#btnPrintEven").click(function () {
                printDialogResult = "OK";
                CurPage = -2;
                SendMsg();
            });
            //偶逆序
            $("#btnPrintEvenRevert").click(function () {
                printDialogResult = "OK";
                CurPage = -3;
                SendMsg();
            });
            //范围打印
            $("#btnPrintRange").click(function () {
                printDialogResult = "OK";
                RangeStart = $("#txtRangeStart").val();
                RangeEnd = $("#txtRangeEnd").val();
                SendMsg();
            });
            //上一页
            $("#btnPrev").click(function () {
                CurPage--;
                if (CurPage < 0) {
                    CurPage = 0;
                }
                $("#txtCurPage").val(CurPage+1);
                DrawPage();
            });
            //下一页
            $("#btnNext").click(function () {
                CurPage++;
                if (CurPage == MaxPageIndex) {
                    CurPage = MaxPageIndex - 1;
                }
                $("#txtCurPage").val(CurPage+1);
                DrawPage();
            });
            if (Json == "") {
                $("#spPage").html("没按要求传入Json!");
                return;
            }
            var imgStr = '';
            $.ajax({
                type: "get",
                dataType: "json", //text, json, xml
                cache: false, //
                async: false, //为true时,异步,不等待后台返回值,为false时强制等待;-asir
                url: Json,
                success: function (imageArr) {
                    for (var i = 0; i < imageArr.length; i++) {
                        if (i > 0) {
                            imgStr += '<div style="font-weight:bold;color:#ff5252;">第' + (i + 1) + '页</div><img src="' + "data:image/png;base64," + imageArr[i] + '" alt="报告" style="margin-bottom:10px;"/>';
                        }
                        else {
                            imgStr += '<img src="' + "data:image/png;base64," + imageArr[i] + '" alt="报告" style="margin-bottom:10px;"/>';
                        }
                    }
                    $("#spPage").html("当前报告共(" + imageArr.length + ")页");
                    $("#divMian").html(imgStr);
                }
            });
            

            //组装消息
            function SendMsg() {
                var msg = {};
                msg.CurPage = CurPage;
                msg.printDialogResult = printDialogResult;
                msg.RangeStart = RangeStart;
                msg.RangeEnd = RangeEnd;
                msg.MsgID = MsgID;
                msg.Type = "PrintPreView";
                msg.NeedRet = true;
                msg.Paras = "";
                msg.RetParas = [printDialogResult, CurPage, RangeStart, RangeEnd];
                ipcRenderer.send('printview', msg);
                window.close();
            }

            //绘制当前页
            function DrawPage() {
                $("#divMian").html('<img src="' + "data:image/png;base64," + imageArr[CurPage] + '" alt="报告" style="margin-bottom:10px;"/>');
            }

        });

    </script>
</head>
<body>
    <div id="divOper" style="margin:auto auto;width: 100%;background-color:#F5F5F5; text-align: center; padding: 5px;">
        <a id="btnPrintCur" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">打印当前页</a>
        <a id="btnPrintAll" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">打印全部</a>
        <a id="btnClose" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">关闭</a>
        <a id="btnPrintOdd" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">打印奇数页</a>
        <a id="btnPrintEven" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">打印偶数页</a>
        <a id="btnPrintEvenRevert" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">偶逆序</a>
        <input id="txtRangeStart" type="text" style="width:30px" class="hisui-validatebox" />
        -
        <input id="txtRangeEnd" type="text" style="width:30px" class="hisui-validatebox" />
        <a id="btnPrintRange" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">范围打印</a>
        <span id="spPage" style="font-weight: bold; color: #ff5252; font-size: 14px;"></span>
        <input id="txtCurPage" type="text" style="width:30px" class="hisui-validatebox" />
        <a id="btnPrev" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">上一页</a>
        <a id="btnNext" href="#" class="hisui-linkbutton" data-options="iconCls:'icon-print',plain:true" style="margin-left:10px;">下一页</a>
        <span style="font-weight: bold; color: #AAAAAA; font-size: 14px;float:right;margin-right:10px;">打印预览</span>
    </div>
    <div id="divMian" style="margin: auto auto; width: 850px; background-color: #DDDDDD; text-align: center; padding-top: 10px;"></div>
</body>
</html>

原来winform打印预览代码调整,原来的打印预览弹窗改为PrintPreViewRetDto PrintPreview = Shell.ShowPrintPreview(jsonFile);驱动electron的ui。

//如果是预览
            if (printFlag == "PrintPreviewOld" || printFlag == "PrintPreview")
            {
                //得到打印预览的图片JSON
                string jsonFile=GetImageJsonFile();
                //显示打印预览
                PrintPreViewRetDto PrintPreview = Shell.ShowPrintPreview(jsonFile);
                //确定打印
                if (PrintPreview.printDialogResult == "Yes")
                {
                    PrinterSettings setting = pdDocument.PrinterSettings;
                    pdDocument = new PrintDocument();
                    pdDocument.PrinterSettings = setting;
                    iRow = 0;
                    startPage = 0;
                    //订阅BeginPrint事件 
                    pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint);
                    //定义打印内容
                    pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
                    //訂閱EndPrint事件,释放资源 
                    pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint);
                    //打印
                    PrintProxy();
                }
                //确定打印
                else if (PrintPreview.printDialogResult == "Ok")
                {
                    //pdDocument = new PrintDocument();
                    iRow = 0;
                    startPage = 0;
                    int curPage = 0;
                    //当前页开始
                    int preStart = 0;
                    pintPoints.Clear();
                    //循环绘制每行数据
                    for (int i = iRow; i < namesTable.Rows.Count; i++)
                    {
                        if (PrintPreview.CurPage >= 0)
                        {
                            if (curPage == PrintPreview.CurPage + 1)
                            {
                                break;
                            }
                        }
                        //取出当前行数据
                        DataRow dr = namesTable.Rows[i];
                        //打印类型
                        string PrintType = dr["PrintType"].ToString();
                        //换页
                        if (PrintType == "PAGE" || (i == (namesTable.Rows.Count - 1)))
                        {
                            if (curPage < PrintPreview.CurPage)
                            {
                                iRow = i + 1;
                            }
                            else
                            {
                                endRow = i + 1;
                            }
                            curPage++;
                            //打印奇数页
                            if (PrintPreview.CurPage == -1)
                            {
                                if (curPage % 2 != 0)
                                {
                                    if (PrintPreview.RangeStart > 0 && PrintPreview.RangeEnd > 0)
                                    {
                                        if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                        {
                                            pintPoints.Add(new Point(preStart, i));
                                        }
                                    }
                                    else
                                    {
                                        pintPoints.Add(new Point(preStart, i));
                                    }
                                }
                            }
                            //打印偶数页
                            else if (PrintPreview.CurPage == -2)
                            {
                                if (curPage % 2 == 0)
                                {
                                    if (PrintPreview.RangeStart > 0 && PrintPreview.RangeEnd > 0)
                                    {
                                        if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                        {
                                            pintPoints.Add(new Point(preStart, i));
                                        }
                                    }
                                    else
                                    {
                                        pintPoints.Add(new Point(preStart, i));
                                    }
                                }
                            }
                            //打印偶数页逆序
                            else if (PrintPreview.CurPage == -3)
                            {
                                if (curPage % 2 == 0)
                                {
                                    if (PrintPreview.RangeStart > 0 && PrintPreview.RangeEnd > 0)
                                    {
                                        if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                        {
                                            pintPoints.Insert(0, new Point(preStart, i));
                                        }
                                    }
                                    else
                                    {
                                        pintPoints.Insert(0, new Point(preStart, i));
                                    }
                                }
                            }
                            //范围打印
                            else if (PrintPreview.CurPage == -4)
                            {
                                if (curPage >= PrintPreview.RangeStart && curPage <= PrintPreview.RangeEnd)
                                {
                                    pintPoints.Add(new Point(preStart, i));
                                }
                            }
                            //当前页开始位置
                            preStart = i + 1;
                        }
                    }
                    //订阅BeginPrint事件 
                    pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint);
                    //定义打印内容
                    pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
                    //訂閱EndPrint事件,释放资源 
                    pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint);
                    //打印
                    PrintProxy();
                }
            }

Excel导出从多个模板选一个对接,需要弹窗展示多个模板名称让用户选择用的模板。通过string fullName = MessageServer.shell.SelectFileDialog(tempExcelPath);驱动UI

驱动地方,

//导出Excel
                    else if (((inputStrArr[0] == "Export") || (inputStrArr[0] == "ExportFast")) && inputStrArr.Length > 2)
                    {
                        string tempExcelPath = inputStrArr[6];
                        //快速导出Excel标识
                        if (inputStrArr[0] == "ExportFast")
                        {
                            ExportUtil.IsExportFast = true;
                        }
                        //选模板的模式
                        if (tempExcelPath.Contains("|"))
                        {
                            //选择模板
                            string fullName = MessageServer.shell.SelectFileDialog(tempExcelPath);
                            if (fullName != "")
                            {
                                inputStrArr[6] = fullName;
                                RealExport(inputStrArr);
                            }
                        }
                        else
                        {
                            RealExport(inputStrArr);
                        }
                    }

发消息给UI层

/// <summary>
        /// 从多个文件选一个弹窗
        /// </summary>
        /// <param name="selectStr">用|分割的多个名称</param>
        /// <returns></returns>
        public string SelectFileDialog(string selectStr)
        {

            if (MessageServer.UIOper != null)
            {
                return MessageServer.UIOper.ShowSelectTmpFileDialog(selectStr);
            }
            Console.WriteLine("没有UI,默认选择第一个:");
            string path = selectStr.Split('|')[0];
            return path;
        }

electron交互层,这里把组装的UI消息推送给界面端,界面收到消息做响应

/// <summary>
        /// 显示选择文件对话框
        /// </summary>
        /// <param name="selectStr"></param>
        /// <returns></returns>
        public string ShowSelectTmpFileDialog(string selectStr)
        {
            UIMsgDto dto = new UIMsgDto();
            dto.Type = "SelectTmpFileDialog";
            dto.NeedRet = true;
            dto.Paras = new List<string>();
            dto.Paras.Add(selectStr);
            //会阻塞等待返回
            UIMsgDto ret = SenMsgAndWait(dto);
            if (ret != null)
            {
                if (ret.RetParas != null && ret.RetParas.Count > 0)
                {
                    return ret.RetParas[0];
                }
            }
            return "";
        }

js处理,处理选择模板类型消息,展示模板选择弹窗,把选择结果发送给服务端。

//选择模板文件对话框,多选一
    else if (data.Type == "SelectTmpFileDialog") {
        var path = data.Paras[0];
        var pathArr = path.split('|');
        var buttons = [];
        for (var i = 0; i < pathArr.length; i++) {
            var oneArr = pathArr[i].split("/");
            buttons.push(oneArr[oneArr.length-1]);
        }
        var choice = dialog.showMessageBoxSync(mainWindow, {
            type: "info",
            buttons: buttons,
            title: "选择模板对话框",
            message: "请选择要使用的导出模板",
            defaultId: -1,
            cancelId: -1
        });
        //执行菜单逻辑
        if (choice >= 0) {
            data.RetParas = [];
            data.RetParas.push(pathArr[choice]);
            console.log("UI->S", "uimsg#" + JSON.stringify(data));
            ws.send("uimsg#" + JSON.stringify(data));
        }
        else {
            data.RetParas = [];
            data.RetParas.push("");
            console.log("UI->S", "uimsg#" + JSON.stringify(data));
            ws.send("uimsg#" + JSON.stringify(data));
        }
    }

通过前后端精密的配合解决DotNetCore没跨平台ui的问题。同时实现CS界面和后端解耦合

zabbix监控打印机在不在线_zabbix监控打印机在不在线

zabbix监控打印机在不在线_开发语言_02

完美,哈哈,多平台可用,centos录屏不好弄,弹窗风格没windows好,总算实现了完全跨平台了