import { onHide, onShow, onUnload } from '@dcloudio/uni-app' const androidKeyCodeMap = { 7: '0', 8: '1', 9: '2', 10: '3', 11: '4', 12: '5', 13: '6', 14: '7', 15: '8', 16: '9', 29: 'A', 30: 'B', 31: 'C', 32: 'D', 33: 'E', 34: 'F', 35: 'G', 36: 'H', 37: 'I', 38: 'J', 39: 'K', 40: 'L', 41: 'M', 42: 'N', 43: 'O', 44: 'P', 45: 'Q', 46: 'R', 47: 'S', 48: 'T', 49: 'U', 50: 'V', 51: 'W', 52: 'X', 53: 'Y', 54: 'Z', 55: ',', 56: '.', 69: '-', 70: '=', 71: '[', 72: ']', 73: '\\', 74: ';', 75: "'", 76: '/', 81: '+' } export function useScannerInput(options = {}) { const minLength = Number(options.minLength ?? 3) const commitDelay = Number(options.commitDelay ?? 120) const uppercase = options.uppercase !== false const ignoreInputTarget = options.ignoreInputTarget !== false const hideKeyboardOnScan = options.hideKeyboardOnScan !== false const hideKeyboardOnLeave = options.hideKeyboardOnLeave !== false const onScan = typeof options.onScan === 'function' ? options.onScan : () => {} let scannerBuffer = '' let scannerTimer = null let scannerListening = false let plusKeyListening = false function getScannerEventTarget() { if (typeof document !== 'undefined') return document if (typeof window !== 'undefined') return window return null } function registerScannerListener() { if (scannerListening) return const target = getScannerEventTarget() if (target?.addEventListener) { target.addEventListener('keydown', handleScannerKeydown) scannerListening = true } registerPlusKeyListener() } function unregisterScannerListener() { const target = getScannerEventTarget() if (scannerListening && target?.removeEventListener) { target.removeEventListener('keydown', handleScannerKeydown) } scannerListening = false unregisterPlusKeyListener() clearScannerBuffer() if (hideKeyboardOnLeave) hideSoftKeyboard() } function registerPlusKeyListener() { if (plusKeyListening) return if (typeof plus === 'undefined' || !plus?.key?.addEventListener) return plus.key.addEventListener('keydown', handlePlusScannerKeydown) plusKeyListening = true } function unregisterPlusKeyListener() { if (!plusKeyListening) return if (typeof plus !== 'undefined' && plus?.key?.removeEventListener) { plus.key.removeEventListener('keydown', handlePlusScannerKeydown) } plusKeyListening = false } function handlePlusScannerKeydown(event) { handleScannerKeydown({ ...event, isPlusKeyEvent: true }) } function handleScannerKeydown(event) { if (ignoreInputTarget) { const targetTag = String(event?.target?.tagName || '').toLowerCase() if (targetTag === 'input' || targetTag === 'textarea') return } const key = normalizeScannerKey(event) if (!key) return if (key === 'Enter') { commitScannerBuffer() return } scannerBuffer += key if (scannerTimer) clearTimeout(scannerTimer) scannerTimer = setTimeout(() => { commitScannerBuffer() }, commitDelay) } function normalizeScannerKey(event) { if (event?.ctrlKey || event?.altKey || event?.metaKey) return '' if (isAndroidPlusKeyEvent(event)) return normalizeAndroidKeyCode(event) const key = event?.key if (key === 'Enter' || key === 'Tab') return 'Enter' if (typeof key === 'string' && key.length === 1) return uppercase ? key.toUpperCase() : key const code = Number(event?.keyCode || event?.which || 0) if (code === 13 || code === 9) return 'Enter' if (code >= 48 && code <= 90) { const value = String.fromCharCode(code) return uppercase ? value.toUpperCase() : value } if (code >= 96 && code <= 105) return String(code - 96) if (code === 189 || code === 109) return '-' if (code === 190 || code === 110) return '.' return '' } function isAndroidPlusKeyEvent(event) { return Boolean(event?.isPlusKeyEvent) } function normalizeAndroidKeyCode(event) { const code = Number(event?.keyCode || event?.which || 0) if (code === 66 || code === 61 || code === 160) return 'Enter' const value = androidKeyCodeMap[code] || '' return uppercase ? value.toUpperCase() : value.toLowerCase() } function clearScannerBuffer() { scannerBuffer = '' if (scannerTimer) { clearTimeout(scannerTimer) scannerTimer = null } } async function commitScannerBuffer() { const value = scannerBuffer.trim() clearScannerBuffer() if (value.length < minLength) return if (hideKeyboardOnScan) hideSoftKeyboard() await onScan(value) } function hideSoftKeyboard() { try { uni.hideKeyboard() } catch (e) {} } onShow(() => { registerScannerListener() }) onHide(() => { unregisterScannerListener() }) onUnload(() => { unregisterScannerListener() }) return { clearScannerBuffer, registerScannerListener, unregisterScannerListener } }