<template>
  <view class="container">
    <!-- 顶部导航 -->
    <view class="nav-bar">
      <text class="nav-title">表盘管理器</text>
    </view>

    <!-- 主内容区 -->
    <view class="content">
      <!-- 图片预览区 (圆形表盘) -->
      <view class="preview-container">
        <view class="preview-frame">
          <image 
            :src="currentImageUrl" 
            class="preview-image" 
            mode="aspectFill"
            v-if="currentImageUrl"
          ></image>
          <view class="empty-preview" v-else>
            <uni-icons type="image" size="60" color="#ccc"></uni-icons>
            <text>请选择表盘图片</text>
          </view>
        </view>
        <button
          class="set-btn"
          @click="setAsCurrentFace"
          v-if="currentImageUrl"
          :disabled="isSending"
        >
          {{ isSending ? '传输中 ' + transferProgress + '%' : '设置为当前表盘' }}
        </button>
		<view class="btn-row">
		  <button class="upload-btn" @click="chooseImage">
		    <uni-icons type="camera" size="24" color="#fff"></uni-icons>
		    <text>上传图片</text>
		  </button>
		  <button class="upload-btn gif-btn" @click="chooseGif">
		    <uni-icons type="videocam" size="24" color="#fff"></uni-icons>
		    <text>上传GIF</text>
		  </button>
		</view>
      </view>

      <!-- 卡片式轮播区 -->
      <view class="carousel-section">
        <text class="section-title">已上传表盘</text>
        <view class="carousel-container">
          <!-- 卡片式轮播核心修改 -->
          <swiper 
            class="card-swiper" 
            circular 
            previous-margin="200rpx" 
            next-margin="200rpx"
            @change="handleCarouselChange"
          >
            <swiper-item v-for="(img, index) in uploadedImages" :key="index">
              <view class="card-item" @click="selectImage(index)">
                <view class="card-frame">
                  <image 
                    :src="img.url" 
                    class="card-image" 
                    mode="aspectFill"
                  ></image>
                  <view class="card-overlay" v-if="currentImageIndex === index">
                    <uni-icons type="checkmark" size="30" color="#007aff"></uni-icons>
                  </view>
                </view>
              </view>
            </swiper-item>
          </swiper>
          <view class="carousel-hint" v-if="uploadedImages.length === 0">
            <text>暂无上传图片，请点击上方上传按钮添加</text>
          </view>
        </view>
      </view>

      <!-- BLE数据展示区 -->
      <view class="data-section">
        <text class="section-title">设备状态</text>
        <view class="data-grid">
          <!-- 电量信息 -->
          <view class="data-card">
            <view class="data-icon battery-icon">
              <uni-icons type="battery" size="36" :color="batteryColor"></uni-icons>
            </view>
            <view class="data-info">
              <text class="data-value">{{ batteryLevel }}%</text>
              <text class="data-label">电量</text>
            </view>
          </view>

          <!-- 温度信息 -->
          <view class="data-card">
            <view class="data-icon temp-icon">
              <uni-icons type="thermometer" size="36" color="#ff7a45"></uni-icons>
            </view>
            <view class="data-info">
              <text class="data-value">{{ temperature }}°C</text>
              <text class="data-label">温度</text>
            </view>
          </view>

          <!-- 湿度信息 -->
          <view class="data-card">
            <view class="data-icon humidity-icon">
              <uni-icons type="water" size="36" color="#40a9ff"></uni-icons>
            </view>
            <view class="data-info">
              <text class="data-value">{{ humidity }}%</text>
              <text class="data-label">湿度</text>
            </view>
          </view>

          <!-- 表盘状态 -->
          <view class="data-card">
            <view class="data-icon status-icon">
              <uni-icons type="watch" size="36" color="#52c41a"></uni-icons>
            </view>
            <view class="data-info">
              <text class="data-value">{{ faceStatusText }}</text>
              <text class="data-label">表盘状态</text>
            </view>
          </view>
        </view>

        <!-- 设备连接状态 -->
        <view class="connection-status">
          <uni-icons 
            type="bluetooth" 
            size="24" 
            :color="isConnected ? '#52c41a' : '#ff4d4f'"
            :animation="isScanning ? 'spin' : ''"
          ></uni-icons>
		  <view class="status-pot" 
		  :style="{
			  backgroundColor:isConnected?'Green':'red'
		  }"
		  ></view>
          <text class="status-text">
            {{ isConnected ? '已连接设备' : isScanning ? '正在搜索设备...' : '未连接设备' }}
          </text>
          <button 
            class="connect-btn" 
            @click="toggleConnection"
            :disabled="isScanning"
          >
            {{ isConnected ? '断开连接' : '连接设备' }}
          </button>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
// 脚本部分与原代码一致，无需修改
export default {
  data() {
    return {
      // 图片相关
      uploadedImages: [], // 已上传的图片列表
      currentImageUrl: '', // 当前选中的图片
      currentImageIndex: -1, // 当前选中的图片索引
      imageDir: '', // 图片保存目录
      
      // BLE设备数据
      isConnected: true, // 是否连接
      isScanning: false, // 是否正在扫描
      batteryLevel: 0, // 电量
      temperature: 0, // 温度
      humidity: 0, // 湿度
      faceStatus: 0, // 表盘状态 0-正常 1-更新中 2-异常
      
	  // statusPotColor:'Green',
	  
	  deviceId:'',
	  imageServiceuuid:'',
	  imageWriteuuid:'',
	  imageEdituuid:'',
	  isSending: false,
	  transferProgress: 0,
      // 模拟数据定时器
      dataTimer: null
    };
  },
  
  computed: {
    // 表盘状态文本
    faceStatusText() {
      switch(this.faceStatus) {
        case 0: return '正常';
        case 1: return '更新中';
        case 2: return '异常';
        default: return '未知';
      }
    },
    
    // 电池颜色（根据电量变化）
    batteryColor() {
      if (this.batteryLevel > 70) return '#52c41a';
      if (this.batteryLevel > 30) return '#faad14';
      return '#ff4d4f';
    }
  },
  
  onLoad(options) {
	this.deviceId = options.deviceId
	this.initImageDir();
	this.loadSavedImages();
	this.setBleMtu();
  },
  
  onUnload() {
    // 页面卸载时清理
    this.stopDataSimulation();
    if (this.isConnected) {
      this.disconnectDevice();
    }
  },
  
  methods: {
	// BLE 单次写入（内部方法）
	_bleWriteOnce(characteristicId, buffer, writeType) {
		return new Promise((resolve, reject) => {
			uni.writeBLECharacteristicValue({
				deviceId: this.deviceId,
				serviceId: this.imageServiceuuid,
				characteristicId: characteristicId,
				value: buffer,
				writeType: writeType || 'writeNoResponse',
				success: resolve,
				fail: reject
			});
		});
	},
	// BLE 写入封装（带重试，writeNoResponse 失败自动降级为 write）
	async bleWrite(characteristicId, buffer) {
		const MAX_RETRY = 3;
		for (let i = 0; i < MAX_RETRY; i++) {
			try {
				await this._bleWriteOnce(characteristicId, buffer, 'writeNoResponse');
				return;
			} catch (err) {
				if (i < MAX_RETRY - 1) {
					// BLE 写队列拥塞，等待后重试（退避递增）
					await this.delay(20 * (i + 1));
				} else {
					// 最后一次尝试用 write（带应答），更可靠
					try {
						await this._bleWriteOnce(characteristicId, buffer, 'write');
						return;
					} catch (fallbackErr) {
						throw fallbackErr;
					}
				}
			}
		}
	},
	// 延时
	delay(ms) {
		return new Promise(resolve => setTimeout(resolve, ms));
	},
	// 读取图片文件为 ArrayBuffer
	readImageAsArrayBuffer(filePath) {
		return new Promise((resolve, reject) => {
			console.log('readImageAsArrayBuffer 开始, 路径:', filePath);
			plus.io.resolveLocalFileSystemURL(filePath, (fileEntry) => {
				console.log('resolveLocalFileSystemURL 成功');
				fileEntry.file((file) => {
					console.log('获取File对象成功, 大小:', file.size);
					const reader = new plus.io.FileReader();
					reader.onloadend = (e) => {
						console.log('FileReader onloadend, 有数据:', !!e.target.result);
						if (e.target.result) {
							resolve(e.target.result);
						} else {
							reject(new Error('读取文件结果为空'));
						}
					};
					reader.onerror = (e) => {
						console.error('FileReader onerror:', e);
						reject(new Error('FileReader错误'));
					};
					reader.readAsDataURL(file);
				}, (err) => {
					console.error('fileEntry.file 失败:', JSON.stringify(err));
					reject(err);
				});
			}, (err) => {
				console.error('resolveLocalFileSystemURL 失败:', JSON.stringify(err));
				reject(err);
			});
		});
	},
	// DataURL 转 ArrayBuffer
	dataURLtoArrayBuffer(dataURL) {
		const base64 = dataURL.split(',')[1];
		const binary = atob(base64);
		const len = binary.length;
		const buffer = new ArrayBuffer(len);
		const view = new Uint8Array(buffer);
		for (let i = 0; i < len; i++) {
			view[i] = binary.charCodeAt(i);
		}
		return buffer;
	},
	// 图片分包传输
	async writeBleImage(filename, imageArrayBuffer) {
		const data = new Uint8Array(imageArrayBuffer);
		const len = data.length;
		console.log('开始传输图片:', filename, '大小:', len, '字节');

		// 1. 发送前序帧（26字节）
		const header = new Uint8Array(26);
		header[0] = 0xFD;
		for (let i = 0; i < Math.min(filename.length, 22); i++) {
			header[i + 1] = filename.charCodeAt(i);
		}
		header[23] = (len >> 16) & 0xFF;
		header[24] = (len >> 8) & 0xFF;
		header[25] = len & 0xFF;

		await this.bleWrite(this.imageWriteuuid, header.buffer);
		await this.delay(50);

		// 2. 分包发送图片数据（无应答写入，不等ACK）
		const CHUNK_SIZE = 507;  // (MTU-3) - 2字节帧头 = 509 - 2
		let offset = 0;
		let packetNo = 0;

		while (offset < len) {
			const remaining = len - offset;
			const chunkLen = Math.min(CHUNK_SIZE, remaining);
			const isEnd = (offset + chunkLen >= len) ? 0x01 : 0x00;

			const packet = new Uint8Array(2 + chunkLen);
			packet[0] = packetNo & 0xFF;
			packet[1] = isEnd;
			packet.set(data.slice(offset, offset + chunkLen), 2);

			await this.bleWrite(this.imageWriteuuid, packet.buffer);
			// 每包间隔5ms（平衡传输速度与BLE控制器队列容量）
			await this.delay(5);

			offset += chunkLen;
			packetNo++;

			// 每10包更新一次进度（减少UI刷新开销）
			if (packetNo % 10 === 0 || isEnd) {
				this.transferProgress = Math.floor(offset / len * 100);
				uni.showLoading({ title: '传输中 ' + this.transferProgress + '%', mask: true });
			}
		}

		console.log('图片传输完成，共', packetNo, '包');
	},
	// 通过 16-bit UUID 在列表中查找（兼容多种格式）
	findByUuid16(list, uuid16) {
		const hex4 = uuid16.toString(16).padStart(4, '0').toLowerCase();
		const fullTarget = '0000' + hex4 + '-0000-1000-8000-00805f9b34fb';
		return list.find(item => {
			const uuid = item.uuid.toLowerCase();
			// 完整 128-bit 格式匹配
			if (uuid === fullTarget) return true;
			// 短格式匹配（如 "0b00" 或 "00000b00"）
			if (uuid === hex4 || uuid === '0000' + hex4) return true;
			// 包含 16-bit 值的 128-bit 格式（不同基础UUID）
			if (uuid.startsWith('0000' + hex4 + '-')) return true;
			return false;
		});
	},
	getBleService(){
		var that = this;
		uni.getBLEDeviceServices({
			deviceId: that.deviceId,
			success(res) {
				// 打印所有服务UUID，便于调试格式问题
				console.log('发现服务数量:', res.services.length);
				res.services.forEach((s, i) => {
					console.log('  服务[' + i + ']:', s.uuid);
				});
				const service = that.findByUuid16(res.services, 0x0B00);
				if (service) {
					that.imageServiceuuid = service.uuid;
					console.log('图片服务已找到:', service.uuid);
					that.getBleChar();
				} else {
					console.error('未找到图片传输服务 0x0B00，请检查上方打印的UUID格式');
					uni.showToast({ title: '未找到图片服务', icon: 'none' });
				}
			},
			fail() {
				console.log('获取服务Id失败');
			}
		});
	},
	getBleChar(){
		var that = this;
		uni.getBLEDeviceCharacteristics({
			deviceId: that.deviceId,
			serviceId: that.imageServiceuuid,
			success(res) {
				console.log('发现特征数量:', res.characteristics.length);
				res.characteristics.forEach((c, i) => {
					console.log('  特征[' + i + ']:', c.uuid, '属性:', JSON.stringify(c.properties));
				});
				const writeChar = that.findByUuid16(res.characteristics, 0x0B01);
				const editChar = that.findByUuid16(res.characteristics, 0x0B02);
				if (writeChar) {
					that.imageWriteuuid = writeChar.uuid;
					console.log('写入特征已找到:', writeChar.uuid);
				}
				if (editChar) {
					that.imageEdituuid = editChar.uuid;
					console.log('编辑特征已找到:', editChar.uuid);
				}
				if (!writeChar || !editChar) {
					console.error('特征发现不完整, write:', !!writeChar, 'edit:', !!editChar);
				}
			},
			fail() {
				console.log('获取特征Id失败');
			}
		});
	},
	setBleMtu(){
		var that = this
		uni.setBLEMTU({
			deviceId:that.deviceId,
			mtu:512,
			success() {
				that.isConnected = true
				// that.statusPotColor = 'Green'
				console.log('MTU设置成功')
				that.getBleService();
			},
			fail() {
				console.log('MTU设置失败')
			}
		})
	},
    // 初始化图片保存目录
    initImageDir() {
      // #ifdef APP-PLUS
      // 获取应用私有目录
      const docPath = plus.io.convertLocalFileSystemURL('_doc/');
      this.imageDir = docPath + 'watch_faces/';
      plus.io.resolveLocalFileSystemURL(this.imageDir, 
        () => {},
        () => {
          plus.io.resolveLocalFileSystemURL('_doc/', (root) => {
            root.getDirectory('watch_faces', { create: true }, () => {
              console.log('目录创建成功');
            });
          });
        }
      );
      // #endif
      
      // H5和小程序使用本地存储模拟
      // #ifndef APP-PLUS
      this.imageDir = 'watch_faces/';
      // #endif
    },
    
    loadSavedImages() {
      // #ifdef APP-PLUS
      plus.io.resolveLocalFileSystemURL(this.imageDir, (dir) => {
        const reader = dir.createReader();
        reader.readEntries((entries) => {
          const images = [];
          entries.forEach((entry) => {
            if (entry.isFile && this.isImageFile(entry.name)) {
              images.push({
                name: entry.name,
                url: entry.toLocalURL()
              });
            }
          });
          this.uploadedImages = images;
          // 如果有图片，默认选中第一张
          if (images.length > 0) {
            this.currentImageUrl = images[0].url;
            this.currentImageIndex = 0;
          }
        });
      });
      // #endif
      
      // H5和小程序从本地存储加载
      // #ifndef APP-PLUS
      const savedImages = uni.getStorageSync('watch_face_images') || [];
      this.uploadedImages = savedImages;
      if (savedImages.length > 0) {
        this.currentImageUrl = savedImages[0].url;
        this.currentImageIndex = 0;
      }
      // #endif
    },
    
    // 判断是否为图片文件
    isImageFile(filename) {
      const ext = filename.toLowerCase().split('.').pop();
      return ['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext);
    },
    
    // 选择图片（支持 GIF 和普通图片）
    chooseImage() {
      uni.chooseImage({
        count: 1,
        sizeType: ['compressed'],
        sourceType: ['album', 'camera'],
        crop: {
          quality: 100,
          width: 360,
          height: 360,
          resize: true
        },
        success: (res) => {
          console.log(res);
          const tempFilePath = res.tempFilePaths[0];

          // #ifdef APP-PLUS
          plus.io.resolveLocalFileSystemURL(tempFilePath, (fileEntry) => {
            fileEntry.file((file) => {
              const reader = new FileReader();
              reader.onloadend = (e) => {
                this.imageBuffer = e.target.result;
                this.log = '图片读取成功，大小：' + this.imageBuffer.byteLength + '字节';
              };
              reader.readAsArrayBuffer(file);
            });
          });
          // #endif

          // #ifndef APP-PLUS
          const fs = uni.getFileSystemManager();
          fs.readFile({
            filePath: tempFilePath,
            encoding: 'binary',
            success: res => {
              this.imageBuffer = res.data;
              this.log = '图片读取成功，大小：' + this.imageBuffer.byteLength + '字节';
            }
          });
          // #endif

          this.saveImageToLocal(tempFilePath);
        },
        fail: (err) => {
          console.error('选择图片失败:', err);
          uni.showToast({ title: '选择图片失败', icon: 'none' });
        }
      });
    },
    
    // 选择GIF动图（不裁剪，保留原始动画）
    chooseGif() {
      uni.chooseImage({
        count: 1,
        sizeType: ['original'],
        sourceType: ['album'],
        success: (res) => {
          console.log(res);
          const tempFilePath = res.tempFilePaths[0];

          // 检查是否为GIF文件
          if (!tempFilePath.toLowerCase().endsWith('.gif')) {
            uni.showToast({ title: '请选择GIF动图文件', icon: 'none' });
            return;
          }

          // 检测 GIF 尺寸，非 360×360 提示用户
          uni.getImageInfo({
            src: tempFilePath,
            success: (imgInfo) => {
              console.log('GIF尺寸:', imgInfo.width, '×', imgInfo.height);
              const sizeOk = (imgInfo.width === 360 && imgInfo.height === 360);

              const doSave = () => {
                // #ifdef APP-PLUS
                // 检查文件大小（SPIFFS 限制，GIF 不宜超过 500KB）
                plus.io.resolveLocalFileSystemURL(tempFilePath, (fileEntry) => {
                  fileEntry.file((file) => {
                    if (file.size > 500 * 1024) {
                      uni.showModal({
                        title: '文件较大',
                        content: `GIF文件 ${(file.size / 1024).toFixed(0)}KB，设备存储有限，建议不超过500KB。是否继续？`,
                        success: (modalRes) => {
                          if (modalRes.confirm) {
                            this.saveImageToLocal(tempFilePath);
                          }
                        }
                      });
                    } else {
                      this.saveImageToLocal(tempFilePath);
                    }
                    // 读取文件到buffer
                    const reader = new FileReader();
                    reader.onloadend = (e) => {
                      this.imageBuffer = e.target.result;
                      this.log = 'GIF读取成功，大小：' + this.imageBuffer.byteLength + '字节';
                    };
                    reader.readAsArrayBuffer(file);
                  });
                });
                // #endif

                // #ifndef APP-PLUS
                this.saveImageToLocal(tempFilePath);
                // #endif
              };

              if (!sizeOk) {
                uni.showModal({
                  title: 'GIF尺寸不匹配',
                  content: `当前GIF尺寸为 ${imgInfo.width}×${imgInfo.height}，设备屏幕为 360×360。非标准尺寸的GIF播放可能不流畅且无法铺满屏幕，建议使用360×360的GIF动图。是否继续上传？`,
                  confirmText: '继续上传',
                  cancelText: '取消',
                  success: (modalRes) => {
                    if (modalRes.confirm) {
                      doSave();
                    }
                  }
                });
              } else {
                doSave();
              }
            },
            fail: () => {
              // 获取尺寸失败，仍然允许上传
              console.warn('获取GIF尺寸失败，跳过检测');
              // #ifdef APP-PLUS
              plus.io.resolveLocalFileSystemURL(tempFilePath, (fileEntry) => {
                fileEntry.file((file) => {
                  this.saveImageToLocal(tempFilePath);
                  const reader = new FileReader();
                  reader.onloadend = (e) => {
                    this.imageBuffer = e.target.result;
                    this.log = 'GIF读取成功，大小：' + this.imageBuffer.byteLength + '字节';
                  };
                  reader.readAsArrayBuffer(file);
                });
              });
              // #endif
              // #ifndef APP-PLUS
              this.saveImageToLocal(tempFilePath);
              // #endif
            }
          });
        },
        fail: (err) => {
          console.error('选择GIF失败:', err);
          uni.showToast({ title: '选择GIF失败', icon: 'none' });
        }
      });
    },

    // 保存图片到本地目录
    saveImageToLocal(tempPath) {
      // #ifdef APP-PLUS
      // 根据文件类型保留扩展名（GIF 保持 .gif，其他统一 .jpg）
      const isGif = tempPath.toLowerCase().endsWith('.gif');
      const fileName = `face_${Date.now()}.${isGif ? 'gif' : 'jpg'}`;
      const targetPath = this.imageDir + fileName;
      
      plus.io.resolveLocalFileSystemURL(tempPath, (file) => {
        plus.io.resolveLocalFileSystemURL(this.imageDir, (dir) => {
          file.copyTo(dir, fileName, (newFile) => {
            const imageUrl = newFile.toLocalURL();
            this.uploadedImages.push({
              name: fileName,
              url: imageUrl
            });
            // 保存到列表后选中新图片
            this.currentImageIndex = this.uploadedImages.length - 1;
            this.currentImageUrl = imageUrl;
            uni.showToast({ title: '图片保存成功', icon: 'success' });
          }, (err) => {
            console.error('保存图片失败:', err);
            uni.showToast({ title: '保存图片失败', icon: 'none' });
          });
        });
      });
      // #endif
      
      // H5和小程序保存到本地存储
      // #ifndef APP-PLUS
      const isGif2 = tempPath.toLowerCase().endsWith('.gif');
      const fileName = `face_${Date.now()}.${isGif2 ? 'gif' : 'jpg'}`;
      this.uploadedImages.push({
        name: fileName,
        url: tempPath
      });
      // 保存到本地存储
      uni.setStorageSync('watch_face_images', this.uploadedImages);
      // 选中新图片
      this.currentImageIndex = this.uploadedImages.length - 1;
      this.currentImageUrl = tempPath;
      uni.showToast({ title: '图片保存成功', icon: 'success' });
      // #endif
    },
    
    // 选择轮播中的图片
    selectImage(index) {
      this.currentImageIndex = index;
      this.currentImageUrl = this.uploadedImages[index].url;
    },
    
    // 轮播图变化时触发
    handleCarouselChange(e) {
      const index = e.detail.current;
      this.currentImageIndex = index;
      this.currentImageUrl = this.uploadedImages[index].url;
    },
    
    // 压缩图片为JPEG格式（设备端只支持JPEG解码）
    compressToJpeg(srcPath) {
      return new Promise((resolve, reject) => {
        uni.compressImage({
          src: srcPath,
          quality: 100,
          success: (res) => {
            console.log('JPEG压缩完成:', res.tempFilePath);
            resolve(res.tempFilePath);
          },
          fail: (err) => {
            console.error('JPEG压缩失败:', err);
            reject(err);
          }
        });
      });
    },

    // 设置为当前表盘（BLE 传输图片到设备，支持 JPEG 和 GIF）
    async setAsCurrentFace() {
      if (this.isSending) return;
      if (this.currentImageIndex < 0 || !this.imageWriteuuid) {
        uni.showToast({ title: '请先选择图片并等待BLE就绪', icon: 'none' });
        return;
      }

      const currentImage = this.uploadedImages[this.currentImageIndex];
      if (!currentImage) return;

      this.isSending = true;
      this.faceStatus = 1;
      this.transferProgress = 0;

      const isGif = currentImage.name.toLowerCase().endsWith('.gif');

      try {
        let buffer;
        let bleName;

        if (isGif) {
          // GIF: 直接读取原始文件，不压缩（压缩会破坏动画帧）
          uni.showLoading({ title: '读取GIF...', mask: true });
          const dataURL = await this.readImageAsArrayBuffer(currentImage.url);
          buffer = this.dataURLtoArrayBuffer(dataURL);
          bleName = currentImage.name;  // 保留 .gif 后缀
          console.log('GIF读取完成，大小:', buffer.byteLength, '字节');

          // GIF 文件较大时提示传输时间
          if (buffer.byteLength > 200 * 1024) {
            const sizeKB = (buffer.byteLength / 1024).toFixed(0);
            uni.showLoading({ title: `传输GIF ${sizeKB}KB...`, mask: true });
          }
        } else {
          // JPEG: 压缩后传输
          uni.showLoading({ title: '压缩图片...', mask: true });
          const jpegPath = await this.compressToJpeg(currentImage.url);

          uni.showLoading({ title: '读取图片...', mask: true });
          const dataURL = await this.readImageAsArrayBuffer(jpegPath);
          buffer = this.dataURLtoArrayBuffer(dataURL);
          bleName = currentImage.name.replace(/\.\w+$/, '.jpg');
          console.log('JPEG读取完成，大小:', buffer.byteLength, '字节');
        }

        // BLE 分包传输
        await this.writeBleImage(bleName, buffer);

        uni.hideLoading();
        this.faceStatus = 0;
        uni.showToast({ title: '表盘已更新', icon: 'success' });
        uni.setStorageSync('current_watch_face', this.currentImageUrl);
      } catch (err) {
        uni.hideLoading();
        this.faceStatus = 2;
        console.error('传输失败:', err);
        uni.showToast({ title: '传输失败: ' + (err.errMsg || err.message || err), icon: 'none' });
        setTimeout(() => { this.faceStatus = 0; }, 3000);
      } finally {
        this.isSending = false;
      }
    },
    
    // 切换设备连接状态
    toggleConnection() {
      if (this.isConnected) {
        this.disconnectDevice();
      } else {
        this.connectDevice();
      }
    },
    
    // 连接设备
    connectDevice() {
		var that = this;
		this.isScanning = true;
		uni.showToast({ title: '正在连接设备...', icon: 'none' });
		uni.createBLEConnection({
			deviceId:that.deviceId,
			success() {
				that.isScanning = false;
				that.isConnected = true;
				// that.statusPotColor = 'Green';
				uni.showToast({ title: '设备连接成功', icon: 'success' });
				that.setBleMtu();
				that.startDataSimulation();
			}
		})
    },
    
    // 断开连接
    disconnectDevice() {
		var that = this;
		uni.closeBLEConnection({
			deviceId:that.deviceId,
			success() {
				that.isConnected = false;
				that.statusPotColor = 'red';
				uni.showToast({ title: '已断开连接', icon: 'none' });
				that.stopDataSimulation();
			},
			fail(res) {
				if(res == 10000){
					uni.openBluetoothAdapter({
						success() {
							that.isConnected = false;
						},
						fail() {
							console.log('初始化失败')
						}
					})
				}
			}
		})
      
    },
    
    // 开始模拟数据更新
    startDataSimulation() {
      // 清除之前的定时器
      if (this.dataTimer) {
        clearInterval(this.dataTimer);
      }
      
      // 初始化随机数据
      this.batteryLevel = Math.floor(Math.random() * 30) + 70; // 70-100%
      this.temperature = Math.floor(Math.random() * 10) + 20; // 20-30°C
      this.humidity = Math.floor(Math.random() * 30) + 40; // 40-70%
      
      // 每5秒更新一次数据
      this.dataTimer = setInterval(() => {
        // 电量缓慢减少
        if (this.batteryLevel > 1) {
          this.batteryLevel = Math.max(1, this.batteryLevel - Math.random() * 2);
        }
        
        // 温度小幅波动
        this.temperature = Math.max(15, Math.min(35, this.temperature + (Math.random() * 2 - 1)));
        
        // 湿度小幅波动
        this.humidity = Math.max(30, Math.min(80, this.humidity + (Math.random() * 4 - 2)));
        
      }, 5000);
    },
    
    // 停止数据模拟
    stopDataSimulation() {
      if (this.dataTimer) {
        clearInterval(this.dataTimer);
        this.dataTimer = null;
      }
    }
  }
};
</script>

<style scoped>
.status-pot{
	width: 16px;
	height: 16px;
	border-radius: 50%;
}
.container {
  background-color: #f5f5f7;
  min-height: 100vh;
}

/* 导航栏 */
.nav-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx 30rpx;
  background-color: #ffffff;
}

.nav-title {
  color: white;
  font-size: 36rpx;
  font-weight: 500;
}

.btn-row {
  display: flex;
  justify-content: center;
  gap: 20rpx;
  margin-top: 10px;
}

.upload-btn {
  align-items: center;
  gap: 8rpx;
  background-color: #28d50e;
  color: white;
  width: 35%;
  margin: 0;
  padding: 14rpx 0rpx;
  border-radius: 8rpx;
  font-size: 26rpx;
}

.gif-btn {
  background-color: #7c3aed;
}

/* 内容区 */
.content {
  padding: 30rpx;
}

.section-title {
  display: block;
  font-size: 32rpx;
  color: #333;
  margin: 30rpx 0 20rpx;
  font-weight: 500;
}

/* 图片预览区 */
.preview-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 20rpx;
}

.preview-frame {
	width: 480rpx;
	height: 480rpx;
	border-radius: 50%;
	background-color: #ffffff;
	box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
	display: flex;
	justify-content: center;
	align-items: center;
	overflow: hidden;
	position: relative;
}

.preview-image {
  width: 100%;
  height: 100%;
}

.empty-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #ccc;
}

.empty-preview text {
  margin-top: 20rpx;
  font-size: 28rpx;
}

.set-btn {
  margin-top: 20rpx;
  background-color: #3cbb19;
  color: white;
  width: 35%;
  padding: 15rpx 0rpx;
  border-radius: 8rpx;
  font-size: 28rpx;
}

/* 卡片式轮播区 */
.carousel-section {
  margin-bottom: 30rpx;
}

.carousel-container {
  background-color: white;
  border-radius: 16rpx;
  padding: 20rpx 0;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  overflow: hidden;
}

/* 卡片轮播核心样式 */
.card-swiper {
  width: 100%;
  height: 240rpx;
}

.card-swiper .swiper-item {
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 0.3s ease;
}

/* 卡片样式 */
.card-item {
  width: 240rpx;
  height: 240rpx;
}

.card-frame {
  width: 240rpx;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.15);
  position: relative;
}

.card-image {
  width: 240rpx;
  height: 100%;
}

/* 选中状态覆盖层 */
.card-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 240rpx;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 卡片轮播动画效果 */
.card-swiper .swiper-item:not(.swiper-item-active) {
  transform: scale(0.8);
  opacity: 0.6;
  z-index: 1;
}

.card-swiper .swiper-item-active {
  transform: scale(1);
  z-index: 2;
}

.carousel-hint {
  height: 200rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #999;
  font-size: 26rpx;
  text-align: center;
}

/* 数据展示区 */
.data-section {
  background-color: white;
  border-radius: 16rpx;
  padding: 20rpx 30rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}

.data-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20rpx;
  margin-bottom: 30rpx;
}

.data-card {
  background-color: #f9f9f9;
  border-radius: 12rpx;
  padding: 20rpx;
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.data-icon {
  width: 60rpx;
  height: 60rpx;
  border-radius: 12rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}

.battery-icon {
  background-color: #f6ffed;
}

.temp-icon {
  background-color: #fff7e6;
}

.humidity-icon {
  background-color: #e6f7ff;
}

.status-icon {
  background-color: #f0f9ff;
}

.data-info {
  flex: 1;
}

.data-value {
  font-size: 32rpx;
  font-weight: bold;
  color: #333;
}

.data-label {
  font-size: 24rpx;
  color: #666;
}

/* 连接状态 */
.connection-status {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15rpx 0;
  border-top: 1rpx solid #f0f0f0;
}

.status-text {
  flex: 1;
  margin: 0 15rpx;
  font-size: 28rpx;
  color: #333;
}

.connect-btn {
  padding: 12rpx 24rpx;
  border-radius: 8rpx;
  font-size: 26rpx;
  background-color: #007aff;
  color: white;
}

.connect-btn:disabled {
  background-color: #ccc;
}
</style>