207 lines
4.4 KiB
Vue
207 lines
4.4 KiB
Vue
|
|
<template>
|
||
|
|
<view class="scan-view-container">
|
||
|
|
<!-- 扫码控件容器 -->
|
||
|
|
<view class="scan-box" id="scan-box"></view>
|
||
|
|
|
||
|
|
<!-- 扫码状态 -->
|
||
|
|
<view class="scan-status" v-if="isScanning">
|
||
|
|
<view class="scan-line"></view>
|
||
|
|
<text class="scan-text">正在扫描...</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 扫码控制按钮 -->
|
||
|
|
<view class="scan-controls" v-if="isScanning">
|
||
|
|
<view class="control-btn" @click="toggleFlash">
|
||
|
|
<uni-icons type="flash" size="22" color="#fff"></uni-icons>
|
||
|
|
<text class="control-text">{{ flashOn ? '关闭手电' : '开启手电' }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="control-btn" @click="pauseScan">
|
||
|
|
<uni-icons type="pause" size="22" color="#fff"></uni-icons>
|
||
|
|
<text class="control-text">{{ scanPaused ? '继续扫码' : '暂停扫码' }}</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
name: 'ScanView',
|
||
|
|
props: {
|
||
|
|
autoStart: {
|
||
|
|
type: Boolean,
|
||
|
|
default: false
|
||
|
|
}
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
isScanning: false,
|
||
|
|
scanPaused: false,
|
||
|
|
flashOn: false,
|
||
|
|
barcodeInstance: null
|
||
|
|
};
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
if (this.autoStart) {
|
||
|
|
this.initScan();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
beforeUnmount() {
|
||
|
|
this.closeScan();
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
initScan() {
|
||
|
|
if (typeof plus === 'undefined') {
|
||
|
|
console.log('当前环境不支持plus扫码');
|
||
|
|
this.$emit('error', '扫码功能需要在App中使用');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('开始初始化扫码控件');
|
||
|
|
this.isScanning = true;
|
||
|
|
|
||
|
|
const barcode = plus.barcode.create('barcode', [plus.barcode.CODE_128, plus.barcode.EAN_13], {
|
||
|
|
top: '0',
|
||
|
|
left: '0',
|
||
|
|
width: '100%',
|
||
|
|
height: '100%',
|
||
|
|
position: 'absolute'
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log('扫码控件创建成功');
|
||
|
|
|
||
|
|
barcode.onmarked = (type, result) => {
|
||
|
|
console.log('识别成功:', result);
|
||
|
|
this.isScanning = false;
|
||
|
|
this.$emit('success', result);
|
||
|
|
};
|
||
|
|
|
||
|
|
barcode.onerror = (error) => {
|
||
|
|
console.error('扫码错误:', error);
|
||
|
|
this.isScanning = false;
|
||
|
|
this.$emit('error', error || '扫码失败');
|
||
|
|
};
|
||
|
|
|
||
|
|
const scanBox = document.getElementById('scan-box');
|
||
|
|
if (scanBox) {
|
||
|
|
scanBox.appendChild(barcode);
|
||
|
|
}
|
||
|
|
|
||
|
|
barcode.start();
|
||
|
|
console.log('扫码已启动');
|
||
|
|
this.barcodeInstance = barcode;
|
||
|
|
},
|
||
|
|
|
||
|
|
closeScan() {
|
||
|
|
if (this.barcodeInstance) {
|
||
|
|
this.barcodeInstance.close();
|
||
|
|
this.barcodeInstance = null;
|
||
|
|
this.isScanning = false;
|
||
|
|
console.log('扫码控件已关闭');
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
pauseScan() {
|
||
|
|
this.scanPaused = !this.scanPaused;
|
||
|
|
if (this.barcodeInstance) {
|
||
|
|
this.scanPaused ? this.barcodeInstance.pause() : this.barcodeInstance.resume();
|
||
|
|
}
|
||
|
|
this.$emit('pause', this.scanPaused);
|
||
|
|
},
|
||
|
|
|
||
|
|
resumeScan() {
|
||
|
|
if (this.barcodeInstance && this.scanPaused) {
|
||
|
|
this.barcodeInstance.resume();
|
||
|
|
this.scanPaused = false;
|
||
|
|
this.isScanning = true;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
toggleFlash() {
|
||
|
|
this.flashOn = !this.flashOn;
|
||
|
|
if (this.barcodeInstance) {
|
||
|
|
this.barcodeInstance.setFlash(this.flashOn);
|
||
|
|
}
|
||
|
|
this.$emit('flash', this.flashOn);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.scan-view-container {
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
position: relative;
|
||
|
|
background-color: #000;
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-box {
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-status {
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
background-color: rgba(0, 0, 0, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-line {
|
||
|
|
width: 80%;
|
||
|
|
height: 2px;
|
||
|
|
background-color: #e60012;
|
||
|
|
animation: scanMove 2s infinite;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes scanMove {
|
||
|
|
0% {
|
||
|
|
transform: translateY(0);
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
50% {
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
100% {
|
||
|
|
transform: translateY(250px);
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-text {
|
||
|
|
color: #fff;
|
||
|
|
font-size: 16px;
|
||
|
|
margin-top: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-controls {
|
||
|
|
position: absolute;
|
||
|
|
bottom: 30px;
|
||
|
|
left: 0;
|
||
|
|
width: 100%;
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-around;
|
||
|
|
padding: 0 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.control-btn {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
color: #fff;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
.control-text {
|
||
|
|
font-size: 12px;
|
||
|
|
margin-top: 5px;
|
||
|
|
}
|
||
|
|
</style>
|