UNPKG

scanonweb

Version:

ScanOnWeb - 扫描控件 JavaScript SDK,支持 v2 协议、scanSource 和增量图像事件

10 lines (9 loc) 13.5 kB
/*! * scanonweb v2.0.1 * ScanOnWeb - 扫描控件 JavaScript SDK,支持 v2 协议、scanSource 和增量图像事件 * https://www.brainysoft.cn * * Copyright (c) 2026 BrainySoft * Licensed under the MIT license */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).ScanOnWeb=t()}(this,(function(){"use strict";class e{constructor(){this.protocolVersion=2,this.serverProtocolVersion=null,this.imageCount=0,this.scaner_work_config={showUI:!1,dpi_x:300,dpi_y:300,deviceIndex:0,showDialog:!1,scanSource:"flatbed",autoFeed:!1,dupxMode:!1,autoDeskew:!1,autoBorderDetection:!1,colorMode:"RGB",transMode:"memory"},this.h5socket=null,this.tryConnect()}getConnectedServer(e){return console.log("尝试连接托盘扫描服务websocket服务器..."),new Promise(((t,o)=>{const a=new WebSocket(e[0]);a.onopen=()=>{t(a)},a.onerror=e=>{o(e)}})).then((e=>(console.log("连接websocket服务器成功!"),this.initWebsocketCallback(e),console.log("尝试获取扫描设备列表..."),this.loadDevices(),e)),(t=>{if(e.length>1)return this.getConnectedServer(e.slice(1));throw t}))}tryConnect(){this.getConnectedServer(["ws://127.0.0.1:2001","ws://127.0.0.1:3001","ws://127.0.0.1:4001","ws://127.0.0.1:5001"])}initWebsocketCallback(e){this.h5socket=e,this.h5socket.onerror=this.onSocketError.bind(this),this.h5socket.onmessage=this.onSocketMessage.bind(this)}onSocketError(e){alert("无法连接扫描服务程序,请检查扫描服务程序是否已经启动!"),console.log("WebSocket error: "+e.data)}isCallbackExist(e){return!(!e||void 0===e||void 0===e)&&"function"==typeof e}dispatchCallback(e,t){this.isCallbackExist(this[e])&&this[e](t)}isUploadCommandType(e){return"uploadAllImageAsPdfToUrl"===e||"uploadAllImageAsTiffToUrl"===e||"uploadJpgImageByIndex"===e}extractUploadResult(e){if(!e||"object"!=typeof e)return null;const t=[e.uploadResultJson,e.uploadResult];for(const e of t)if(e){if("object"==typeof e)return e;if("string"==typeof e)try{return JSON.parse(e)}catch(e){}}return"string"==typeof e.message||"string"==typeof e.msg||"string"==typeof e.error?{success:!0===e.success||!0===e.ok,message:e.message||e.msg||e.error||"",error:e.error||e.message||e.msg||"",raw:"string"==typeof e.uploadResult?e.uploadResult:null}:null}resolveUploadMessage(e,t){const o=this.extractUploadResult(e),a=[o&&o.message,o&&o.error,e&&e.message,e&&e.msg,e&&e.error];for(const e of a)if("string"==typeof e&&e.trim())return e.trim();return"string"==typeof t?t:""}normalizeUploadHeaderValue(e,t="header value"){if("string"==typeof e)return e;if("number"==typeof e||"boolean"==typeof e)return String(e);throw new Error(`${t} must be a string, number, or boolean`)}normalizeUploadRequestHeadersInput(e){if(null==e)return[];if(Array.isArray(e))return e.map(((e,t)=>{if(!e||"object"!=typeof e)throw new Error(`headers[${t}] must be an object`);const o="string"==typeof e.name?e.name.trim():"";if(!o)throw new Error(`headers[${t}].name must be a non-empty string`);return{name:o,value:this.normalizeUploadHeaderValue(e.value,`headers[${t}].value`)}}));if("object"==typeof e)return Object.keys(e).map((t=>({name:t,value:this.normalizeUploadHeaderValue(e[t],`headers['${t}']`)})));throw new Error("upload request headers must be an object, array, or null")}normalizeUploadMessage(e){if(!e||"object"!=typeof e||!this.isUploadCommandType(e.cmd_type))return e;const t=this.extractUploadResult(e);if(!t)return e;e.uploadResultJson=t,e.uploadSucceeded="boolean"==typeof t.success?t.success:!0===e.success||!0===e.ok;const o=this.resolveUploadMessage(e,"");return o&&(e.uploadMessage=o,e.message||(e.message=o),e.msg||(e.msg=o),!1!==e.uploadSucceeded||e.error||(e.error=o)),e}toBoolCompat(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const t=e.trim().toLowerCase();return["1","true","yes","y","on","adf"].includes(t)}return!!e}toIntCompat(e,t){const o=Number(e);return Number.isInteger(o)?o:t}normalizeScanSource(e,t){if("string"==typeof e){const t=e.trim().toLowerCase();if("adf"===t||"feeder"===t||"documentfeeder"===t||"document_feeder"===t||"automatic_document_feeder"===t)return"adf";if("flatbed"===t||"flat_bed"===t||"platen"===t)return"flatbed"}return this.toBoolCompat(t)?"adf":"flatbed"}getLegacyAutoFeedEnable(e){return"adf"===this.normalizeScanSource(e)}shouldIncludeLegacyAutoFeedEnable(){return null===this.serverProtocolVersion||this.serverProtocolVersion<2}normalizeScanConfig(e,t){const o=Object.assign({},this.scaner_work_config,e||{}),a=!t||!1!==t.includeLegacyAutoFeedEnable,s={showUI:this.toBoolCompat(o.showUI),dpi_x:this.toIntCompat(o.dpi_x,300),dpi_y:this.toIntCompat(o.dpi_y,300),deviceIndex:this.toIntCompat(o.deviceIndex,0),showDialog:this.toBoolCompat(o.showDialog),scanSource:this.normalizeScanSource(o.scanSource,o.autoFeedEnable),autoFeed:this.toBoolCompat(o.autoFeed),dupxMode:this.toBoolCompat(o.dupxMode),autoDeskew:this.toBoolCompat(o.autoDeskew),autoBorderDetection:this.toBoolCompat(o.autoBorderDetection),colorMode:o.colorMode||"RGB",transMode:o.transMode||"memory"};return a&&(s.autoFeedEnable=this.getLegacyAutoFeedEnable(s.scanSource)),s}recordServerProtocolVersion(e){const t=this.toIntCompat(e&&e.protocolVersion,1);return this.serverProtocolVersion=t,t}applyIncomingScanConfig(e){this.scaner_work_config.deviceIndex=this.toIntCompat(e.currentIndex,this.scaner_work_config.deviceIndex),Object.prototype.hasOwnProperty.call(e,"showDialog")&&(this.scaner_work_config.showDialog=this.toBoolCompat(e.showDialog)),this.scaner_work_config.scanSource=this.normalizeScanSource(e.scanSource,e.autoFeedEnable),Object.prototype.hasOwnProperty.call(e,"autoFeed")&&(this.scaner_work_config.autoFeed=this.toBoolCompat(e.autoFeed)),Object.prototype.hasOwnProperty.call(e,"dupxMode")&&(this.scaner_work_config.dupxMode=this.toBoolCompat(e.dupxMode)),Object.prototype.hasOwnProperty.call(e,"autoDeskew")&&(this.scaner_work_config.autoDeskew=this.toBoolCompat(e.autoDeskew)),Object.prototype.hasOwnProperty.call(e,"autoBorderDetection")&&(this.scaner_work_config.autoBorderDetection=this.toBoolCompat(e.autoBorderDetection)),"string"==typeof e.colorMode&&e.colorMode&&(this.scaner_work_config.colorMode=e.colorMode),"string"==typeof e.transMode&&e.transMode&&(this.scaner_work_config.transMode=e.transMode),this.scaner_work_config.autoFeedEnable=this.getLegacyAutoFeedEnable(this.scaner_work_config.scanSource)}normalizeIncomingMessage(e){const t=Object.assign({},e||{}),o=this.recordServerProtocolVersion(t),a="string"==typeof t.cmd_type?t.cmd_type:"";switch(t.scanSource||(t.scanSource=this.normalizeScanSource(t.scanSource,t.autoFeedEnable)),a){case"getAllImage":t.cmd_type="imageListSnapshot";break;case"getImageById":t.cmd_type="imageSnapshot";break;case"imageDrap":t.cmd_type="imageMoved"}return t.protocolVersion||(t.protocolVersion=o),this.normalizeUploadMessage(t),t}onSocketMessage(e){const t=JSON.parse(e.data),o=this.normalizeIncomingMessage(t);switch("number"==typeof o.imageCount&&(this.imageCount=o.imageCount),o.cmd_type){case"getDevicesList":this.dispatchCallback("onGetDevicesListEvent",o);break;case"scanComplete":this.dispatchCallback("onScanFinishedEvent",o);break;case"selectScanDevice":this.applyIncomingScanConfig(o),this.dispatchCallback("onSelectScanDeviceEvent",o);break;case"getImageCount":this.dispatchCallback("onGetImageCountEvent",o);break;case"imageListSnapshot":this.dispatchCallback("onImageListSnapshotEvent",o),this.dispatchCallback("onGetAllImageEvent",o);break;case"imageSnapshot":this.dispatchCallback("onImageSnapshotEvent",o),this.dispatchCallback("onGetImageByIdEvent",o);break;case"scanPageAdded":this.dispatchCallback("onScanPageAddedEvent",o);break;case"loadImageFromUrl":this.dispatchCallback("onLoadImageFromUrlEvent",o);break;case"loadImageFromBase64":this.dispatchCallback("onLoadImageFromBase64Event",o);break;case"rotateImage":this.dispatchCallback("onRotateImageEvent",o);break;case"getImageSize":this.dispatchCallback("onGetImageSizeEvent",o);break;case"uploadAllImageAsPdfToUrl":this.dispatchCallback("onUploadAllImageAsPdfToUrlEvent",o);break;case"uploadAllImageAsTiffToUrl":this.dispatchCallback("onUploadAllImageAsTiffToUrlEvent",o);break;case"uploadJpgImageByIndex":this.dispatchCallback("onUploadJpgImageByIndexEvent",o);break;case"setUploadRequestHeaders":this.dispatchCallback("onSetUploadRequestHeadersEvent",o);break;case"upload":this.dispatchCallback("onUploadEvent",o);break;case"openClientLocalMultipageFile":this.dispatchCallback("onOpenClientLocalMultipageFileEvent",o);break;case"imageEdited":this.dispatchCallback("onImageEditedEvent",o);break;case"imageMoved":this.dispatchCallback("onImageMovedEvent",o),this.dispatchCallback("onImageDrapEvent",o);break;case"imageDeleted":this.dispatchCallback("onImageDeletedEvent",o);break;case"imagesCleared":this.dispatchCallback("onImagesClearedEvent",o)}}normalizeOutgoingCommand(e){const t=Object.assign({},e||{});return t.protocolVersion=this.protocolVersion,"startScan"===t.cmd_type&&(t.config=this.normalizeScanConfig(t.config||this.scaner_work_config,{includeLegacyAutoFeedEnable:this.shouldIncludeLegacyAutoFeedEnable()})),t}sendWebSocketCommand(e){try{this.h5socket&&1===this.h5socket.readyState?this.h5socket.send(JSON.stringify(this.normalizeOutgoingCommand(e))):alert("发送扫描指令失败!请刷新页面或者检查托盘扫描程序是否已经正常运行!")}catch(e){alert("发送扫描指令失败!"+e)}}setLicenseKey(e,t,o,a){this.sendWebSocketCommand({cmd_type:"setLicenseKey",licenseMode:e,key1:t,key2:o,url:a})}loadDevices(){this.sendWebSocketCommand({cmd_type:"getDevicesList"})}selectScanDevice(e){this.sendWebSocketCommand({cmd_type:"selectScanDevice",deviceIndex:e})}startScan(){this.sendWebSocketCommand({cmd_type:"startScan",config:this.scaner_work_config})}clearAll(){this.sendWebSocketCommand({cmd_type:"clearAll"})}getImageCount(){this.sendWebSocketCommand({cmd_type:"getImageCount"})}getAllImage(){this.sendWebSocketCommand({cmd_type:"getAllImage"})}getImageById(e){const t={cmd_type:"getImageById"};"string"==typeof e&&e.trim()?t.imageId=e.trim():t.index=e,this.sendWebSocketCommand(t)}loadImageFromUrl(e,t){if(!t){const o=e.split(".").pop().toLowerCase();t="pdf"===o?"pdf":"tiff"===o||"tif"===o?"tiff":(["jpg","jpeg","png","bmp","gif","webp"].includes(o),"image")}this.sendWebSocketCommand({cmd_type:"loadImageFromUrl",url:e,type:t})}loadImageFromBase64(e,t){let o=t||"jpg",a=e;if(a.startsWith("data:")){const e=a.indexOf("base64,");if(-1!==e){if(!t){const e=a.match(/data:image\/(\w+);/);e&&e[1]&&(o="jpeg"===e[1]?"jpg":e[1])}a=a.substring(e+7)}}this.sendWebSocketCommand({cmd_type:"loadImageFromBase64",base64Data:a,format:o})}rotateImage(e,t){this.sendWebSocketCommand({cmd_type:"rotateImage",index:e,angle:t})}getImageSize(e){this.sendWebSocketCommand({cmd_type:"getImageSize",index:e})}deleteImageByIndex(e,t){const o={cmd_type:"deleteImageByIndex",index:e};"string"==typeof t&&t.trim()&&(o.imageId=t.trim()),this.sendWebSocketCommand(o)}moveImage(e,t){this.sendWebSocketCommand({cmd_type:"moveImage",oldIndex:e,newIndex:t})}setUploadRequestHeaders(e){this.sendWebSocketCommand({cmd_type:"setUploadRequestHeaders",headers:this.normalizeUploadRequestHeadersInput(e)})}uploadAllImageAsPdfToUrl(e,t,o){this.sendWebSocketCommand({cmd_type:"uploadAllImageAsPdfToUrl",url:e,id:t,desc:o})}uploadAllImageAsTiffToUrl(e,t,o){this.sendWebSocketCommand({cmd_type:"uploadAllImageAsTiffToUrl",url:e,id:t,desc:o})}uploadJpgImageByIndex(e,t,o,a){this.sendWebSocketCommand({cmd_type:"uploadJpgImageByIndex",index:a,url:e,id:t,desc:o})}saveAllImageToLocal(e){this.sendWebSocketCommand({cmd_type:"saveAllImageToLocal",filename:e})}openClientLocalfile(){this.sendWebSocketCommand({cmd_type:"openClientLocalfile"})}openClientLocalMultipageFile(){this.sendWebSocketCommand({cmd_type:"openClientLocalMultipageFile"})}ftpUploadAllImage(e,t,o,a,s,n){this.sendWebSocketCommand({cmd_type:"ftpUploadAllImage",serverIp:e,port:t,username:o,password:a,serverPath:s,filename:n})}setUploadButtonVisible(e){this.sendWebSocketCommand({cmd_type:"setUploadButtonVisible",visible:e})}setFocus(){this.sendWebSocketCommand({cmd_type:"focus"})}hidden(){this.sendWebSocketCommand({cmd_type:"hidden"})}closeWebSocket(){this.h5socket.close()}loadMultipleImagesFromBase64(e){Array.isArray(e)&&0!==e.length?e.forEach(((e,t)=>{setTimeout((()=>{this.loadImageFromBase64(e.data,e.format||"jpg")}),100*t)})):console.error("loadMultipleImagesFromBase64: 参数必须是非空数组")}loadImageFromCanvas(e,t,o){const a=t||"jpg",s="number"==typeof o?o:.9;if(!(e&&e instanceof HTMLCanvasElement))return void console.error("loadImageFromCanvas: 参数必须是有效的Canvas元素");const n="jpg"===a?"image/jpeg":"image/"+a,r=e.toDataURL(n,s).split(",")[1];this.loadImageFromBase64(r,a)}loadImageFromFileInput(e){if(!e||!e.files||0===e.files.length)return void console.error("loadImageFromFileInput: 没有选择文件");Array.from(e.files).forEach(((e,t)=>{if(!e.type.startsWith("image/"))return void console.warn("跳过非图像文件: "+e.name);const o=new FileReader;o.onload=o=>{const a=o.target.result,s=e.name.split(".").pop().toLowerCase(),n="jpeg"===s?"jpg":s;setTimeout((()=>{this.loadImageFromBase64(a,n)}),100*t)},o.readAsDataURL(e)}))}}return"undefined"!=typeof module&&module.exports&&(module.exports=e),"undefined"!=typeof window&&(window.ScanOnWeb=e),e}));