This commit is contained in:
iqudoo
2026-06-09 12:26:14 +08:00
parent fb3a4b4e06
commit 0b1b145b9c
6 changed files with 76 additions and 29 deletions

10
dist/index.d.ts vendored
View File

@@ -363,15 +363,17 @@ interface IScan {
*/
stopScan(): void;
/**
* 开启扫码
* 开启扫码(摄像头 / 桥接 / 微信等)
* @param key 可选,指定后结果仅分发给同 key 的 onScanListener
*/
startScan(): void;
startScan(key?: string): void;
/**
* 选择图片进行识别
* @param key 可选,指定后结果仅分发给同 key 的 onScanListener
*/
scanImage(): void;
scanImage(key?: string): void;
/** 由业务/原生传入已选图片 File 识别WebView input.files 异常时使用) */
scanImageFromFile(file: File | Blob): void;
scanImageFromFile(file: File | Blob, key?: string): void;
/**
* 清除全部监听
*/

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -120,7 +120,7 @@ function hydrateEmbedParams(params, messageSource, targetOrigin) {
return params.map(walk);
}
function broadcastScanErrorToEmbedChildren(error) {
function broadcastScanErrorToEmbedChildren(error, meta) {
if (embedChildSources.size === 0 || error == null || error === "") {
return;
}
@@ -132,6 +132,7 @@ function broadcastScanErrorToEmbedChildren(error) {
v: EMBED_V,
kind: "forwardScanError",
error,
scanKey: meta && meta.scanKey,
},
"*"
);
@@ -153,6 +154,7 @@ function broadcastScanResultToEmbedChildren(result, meta) {
kind: "forwardScanResult",
result,
scanSource: meta && meta.source,
scanKey: meta && meta.scanKey,
},
"*"
);
@@ -221,6 +223,7 @@ function embedChildOnMessage(ev) {
if (typeof data.result === "string") {
const consumed = dispatchEmbedScanResult(data.result, {
source: data.scanSource,
scanKey: data.scanKey,
});
if (consumed && resolveUseParentProxy()) {
window.parent.postMessage(
@@ -238,7 +241,9 @@ function embedChildOnMessage(ev) {
}
if (data.kind === "forwardScanError") {
if (typeof data.error === "string") {
dispatchEmbedScanError(data.error);
dispatchEmbedScanError(data.error, {
scanKey: data.scanKey,
});
}
return;
}

View File

@@ -17,8 +17,8 @@ export function forwardEmbedScanResultIfNeeded(result, meta) {
}
}
export function forwardEmbedScanErrorIfNeeded(error) {
export function forwardEmbedScanErrorIfNeeded(error, meta) {
if (embedScanErrorForwarder && error != null && error !== "") {
embedScanErrorForwarder(error);
embedScanErrorForwarder(error, meta);
}
}

View File

@@ -27,6 +27,7 @@ let _scan_error_listener_list = [];
let _scan_resolve = null;
let _scan_closing = false;
let _scan_next_start_time = 0;
let _scan_session_key = null;
let _embed_scan_host_enabled = false;
const SCAN_RESTART_DELAY = 500;
@@ -160,6 +161,26 @@ function __match(result, match) {
return true;
}
function __resolveScanKey(meta) {
if (meta && meta.scanKey === null) {
return null;
}
if (meta && typeof meta.scanKey === "string" && meta.scanKey) {
return meta.scanKey;
}
if (meta && meta.source === "scanner") {
return null;
}
return _scan_session_key;
}
function __listenerMatches(item, result, scanKey) {
if (scanKey && item.key !== scanKey) {
return false;
}
return __match(result, item.match);
}
function __shouldSkipBeep(meta) {
if (meta && meta.skipBeep) {
return true;
@@ -186,11 +207,12 @@ function __isScanCancel(raw) {
function __result(result, meta) {
result = parseBarcodeString(result);
forwardEmbedScanResultIfNeeded(result, meta);
const scanKey = __resolveScanKey(meta);
forwardEmbedScanResultIfNeeded(result, Object.assign({}, meta, { scanKey }));
let matched = false;
for (let i = 0; i < _scan_listener_list.length; i++) {
const item = _scan_listener_list[i];
if (item.listener && __match(result, item.match)) {
if (item.listener && __listenerMatches(item, result, scanKey)) {
matched = true;
item.listener({ result, key: item.key });
break;
@@ -226,11 +248,12 @@ function __scanError(raw, meta) {
if (!error) {
return false;
}
forwardEmbedScanErrorIfNeeded(error);
const scanKey = __resolveScanKey(meta);
forwardEmbedScanErrorIfNeeded(error, Object.assign({}, meta, { scanKey }));
let matched = false;
for (let i = 0; i < _scan_error_listener_list.length; i++) {
const item = _scan_error_listener_list[i];
if (item.listener && __match(error, item.match)) {
if (item.listener && __listenerMatches(item, error, scanKey)) {
matched = true;
item.listener(Object.assign({
error,
@@ -267,16 +290,25 @@ function __notifyWebScanFailure(raw, meta) {
return notified;
}
function __hasMatchedListener(result) {
function __hasMatchedListener(result, meta) {
const scanKey = __resolveScanKey(meta);
for (let i = 0; i < _scan_listener_list.length; i++) {
const item = _scan_listener_list[i];
if (item.listener && __match(result, item.match)) {
if (item.listener && __listenerMatches(item, result, scanKey)) {
return true;
}
}
return false;
}
function __clearScanSessionKey() {
_scan_session_key = null;
}
function __beginScanSession(key) {
_scan_session_key = typeof key === "string" && key ? key : null;
}
function __scanning() {
if (_scan_status !== "scanning") {
_scan_status = "scanning";
@@ -329,9 +361,9 @@ export function dispatchEmbedScanResult(raw, meta) {
* 父页通过 postMessage 将识别错误投递到嵌入 iframe 时调用。
* @returns {boolean} 是否有监听消费了该错误
*/
export function dispatchEmbedScanError(raw) {
export function dispatchEmbedScanError(raw, meta) {
const error = normalizeScanError(raw);
return __scanError(error, { source: "image" });
return __scanError(error, Object.assign({ source: "image" }, meta || {}));
}
/**
@@ -355,7 +387,7 @@ export function acknowledgeEmbedScanConsumed(raw) {
}
function __scannerResult(result, meta) {
if (!__hasMatchedListener(result)) {
if (!__hasMatchedListener(result, meta)) {
return __result(result, meta);
}
if (isScanning()) {
@@ -458,7 +490,7 @@ function __startWebScan(useImageScan = false) {
}
return resp;
}
__result(resp.result);
__result(resp.result, { source: "web" });
return resp;
}).catch(err => {
if (!isScanning()) {
@@ -495,7 +527,7 @@ function __startImageScan() {
__notifyImageScanFailure(resp);
return resp;
}
__result(resp.result);
__result(resp.result, { source: "image" });
return resp;
}).catch(err => {
if (!isScanning()) {
@@ -505,7 +537,7 @@ function __startImageScan() {
return err;
}
if (err && err.result) {
__result(err.result);
__result(err.result, { source: "image" });
return err;
}
__notifyImageScanFailure(err);
@@ -686,12 +718,13 @@ export function stopScan() {
});
}
export function startScan() {
export function startScan(key) {
if (isScanning() || _scan_closing || Date.now() < _scan_next_start_time) {
return;
}
unlockScanBeep();
Promise.resolve().then(() => {
__beginScanSession(key);
__scanning();
let scannerPromise = new Promise(resolve => {
_scan_resolve = resolve;
@@ -711,11 +744,12 @@ export function startScan() {
return withScanSessionTimeout(Promise.race([scanPromise, scannerPromise]));
}).finally(() => {
_scan_resolve = null;
__clearScanSessionKey();
__closed();
});
}
export function scanImage() {
export function scanImage(key) {
if (!isSupportImageScan()) {
printDebug("Not support image scanner");
return;
@@ -724,6 +758,7 @@ export function scanImage() {
return;
}
unlockScanBeep();
__beginScanSession(key);
__scanning();
withScanSessionTimeout(__startImageScan()).catch(err => {
if (err && err.cancel) {
@@ -731,12 +766,13 @@ export function scanImage() {
}
__notifyImageScanFailure(err);
}).finally(() => {
__clearScanSessionKey();
__closed();
});
}
/** 由原生/业务传入已选图片 File避免 WebView 无法从 input.files 取文件 */
export function scanImageFromFile(file) {
export function scanImageFromFile(file, key) {
if (!isSupportImageScan()) {
printDebug("Not support image scanner");
return;
@@ -746,6 +782,7 @@ export function scanImageFromFile(file) {
}
unlockScanBeep();
cleanupWebScanResiduals();
__beginScanSession(key);
__scanning();
withScanSessionTimeout(
detectImageFileForScan(file).then(resp => {
@@ -759,7 +796,7 @@ export function scanImageFromFile(file) {
__notifyImageScanFailure(resp);
return resp;
}
__result(resp.result);
__result(resp.result, { source: "image" });
return resp;
})
).catch(err => {
@@ -768,6 +805,7 @@ export function scanImageFromFile(file) {
}
__notifyImageScanFailure(err);
}).finally(() => {
__clearScanSessionKey();
__closed();
});
}

10
types/index.d.ts vendored
View File

@@ -363,15 +363,17 @@ interface IScan {
*/
stopScan(): void;
/**
* 开启扫码
* 开启扫码(摄像头 / 桥接 / 微信等)
* @param key 可选,指定后结果仅分发给同 key 的 onScanListener
*/
startScan(): void;
startScan(key?: string): void;
/**
* 选择图片进行识别
* @param key 可选,指定后结果仅分发给同 key 的 onScanListener
*/
scanImage(): void;
scanImage(key?: string): void;
/** 由业务/原生传入已选图片 File 识别WebView input.files 异常时使用) */
scanImageFromFile(file: File | Blob): void;
scanImageFromFile(file: File | Blob, key?: string): void;
/**
* 清除全部监听
*/