UNPKG

scanonweb

Version:

ScanOnWeb - 扫描控件 JavaScript SDK,用于与本地扫描服务程序通信

587 lines (549 loc) 17.7 kB
/*! * scanonweb v1.0.1 * ScanOnWeb - 扫描控件 JavaScript SDK,用于与本地扫描服务程序通信 * https://www.brainysoft.cn * * Copyright (c) 2025 BrainySoft * Licensed under the MIT license */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ScanOnWeb = factory()); })(this, (function () { 'use strict'; /** * ScanOnWeb - 扫描控件 JavaScript SDK * https://www.brainysoft.cn 扫描控件官方网站,如需更多文档帮助请访问官网 * @version 1.0.1 * @author BrainySoft * @license MIT */ /** * 扫描控件类 - 用于与本地扫描服务程序通信 * @class ScanOnWeb */ class ScanOnWeb { constructor() { // 扫描配置参数信息,后续扫描仪开始扫描前会根据这个配置信息来进行扫描设置 this.scaner_work_config = { showUI: false, // 是否显示扫描控件工作界面,如果为false则不显示扫描控件工作界面 dpi_x: 300, // dpi 分辨率x,一般的图像扫描300dpi就够了 dpi_y: 300, // dpi 分辨率y deviceIndex: 0, // 选中的扫描仪硬件设备id索引,如果有多个扫描仪设备,这个值就是用来选择哪个设备进行扫描的 showDialog: false, // 是否显示设备内置对话框 autoFeedEnable: true, // 是否使用自动进纸器(需要设备支持才能正常工作) autoFeed: false, // 是否自动装填纸张(需要设备支持才能正常工作) dupxMode: false, // 是否使用双面扫描模式(需要设备支持才能正常工作) autoDeskew: false, // 是否使用自动纠偏模式(需要设备支持才能正常工作) autoBorderDetection: false, // 是否使用自动边框检测(需要设备支持才能正常工作) colorMode: "RGB", // 色彩模式,RGB为彩色模式,BW是黑白模式 ,GRAY是灰色模式 transMode: "memory" // 数据传输模式,memory,file,native 这三种配置值,默认为memory模式,大部分设备都是使用这种模式 }; this.h5socket = null; this.imageCount = 0; // 扫描结果图像总数 // 尝试连接websocket服务器,注意连接成功哪个是通过回调实现的 this.tryConnect(); } /** * 通过连接多个websocket server端口返回一个可用的websocket连接对象,主要用于防止本地端口被占用的情况 * @param {string[]} wssUrls - WebSocket服务器URL数组 * @returns {Promise} WebSocket连接Promise */ getConnectedServer(wssUrls) { console.log("尝试连接托盘扫描服务websocket服务器..."); return new Promise((resolve, reject) => { const server = new WebSocket(wssUrls[0]); server.onopen = () => { resolve(server); }; server.onerror = err => { reject(err); }; }).then(server => { console.log("连接websocket服务器成功!"); // 找到了可用websocket服务器端口 this.initWebsocketCallback(server); console.log("尝试获取扫描设备列表..."); // 发送一个获取扫描设备列表的命令,询问本地计算机安装了多少个扫描设备的驱动程序 this.loadDevices(); return server; }, err => { // 如果连接失败,则尝试连接其他端口 if (wssUrls.length > 1) { return this.getConnectedServer(wssUrls.slice(1)); } throw err; }); } /** * 尝试检测websocket哪个端口可以成功连接 */ tryConnect() { // 以下一共定义了5个websocket端口,如果有端口被占用,则会自动尝试连接下一个端口 const wssUrls = ["ws://127.0.0.1:1001", "ws://127.0.0.1:2001", "ws://127.0.0.1:3001", "ws://127.0.0.1:4001", "ws://127.0.0.1:5001"]; this.getConnectedServer(wssUrls); } /** * 初始化websocket相关的函数绑定 * @param {WebSocket} server - WebSocket服务器实例 */ initWebsocketCallback(server) { this.h5socket = server; this.h5socket.onerror = this.onSocketError.bind(this); this.h5socket.onmessage = this.onSocketMessage.bind(this); } /** * WebSocket错误处理 * @param {Event} event - 错误事件 */ onSocketError(event) { alert("无法连接扫描服务程序,请检查扫描服务程序是否已经启动!"); console.log("WebSocket error: " + event.data); } /** * 判断回调函数是否存在 * @param {Function} f - 要检查的函数 * @returns {boolean} 函数是否存在且为函数类型 */ isCallbackExist(f) { if (!f || typeof f === "undefined" || f === undefined) { return false; } return typeof f === "function"; } /** * WebSocket消息处理 * @param {MessageEvent} event - WebSocket消息事件 */ onSocketMessage(event) { const msg = JSON.parse(event.data); // console.log(msg); switch (msg.cmd_type) { case "getDevicesList": { // 获取设备信息列表返回结果 if (this.isCallbackExist(this.onGetDevicesListEvent)) { this.onGetDevicesListEvent(msg); } break; } case "scanComplete": { // 扫描完成 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onScanFinishedEvent)) { this.onScanFinishedEvent(msg); } break; } case "selectScanDevice": { // 选择扫描设备结果 this.scaner_work_config.deviceIndex = msg.currentIndex; // 当前选中的设备索引 this.scaner_work_config.showDialog = msg.showDialog; // 是否显示设备内置对话框 this.scaner_work_config.autoFeedEnable = msg.autoFeedEnable; // 是否使用自动进纸器(需要设备支持才能正常工作) this.scaner_work_config.autoFeed = msg.autoFeed; // 是否自动装填纸张(需要设备支持才能正常工作) this.scaner_work_config.dupxMode = msg.dupxMode; // 是否使用双面扫描模式(需要设备支持才能正常工作) this.scaner_work_config.autoDeskew = msg.autoDeskew; // 是否使用自动纠偏模式(需要设备支持才能正常工作) this.scaner_work_config.autoBorderDetection = msg.autoBorderDetection; // 是否使用自动边框检测(需要设备支持才能正常工作) if (this.isCallbackExist(this.onSelectScanDeviceEvent)) { this.onSelectScanDeviceEvent(msg); } break; } case "getImageCount": { // 获取扫描图片数量 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onGetImageCountEvent)) { this.onGetImageCountEvent(msg); } break; } case "getAllImage": { // 获取所有图片 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onGetAllImageEvent)) { this.onGetAllImageEvent(msg); } break; } case "getImageById": { // 获取某一页图片的base64编码数据 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onGetImageByIdEvent)) { this.onGetImageByIdEvent(msg); } break; } case "loadImageFromUrl": { // 从URL加载图片 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onLoadImageFromUrlEvent)) { this.onLoadImageFromUrlEvent(msg); } break; } case "rotateImage": { // 旋转图片 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onRotateImageEvent)) { this.onRotateImageEvent(msg); } break; } case "getImageSize": { // 获取图片尺寸 this.imageCount = msg.imageCount; if (this.isCallbackExist(this.onGetImageSizeEvent)) { this.onGetImageSizeEvent(msg); } break; } case "uploadAllImageAsPdfToUrl": { // 上传pdf图像到指定的URL的回调 if (this.isCallbackExist(this.onUploadAllImageAsPdfToUrlEvent)) { this.onUploadAllImageAsPdfToUrlEvent(msg); } break; } case "uploadAllImageAsTiffToUrl": { // 上传tiff图像到指定的URL的回调 if (this.isCallbackExist(this.onUploadAllImageAsTiffToUrlEvent)) { this.onUploadAllImageAsTiffToUrlEvent(msg); } break; } case "uploadJpgImageByIndex": { // 上传jpg图像到指定的URL的回调 if (this.isCallbackExist(this.onUploadJpgImageByIndexEvent)) { this.onUploadJpgImageByIndexEvent(msg); } break; } case "upload": { this.imageCount = msg.imageCount; // 用户点击了界面里面的"开始上传"按钮的时间回调 if (this.isCallbackExist(this.onUploadEvent)) { this.onUploadEvent(msg); } break; } case "imageEdited": { // 用户在扫描托盘程序里面对图片进行了编辑操作的回调 if (this.isCallbackExist(this.onImageEditedEvent)) { this.onImageEditedEvent(msg); } break; } case "imageDrap": { // 用户在扫描托盘程序里面对图片进行了拖拽操作的回调 if (this.isCallbackExist(this.onImageDrapEvent)) { this.onImageDrapEvent(msg); } break; } } } /** * 通过websocket发送数据给webscoket服务端 * @param {Object} commandData - 要发送的命令数据 */ sendWebSocketCommand(commandData) { try { if (this.h5socket.readyState === 1) { this.h5socket.send(JSON.stringify(commandData)); } else { alert("发送扫描指令失败!请刷新页面或者检查托盘扫描程序是否已经正常运行!"); } } catch (e) { alert("发送扫描指令失败!" + e); } } /** * 设置授权信息 * @param {string} licenseMode - 授权模式 * @param {string} key1 - 授权密钥1 * @param {string} key2 - 授权密钥2 * @param {string} licenseServerUrl - 授权服务器URL */ setLicenseKey(licenseMode, key1, key2, licenseServerUrl) { const cmdObj = { cmd_type: "setLicenseKey", licenseMode: licenseMode, key1: key1, key2: key2, url: licenseServerUrl }; this.sendWebSocketCommand(cmdObj); } /** * 加载所有可用的扫描设备 */ loadDevices() { const cmdObj = { cmd_type: "getDevicesList" }; this.sendWebSocketCommand(cmdObj); } /** * 设置当前选中的扫描设备id * @param {number} deviceIndex - 设备索引 */ selectScanDevice(deviceIndex) { const cmdObj = { cmd_type: "selectScanDevice", deviceIndex: deviceIndex }; this.sendWebSocketCommand(cmdObj); } /** * 开始扫描 */ startScan() { const cmdObj = { cmd_type: "startScan", config: this.scaner_work_config }; this.sendWebSocketCommand(cmdObj); } /** * 清除全部扫描结果 */ clearAll() { const cmdObj = { cmd_type: "clearAll" }; this.sendWebSocketCommand(cmdObj); } /** * 获取图像总数 */ getImageCount() { const cmdObj = { cmd_type: "getImageCount" }; this.sendWebSocketCommand(cmdObj); } /** * 获取所有图像 */ getAllImage() { const cmdObj = { cmd_type: "getAllImage" }; this.sendWebSocketCommand(cmdObj); } /** * 发送指令获取某一页图像到托盘服务 * @param {number} index - 图像索引 */ getImageById(index) { const cmdObj = { cmd_type: "getImageById", index: index }; this.sendWebSocketCommand(cmdObj); } /** * 发送指令远程加载服务器端的多页图像到托盘服务 * @param {string} url - 图像URL */ loadImageFromUrl(url) { const cmdObj = { cmd_type: "loadImageFromUrl", url: url }; this.sendWebSocketCommand(cmdObj); } /** * 发送指令旋转某一页图像到托盘服务 * @param {number} index - 图像索引 * @param {number} angle - 旋转角度 */ rotateImage(index, angle) { const cmdObj = { cmd_type: "rotateImage", index: index, angle: angle }; this.sendWebSocketCommand(cmdObj); } /** * 发送指令获取某一页图像的宽度到托盘服务 * @param {number} index - 图像索引 */ getImageSize(index) { const cmdObj = { cmd_type: "getImageSize", index: index }; this.sendWebSocketCommand(cmdObj); } /** * 发送指令删除某一页图像到托盘服务 * @param {number} index - 图像索引 */ deleteImageByIndex(index) { const cmdObj = { cmd_type: "deleteImageByIndex", index: index }; this.sendWebSocketCommand(cmdObj); } /** * 以pdf格式上传全部图像到服务器端 * @param {string} url - 上传URL * @param {string} id - 标识ID * @param {string} desc - 描述信息 */ uploadAllImageAsPdfToUrl(url, id, desc) { const cmdObj = { cmd_type: "uploadAllImageAsPdfToUrl", url: url, id: id, desc: desc }; this.sendWebSocketCommand(cmdObj); } /** * 以tiff格式上传全部图像到服务器端 * @param {string} url - 上传URL * @param {string} id - 标识ID * @param {string} desc - 描述信息 */ uploadAllImageAsTiffToUrl(url, id, desc) { const cmdObj = { cmd_type: "uploadAllImageAsTiffToUrl", url: url, id: id, desc: desc }; this.sendWebSocketCommand(cmdObj); } /** * 以jpg格式上传某一页图像到服务器端 * @param {string} url - 上传URL * @param {string} id - 标识ID * @param {string} desc - 描述信息 * @param {number} index - 图像索引 */ uploadJpgImageByIndex(url, id, desc, index) { const cmdObj = { cmd_type: "uploadJpgImageByIndex", index: index, url: url, id: id, desc: desc }; this.sendWebSocketCommand(cmdObj); } /** * 全部图像保存到客户端本地文件 * @param {string} filename - 文件名 */ saveAllImageToLocal(filename) { const cmdObj = { cmd_type: "saveAllImageToLocal", filename: filename }; this.sendWebSocketCommand(cmdObj); } /** * 从客户端本地读取图像,通过打开文件对话框选择图像文件 */ openClientLocalfile() { const cmdObj = { cmd_type: "openClientLocalfile" }; this.sendWebSocketCommand(cmdObj); } /** * ftp上传全部图像文件到服务器端 * @param {string} serverIp - 服务器IP * @param {number} port - 端口 * @param {string} username - 用户名 * @param {string} password - 密码 * @param {string} serverPath - 服务器路径 * @param {string} filename - 文件名 */ ftpUploadAllImage(serverIp, port, username, password, serverPath, filename) { const cmdObj = { cmd_type: "ftpUploadAllImage", serverIp: serverIp, port: port, username: username, password: password, serverPath: serverPath, filename: filename }; this.sendWebSocketCommand(cmdObj); } /** * 设置上传按钮是否可见 * @param {boolean} visible - 是否可见 */ setUploadButtonVisible(visible) { const cmdObj = { cmd_type: "setUploadButtonVisible", visible: visible }; this.sendWebSocketCommand(cmdObj); } /** * 设置焦点 */ setFocus() { const cmdObj = { cmd_type: "focus" }; this.sendWebSocketCommand(cmdObj); } /** * 隐藏窗口 */ hidden() { const cmdObj = { cmd_type: "hidden" }; this.sendWebSocketCommand(cmdObj); } /** * 关闭websocket连接 */ closeWebSocket() { this.h5socket.close(); } } // CommonJS 兼容性导出 if (typeof module !== "undefined" && module.exports) { module.exports = ScanOnWeb; } // UMD 兼容性导出 if (typeof window !== "undefined") { window.ScanOnWeb = ScanOnWeb; } return ScanOnWeb; }));