| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <template>
- <view class="custom-scan-container">
- <!-- 扫码区域 -->
- <view id="barcodeView" class="barcode-view">
- <!-- 扫码框和动画效果 -->
- <view class="scan-frame">
- <view class="scan-line-animation"></view>
- <view class="corner top-left"></view>
- <view class="corner top-right"></view>
- <view class="corner bottom-left"></view>
- <view class="corner bottom-right"></view>
- </view>
- </view>
-
- <!-- 控制面板 -->
- <view class="control-panel">
- <button class="control-btn" @tap="toggleFlash">
- <text class="icon">🔅</text>
- <text>{{ flashOn ? '关闭闪光灯' : '打开闪光灯' }}</text>
- </button>
-
- <button class="control-btn" @tap="switchCamera">
- <text class="icon">📷</text>
- <text>切换摄像头</text>
- </button>
-
- <button class="control-btn" @tap="stopScan">
- <text class="icon">✖</text>
- <text>停止扫码</text>
- </button>
- </view>
-
- <!-- 结果展示 -->
- <view v-if="scanResult" class="result-panel">
- <text class="result-title">扫码结果:</text>
- <text class="result-content">{{ scanResult }}</text>
- </view>
- </view>
- </template>
- <script>
- export default {
- data() {
- return {
- barcodeInstance: null,
- flashOn: false,
- scanResult: '',
- isScanning: false
- }
- },
-
- onLoad() {
- // 页面加载时初始化扫码
- this.initBarcodeScan();
- },
-
- onUnload() {
- // 页面卸载时释放资源
- this.stopScan();
- },
-
- methods: {
- // 初始化扫码功能
- initBarcodeScan() {
- // 判断运行环境
- if (plus.os.name === 'iOS' || plus.os.name === 'Android') {
- this.initAppBarcode();
- } else {
- this.initH5Barcode();
- }
- },
-
- // App端初始化
- initAppBarcode() {
- const currentWebview = plus.webview.currentWebview();
-
- this.barcodeInstance = plus.barcode.create('barcode', [
- plus.barcode.QR,
- plus.barcode.EAN8,
- plus.barcode.EAN13,
- plus.barcode.CODE128
- ], {
- top: '0px',
- left: '0px',
- width: '100%',
- height: '70%',
- position: 'static',
- frameColor: '#00FF00',
- scanbarColor: '#00FF00'
- });
-
- // 设置扫码回调
- this.barcodeInstance.onmarked = (type, result) => {
- this.handleScanSuccess(type, result);
- };
-
- // 开始扫码
- this.barcodeInstance.start();
- this.isScanning = true;
-
- currentWebview.append(this.barcodeInstance);
- },
-
- // H5端初始化
- initH5Barcode() {
- // 使用之前提到的ZXing.js方案
- this.startH5Scan();
- },
-
- // 处理扫码成功
- handleScanSuccess(type, result) {
- this.scanResult = result;
- console.log(`扫码类型:${type},结果:${result}`);
-
- // 显示成功提示
- uni.showToast({
- title: '扫码成功',
- icon: 'success'
- });
-
- // 可选:震动反馈
- if (plus.os.name === 'iOS' || plus.os.name === 'Android') {
- plus.vibrate.vibrate(200);
- }
-
- // 触发自定义事件
- this.$emit('scanSuccess', { type, result });
- },
-
- // 切换闪光灯
- toggleFlash() {
- if (this.barcodeInstance) {
- this.flashOn = !this.flashOn;
- this.barcodeInstance.setFlash(this.flashOn);
- }
- },
-
- // 切换摄像头
- switchCamera() {
- if (this.barcodeInstance) {
- this.barcodeInstance.switchCamera();
- }
- },
-
- // 停止扫码
- stopScan() {
- if (this.barcodeInstance) {
- this.barcodeInstance.cancel();
- this.barcodeInstance.close();
- this.isScanning = false;
- }
- },
-
- // 重新开始扫码
- restartScan() {
- this.stopScan();
- setTimeout(() => {
- this.initBarcodeScan();
- }, 500);
- }
- }
- }
- </script>
- <style scoped>
- .custom-scan-container {
- height: 100vh;
- background: #000;
- display: flex;
- flex-direction: column;
- }
- .barcode-view {
- flex: 1;
- position: relative;
- background: transparent;
- }
- .scan-frame {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 250px;
- height: 250px;
- border: 2px solid rgba(255, 255, 255, 0.8);
- }
- .scan-line-animation {
- position: absolute;
- width: 100%;
- height: 2px;
- background: linear-gradient(90deg, transparent, #00FF00, transparent);
- animation: scanLine 2s infinite linear;
- }
- @keyframes scanLine {
- 0% { top: 0; opacity: 0; }
- 50% { opacity: 1; }
- 100% { top: 100%; opacity: 0; }
- }
- .corner {
- position: absolute;
- width: 20px;
- height: 20px;
- border-color: #00FF00;
- border-style: solid;
- }
- .top-left {
- top: -2px;
- left: -2px;
- border-width: 2px 0 0 2px;
- }
- /* 其他角样式类似 */
- .control-panel {
- padding: 20px;
- background: rgba(0, 0, 0, 0.8);
- display: flex;
- justify-content: space-around;
- }
- .control-btn {
- background: rgba(255, 255, 255, 0.1);
- color: white;
- border: none;
- padding: 10px 15px;
- border-radius: 20px;
- display: flex;
- align-items: center;
- gap: 5px;
- }
- .result-panel {
- padding: 15px;
- background: rgba(255, 255, 255, 0.9);
- border-radius: 10px;
- margin: 10px;
- }
- </style>
|