zhaohuanhuan 3 ماه پیش
والد
کامیت
ffcc3ebb8e
1فایلهای تغییر یافته به همراه185 افزوده شده و 137 حذف شده
  1. 185 137
      src/views/test.vue

+ 185 - 137
src/views/test.vue

@@ -2,10 +2,26 @@
   <div>
     <h1>蓝牙重量秤连接</h1>
 
+    <!-- 平台信息显示 -->
+    <div class="platform-info">
+      <p><strong>📱 检测到平台:</strong> {{ platformInfo }}</p>
+      <p><strong>🔧 蓝牙支持:</strong>
+        <span :class="isBluetoothSupported ? 'success' : 'error'">
+          {{ isBluetoothSupported ? '✅ 支持' : '❌ 不支持' }}
+        </span>
+      </p>
+      <p><strong>🌐 HTTPS环境:</strong>
+        <span :class="isHttpsEnvironment ? 'success' : 'error'">
+          {{ isHttpsEnvironment ? '✅ 是' : '❌ 否' }}
+        </span>
+      </p>
+    </div>
+
     <!-- 浏览器支持检查 -->
     <div v-if="!isBluetoothSupported" class="warning">
       <p>⚠️ 您的浏览器不支持Web Bluetooth API</p>
       <p>请使用Chrome、Edge或Opera浏览器,并确保在HTTPS环境下运行</p>
+      <p v-if="isMobileDevice">📱 在移动端,请确保使用系统浏览器而非微信等内置浏览器</p>
     </div>
 
     <!-- 环境检查 -->
@@ -14,6 +30,17 @@
       <p>请部署到HTTPS服务器或使用localhost进行开发</p>
     </div>
 
+    <!-- 移动端特殊提示 -->
+    <div v-if="isMobileDevice && isBluetoothSupported && isHttpsEnvironment" class="info">
+      <p>📱 <strong>移动端提示:</strong></p>
+      <ul>
+        <li>确保设备蓝牙已开启</li>
+        <li>蓝牙设备需要在附近(5米内)</li>
+        <li>首次使用需要授予蓝牙权限</li>
+        <li>如果扫描不到设备,请重启设备蓝牙</li>
+      </ul>
+    </div>
+
     <div class="status">
       <p>连接状态: <span :class="['connection-status', getStatusClass()]">{{ connectionStatus }}</span></p>
       <p v-if="deviceName">已连接设备: {{ deviceName }}</p>
@@ -41,23 +68,15 @@
 
       <!-- 扫描模式按钮组 -->
       <div v-else class="scan-controls">
-        <button @click="scanAllDevices" :disabled="isScanning" class="btn-scan">
-          {{ isScanning ? '扫描中...' : '扫描设备' }}
+        <button @click="scanSingleDevice" :disabled="isScanning" class="btn-scan">
+          {{ isScanning ? '扫描中...' : '扫描单个设备' }}
         </button>
 
-        <div class="batch-scan-section">
-          <label class="batch-scan-toggle">
-            <input type="checkbox" v-model="batchScanMode">
-            批量扫描模式
-          </label>
-
-          <button v-if="batchScanMode" @click="startBatchScan" :disabled="isScanning" class="btn-batch-scan">
-            🚀 开始批量扫描
-          </button>
-
-          <button v-if="batchScanMode && batchScanCount > 0" @click="stopBatchScan" class="btn-stop-batch">
-            ⏹️ 停止批量扫描
-          </button>
+        <div class="scan-info-compact">
+          <p><strong>💡 提示:</strong> 每次点击只能发现一个设备,重复点击可发现更多设备</p>
+          <p v-if="isMobileDevice" class="mobile-warning">
+            📱 <strong>移动端注意:</strong> 确保设备蓝牙已开启且在附近
+          </p>
         </div>
       </div>
 
@@ -78,7 +97,7 @@
       <div class="scan-guide">
         <div class="guide-step">
           <span class="step-number">1</span>
-          <span>点击"扫描所有设备"按钮</span>
+          <span>点击"扫描单个设备"按钮</span>
         </div>
         <div class="guide-step">
           <span class="step-number">2</span>
@@ -93,6 +112,16 @@
       <div class="scan-tips">
         <p v-if="availableDevices.length === 0">💡 <strong>提示:</strong> 如果没有看到设备,请确保蓝牙设备已开启并在附近。</p>
         <p v-if="availableDevices.length > 0">✅ 已发现 <strong>{{ availableDevices.length }}</strong> 个设备,可以继续扫描更多设备。</p>
+
+        <div v-if="isMobileDevice" class="mobile-scan-tips">
+          <p><strong>📱 移动端特殊提示:</strong></p>
+          <ul>
+            <li>确保App有蓝牙权限</li>
+            <li>设备需要开启蓝牙广播模式</li>
+            <li>尝试重启设备蓝牙功能</li>
+            <li>检查是否在微信等内置浏览器中</li>
+          </ul>
+        </div>
       </div>
     </div>
 
@@ -162,9 +191,9 @@ export default {
       availableDevices: [],
       isScanning: false,
       scanMode: false, // true: 扫描所有设备, false: 连接指定设备
-      batchScanMode: false, // 是否启用批量扫描模式
-      batchScanCount: 0, // 批量扫描计数
       deviceSearchQuery: '', // 设备搜索查询
+      isMobileDevice: false, // 是否为移动设备
+      platformInfo: '', // 平台信息
       // 重量秤设备UUID (HM-10模块)
       SERVICE_UUID: '0000ffe0-0000-1000-8000-00805f9b34fb',
       CHARACTERISTIC_UUID: '0000ffe1-0000-1000-8000-00805f9b34fb',
@@ -174,6 +203,7 @@ export default {
 
   mounted() {
     this.checkBrowserSupport();
+    this.detectPlatform();
   },
 
   computed: {
@@ -423,73 +453,28 @@ export default {
       console.log('设备列表已清除');
     },
 
-    // 开始批量扫描
-    async startBatchScan() {
-      if (this.isScanning) return;
-
-      this.batchScanCount = 0;
-      this.logBatchScan('开始批量扫描设备...');
 
-      // 开始第一次扫描
-      await this.performBatchScan();
-    },
-
-    // 执行批量扫描
-    async performBatchScan() {
-      if (!this.batchScanMode) return;
-
-      this.batchScanCount++;
-      this.logBatchScan(`执行第 ${this.batchScanCount} 次扫描...`);
-
-      try {
-        await this.scanAllDevices();
-
-        // 如果仍在批量扫描模式且没有达到最大次数,延迟后继续扫描
-        if (this.batchScanMode && this.batchScanCount < 10) { // 最多扫描10次
-          setTimeout(() => {
-            this.performBatchScan();
-          }, 2000); // 2秒延迟,避免过于频繁
-        } else if (this.batchScanCount >= 10) {
-          this.logBatchScan('已达到最大扫描次数 (10次),自动停止批量扫描');
-          this.batchScanMode = false;
-        }
-      } catch (error) {
-        this.logBatchScan(`批量扫描出错: ${error.message}`);
-        this.batchScanMode = false;
-      }
-    },
-
-    // 停止批量扫描
-    stopBatchScan() {
-      this.batchScanMode = false;
-      this.logBatchScan('批量扫描已手动停止');
-    },
-
-    // 批量扫描日志
-    logBatchScan(message) {
-      console.log(`[批量扫描] ${message}`);
-      // 可以在这里添加UI日志显示
-    },
-
-    // 扫描单个蓝牙设备(避免浏览器卡死)
-    async scanAllDevices() {
+    // 扫描单个蓝牙设备(简化版,避免卡死)
+    async scanSingleDevice() {
       if (this.isScanning) return;
 
       this.isScanning = true;
-      const scanMessage = this.batchScanMode ? `正在扫描设备 (${this.batchScanCount})...` : '正在扫描设备...';
-      this.connectionStatus = scanMessage;
+      this.connectionStatus = '正在扫描设备...';
 
       try {
         console.log('开始扫描蓝牙设备...');
 
-        // 在批量扫描模式下给出不同的提示
-        if (this.batchScanMode) {
-          alert(`请在设备列表中选择第 ${this.batchScanCount} 个设备。\n\n如果没有更多设备可以选择,请点击"取消"或关闭对话框来停止批量扫描。`);
+        // 移动端特殊提示
+        if (this.isMobileDevice) {
+          console.log('📱 移动端扫描模式');
+          // 在移动端给出更简洁的提示,避免弹窗干扰
+          this.connectionStatus = '请在设备列表中选择蓝牙设备...';
         }
 
-        // 创建超时Promise,避免无限等待
+        // 创建超时Promise(根据平台调整超时时间)
+        const timeoutMs = this.isMobileDevice ? 45000 : 30000; // 移动端给更长时间
         const timeoutPromise = new Promise((_, reject) => {
-          setTimeout(() => reject(new Error('设备选择超时,请重试')), 30000);
+          setTimeout(() => reject(new Error('设备选择超时,请重试')), timeoutMs);
         });
 
         // 请求设备选择(带超时保护)
@@ -498,45 +483,70 @@ export default {
           optionalServices: [this.SERVICE_UUID]
         });
 
+        console.log('等待用户选择设备...');
         const device = await Promise.race([devicePromise, timeoutPromise]);
 
         // 处理发现的设备
         this.addDeviceToList(device);
         const deviceName = device.name || '未知设备';
-        this.connectionStatus = `已发现设备: ${deviceName}`;
+        this.connectionStatus = `已发现设备: ${deviceName}`;
 
-        if (this.batchScanMode) {
-          this.logBatchScan(`成功发现设备: ${deviceName}`);
-        }
+        console.log('设备扫描成功:', deviceName, device.id);
 
-        console.log('设备扫描成功:', deviceName);
+        // 成功提示(仅在PC端显示,避免移动端弹窗干扰)
+        if (!this.isMobileDevice) {
+          setTimeout(() => {
+            alert(`设备 "${deviceName}" 已添加到列表!\n\n如需发现更多设备,请再次点击"扫描单个设备"按钮。`);
+          }, 500);
+        }
 
       } catch (error) {
         console.error('扫描设备失败:', error);
 
+        // 处理不同类型的错误
         if (error.name === 'NotFoundError') {
-          // 用户取消了设备选择
-          if (this.batchScanMode) {
-            this.connectionStatus = '批量扫描已停止';
-            this.batchScanMode = false;
-            this.logBatchScan('用户取消扫描,批量扫描已停止');
-          } else {
-            this.connectionStatus = '扫描已取消';
-          }
+          // 用户主动取消选择
+          this.connectionStatus = '扫描已取消';
           console.log('用户取消了设备选择');
+
+          if (!this.isMobileDevice) {
+            setTimeout(() => {
+              alert('扫描已取消。如需扫描设备,请再次点击"扫描单个设备"按钮。');
+            }, 300);
+          }
+
         } else if (error.message.includes('超时')) {
-          this.connectionStatus = '扫描超时';
-          if (!this.batchScanMode) {
-            alert('设备选择超时,请重试');
+          this.connectionStatus = '扫描超时,请重试';
+          console.log('设备选择超时');
+
+          if (!this.isMobileDevice) {
+            alert('设备选择超时,请重试。\n\n可能的原因:\n• 设备选择对话框响应慢\n• 用户长时间未选择设备\n• 浏览器权限问题');
           }
+
+        } else if (error.name === 'NotAllowedError') {
+          this.connectionStatus = '权限被拒绝';
+          console.log('蓝牙权限被拒绝');
+
+          alert('蓝牙权限被拒绝!\n\n请检查:\n• 浏览器是否支持Web Bluetooth\n• 是否在HTTPS环境下\n• 是否授予了蓝牙访问权限');
+
+        } else if (error.name === 'NotSupportedError') {
+          this.connectionStatus = '不支持此功能';
+          console.log('Web Bluetooth不支持');
+
+          alert('您的浏览器不支持Web Bluetooth API\n\n请使用:\n• Chrome (56+)\n• Edge (79+)\n• Opera (43+)');
+
         } else {
           this.connectionStatus = '扫描失败';
-          if (!this.batchScanMode) {
+          console.error('未知扫描错误:', error);
+
+          if (!this.isMobileDevice) {
             alert(`扫描失败: ${error.message}`);
           }
         }
       } finally {
+        // 确保扫描状态被重置
         this.isScanning = false;
+        console.log('扫描过程结束');
       }
     },
 
@@ -688,6 +698,45 @@ export default {
       } else {
         console.warn('❌ 不在HTTPS环境下运行,Web Bluetooth API可能无法正常工作');
       }
+    },
+
+    detectPlatform() {
+      // 检测设备类型
+      const userAgent = navigator.userAgent;
+      const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
+      const isAndroid = /Android/i.test(userAgent);
+      const isIOS = /iPad|iPhone|iPod/.test(userAgent);
+      const isWeChat = /MicroMessenger/i.test(userAgent);
+      const isEmbedded = window.parent !== window || window.top !== window;
+
+      this.isMobileDevice = isMobile;
+
+      // 构建平台信息
+      let platform = [];
+      if (isAndroid) platform.push('Android');
+      if (isIOS) platform.push('iOS');
+      if (!isMobile) platform.push('PC桌面端');
+      if (isWeChat) platform.push('微信内置浏览器');
+      if (isEmbedded) platform.push('嵌入式H5');
+
+      this.platformInfo = platform.join(' + ');
+
+      console.log('📱 检测到平台:', this.platformInfo);
+      console.log('📊 设备类型:', this.isMobileDevice ? '移动设备' : '桌面设备');
+      console.log('🌐 是否嵌入式:', isEmbedded ? '是' : '否');
+
+      // 安卓嵌入式H5的特殊处理
+      if (isAndroid && isEmbedded) {
+        console.warn('⚠️ 检测到安卓嵌入式H5环境,蓝牙功能可能受限');
+      }
+
+      return {
+        isMobile,
+        isAndroid,
+        isIOS,
+        isWeChat,
+        isEmbedded
+      };
     }
   },
 
@@ -863,6 +912,42 @@ button {
   text-align: center;
 }
 
+/* 平台信息 */
+.platform-info {
+  margin: 15px 0;
+  padding: 12px;
+  background-color: #f8f9fa;
+  border: 1px solid #dee2e6;
+  border-radius: 8px;
+  font-size: 14px;
+}
+
+.platform-info p {
+  margin: 3px 0;
+}
+
+.success { color: #28a745; font-weight: bold; }
+.error { color: #dc3545; font-weight: bold; }
+
+/* 信息提示 */
+.info {
+  margin: 15px 0;
+  padding: 12px;
+  background-color: #d1ecf1;
+  border: 1px solid #bee5eb;
+  border-radius: 8px;
+  color: #0c5460;
+}
+
+.info ul {
+  margin: 8px 0 0 0;
+  padding-left: 20px;
+}
+
+.info li {
+  margin: 3px 0;
+}
+
 /* 扫描信息提示 */
 .scan-info {
   margin: 15px 0;
@@ -925,57 +1010,20 @@ button {
   align-items: flex-start;
 }
 
-.batch-scan-section {
-  display: flex;
-  align-items: center;
-  gap: 15px;
-  flex-wrap: wrap;
-}
-
-.batch-scan-toggle {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  font-weight: bold;
-  cursor: pointer;
-}
-
-.batch-scan-toggle input[type="checkbox"] {
-  transform: scale(1.2);
-}
-
-.btn-batch-scan {
-  background-color: #28a745;
-  color: white;
-  padding: 8px 16px;
-  border: none;
-  border-radius: 5px;
-  cursor: pointer;
+.scan-info-compact {
   font-size: 14px;
+  color: #666;
 }
 
-.btn-batch-scan:hover:not(:disabled) {
-  background-color: #218838;
-}
-
-.btn-batch-scan:disabled {
-  background-color: #6c757d;
-  cursor: not-allowed;
-}
-
-.btn-stop-batch {
-  background-color: #dc3545;
-  color: white;
-  padding: 8px 16px;
-  border: none;
-  border-radius: 5px;
-  cursor: pointer;
-  font-size: 14px;
+.mobile-warning {
+  color: #856404 !important;
+  background-color: #fff3cd;
+  padding: 8px;
+  border-radius: 4px;
+  margin-top: 8px !important;
+  border: 1px solid #ffeaa7;
 }
 
-.btn-stop-batch:hover {
-  background-color: #c82333;
-}
 
 .mode-selection label {
   margin: 0 15px;