useBarcode.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import { ref, onMounted, onUnmounted, onShow } from 'vue'
  2. import {
  3. useInit,
  4. useGlobalEvent,
  5. updateActivePageOnShow,
  6. cleanupOnPageUnload
  7. } from '@/utils/useBarcodeModule.js'
  8. /**
  9. * Vue3 Composable - 条码扫描
  10. * @param {Object} options 配置选项
  11. * @param {Function} options.onScan 扫描成功回调
  12. * @param {Function} options.onError 扫描失败回调
  13. * @param {boolean} options.autoInit 是否自动初始化
  14. */
  15. export function useBarcode(options = {}) {
  16. const {
  17. onScan,
  18. onError,
  19. autoInit = false
  20. } = options
  21. // 响应式状态
  22. const isScanning = ref(false)
  23. const isInitialized = ref(false)
  24. const scanResult = ref(null)
  25. const scanHistory = ref([])
  26. const error = ref(null)
  27. // 内部状态
  28. let removeListener = null
  29. /**
  30. * 初始化扫描器
  31. */
  32. const init = async () => {
  33. try {
  34. if (isInitialized.value) {
  35. console.warn('扫描器已经初始化')
  36. return true
  37. }
  38. useInit()
  39. isInitialized.value = true
  40. error.value = null
  41. console.log('扫描器初始化成功')
  42. return true
  43. } catch (err) {
  44. error.value = err
  45. if (onError) {
  46. onError(err)
  47. }
  48. console.error('扫描器初始化失败:', err)
  49. return false
  50. }
  51. }
  52. /**
  53. * 开始扫描
  54. */
  55. const startScan = async () => {
  56. try {
  57. // 确保扫描器已初始化
  58. if (!isInitialized.value) {
  59. const success = await init()
  60. if (!success) return false
  61. }
  62. if (isScanning.value) {
  63. console.warn('扫描器已经在运行中')
  64. return true
  65. }
  66. // 注册扫描事件监听
  67. removeListener = useGlobalEvent(handleScanResult)
  68. isScanning.value = true
  69. error.value = null
  70. console.log('开始扫描监听')
  71. return true
  72. } catch (err) {
  73. error.value = err
  74. if (onError) {
  75. onError(err)
  76. }
  77. console.error('开始扫描失败:', err)
  78. return false
  79. }
  80. }
  81. /**
  82. * 停止扫描
  83. */
  84. const stopScan = () => {
  85. try {
  86. if (removeListener) {
  87. removeListener()
  88. removeListener = null
  89. }
  90. isScanning.value = false
  91. console.log('停止扫描监听')
  92. return true
  93. } catch (err) {
  94. error.value = err
  95. if (onError) {
  96. onError(err)
  97. }
  98. console.error('停止扫描失败:', err)
  99. return false
  100. }
  101. }
  102. /**
  103. * 处理扫描结果
  104. */
  105. const handleScanResult = (result) => {
  106. try {
  107. console.log('收到扫描结果:', result)
  108. // 解析扫描结果
  109. const barcode = result.barcode || result.data || result.code || String(result)
  110. const timestamp = new Date().toLocaleString()
  111. const scanData = {
  112. barcode,
  113. timestamp,
  114. rawData: result
  115. }
  116. // 更新状态
  117. scanResult.value = scanData
  118. // 添加到历史记录
  119. scanHistory.value.unshift(scanData)
  120. // 限制历史记录数量
  121. if (scanHistory.value.length > 100) {
  122. scanHistory.value = scanHistory.value.slice(0, 100)
  123. }
  124. // 执行回调
  125. if (onScan) {
  126. onScan(scanData)
  127. }
  128. error.value = null
  129. } catch (err) {
  130. error.value = err
  131. if (onError) {
  132. onError(err)
  133. }
  134. console.error('处理扫描结果失败:', err)
  135. }
  136. }
  137. /**
  138. * 清空扫描历史
  139. */
  140. const clearHistory = () => {
  141. scanHistory.value = []
  142. scanResult.value = null
  143. }
  144. /**
  145. * 清理资源
  146. */
  147. const cleanup = () => {
  148. stopScan()
  149. cleanupOnPageUnload()
  150. }
  151. // 生命周期钩子
  152. onMounted(() => {
  153. if (autoInit) {
  154. init()
  155. }
  156. })
  157. onShow(() => {
  158. // 页面显示时更新活跃页面
  159. updateActivePageOnShow()
  160. })
  161. onUnmounted(() => {
  162. cleanup()
  163. })
  164. // 返回API
  165. return {
  166. // 状态
  167. isScanning,
  168. isInitialized,
  169. scanResult,
  170. scanHistory,
  171. error,
  172. // 方法
  173. init,
  174. startScan,
  175. stopScan,
  176. clearHistory,
  177. cleanup
  178. }
  179. }