if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
  Promise.prototype.finally = function(callback) {
    const promise = this.constructor;
    return this.then(
      (value) => promise.resolve(callback()).then(() => value),
      (reason) => promise.resolve(callback()).then(() => {
        throw reason;
      })
    );
  };
}
;
if (typeof uni !== "undefined" && uni && uni.requireGlobal) {
  const global = uni.requireGlobal();
  ArrayBuffer = global.ArrayBuffer;
  Int8Array = global.Int8Array;
  Uint8Array = global.Uint8Array;
  Uint8ClampedArray = global.Uint8ClampedArray;
  Int16Array = global.Int16Array;
  Uint16Array = global.Uint16Array;
  Int32Array = global.Int32Array;
  Uint32Array = global.Uint32Array;
  Float32Array = global.Float32Array;
  Float64Array = global.Float64Array;
  BigInt64Array = global.BigInt64Array;
  BigUint64Array = global.BigUint64Array;
}
;
if (uni.restoreGlobal) {
  uni.restoreGlobal(Vue, weex, plus, setTimeout, clearTimeout, setInterval, clearInterval);
}
(function(vue) {
  "use strict";
  function formatAppLog(type, filename, ...args) {
    if (uni.__log__) {
      uni.__log__(type, filename, ...args);
    } else {
      console[type].apply(console, [...args, filename]);
    }
  }
  const _export_sfc = (sfc, props) => {
    const target = sfc.__vccOpts || sfc;
    for (const [key, val] of props) {
      target[key] = val;
    }
    return target;
  };
  const _sfc_main$2 = {
    data() {
      return {
        foundDevices: [],
        isScanning: false,
        bluetoothEnabled: false,
        connectedDeviceId: ""
      };
    },
    onLoad() {
      this.initBluetooth();
    },
    onUnload() {
      this.stopScan();
      uni.closeBluetoothAdapter();
      uni.offBluetoothDeviceFound(this.onDeviceFound);
    },
    methods: {
      // 初始化蓝牙适配器
      initBluetooth() {
        uni.openBluetoothAdapter({
          success: () => {
            this.bluetoothEnabled = true;
          },
          fail: (err) => {
            this.bluetoothEnabled = false;
            uni.showModal({
              title: "蓝牙开启失败",
              content: "请检查设备蓝牙是否开启",
              showCancel: false
            });
            formatAppLog("error", "at pages/index/index.vue:88", "蓝牙初始化失败:", err);
          }
        });
      },
      // 切换扫描状态（开始/停止）
      toggleScan() {
        if (!this.bluetoothEnabled) {
          this.initBluetooth();
          return;
        }
        if (this.isScanning) {
          this.stopScan();
        } else {
          this.startScan();
        }
      },
      // 开始扫描设备
      startScan() {
        this.isScanning = true;
        this.foundDevices = [];
        uni.startBluetoothDevicesDiscovery({
          services: [],
          allowDuplicatesKey: false,
          // 不允许重复上报
          success: () => {
            uni.showToast({ title: "开始扫描", icon: "none" });
            uni.onBluetoothDeviceFound(this.onDeviceFound);
          },
          fail: (err) => {
            this.isScanning = false;
            uni.showToast({ title: "扫描失败", icon: "none" });
            formatAppLog("error", "at pages/index/index.vue:124", "扫描失败:", err);
          }
        });
        setTimeout(() => {
          if (this.isScanning)
            this.stopScan();
        }, 5e3);
      },
      // 停止扫描
      stopScan() {
        if (!this.isScanning)
          return;
        uni.stopBluetoothDevicesDiscovery({
          success: () => {
            this.isScanning = false;
            if (this.foundDevices.length == 0) {
              uni.showToast({
                title: `暂未扫描到任何设备`,
                icon: "none"
              });
              return;
            }
            uni.showToast({
              title: `扫描完成，发现${this.foundDevices.length}台设备`,
              icon: "none"
            });
          },
          fail: (err) => {
            formatAppLog("error", "at pages/index/index.vue:154", "停止扫描失败:", err);
          }
        });
      },
      // 设备发现回调（处理去重和数据格式化）
      onDeviceFound(res) {
        const devices = res.devices || [];
        devices.forEach((device) => {
          if (!device.deviceId)
            return;
          const isExist = this.foundDevices.some(
            (d) => d.deviceId === device.deviceId
          );
          if (isExist)
            return;
          var is_bj = false;
          const advData = new Uint8Array(device.advertisData);
          const devicenameData = advData.slice(2, 6);
          const devicename = String.fromCharCode(...devicenameData);
          if (devicename == "dzbj")
            is_bj = true;
          this.foundDevices.push({
            is_bj,
            name: device.name || "未知设备",
            deviceId: device.deviceId,
            rssi: device.RSSI,
            connected: device.deviceId === this.connectedDeviceId
          });
        });
      },
      // 计算信号强度条宽度（-100dBm为0%，-30dBm为100%）
      getRssiWidth(rssi) {
        const minRssi = -100;
        const maxRssi = -30;
        let ratio = (rssi - minRssi) / (maxRssi - minRssi);
        ratio = Math.max(0, Math.min(1, ratio));
        return `${ratio * 100}%`;
      },
      connectDevice(device) {
        var that = this;
        this.stopScan();
        uni.showLoading({ title: "连接中..." });
        uni.createBLEConnection({
          deviceId: device.deviceId,
          success(res) {
            that.foundDevices = that.foundDevices.map((d) => ({
              ...d,
              connected: d.deviceId === device.deviceId
            }));
            uni.hideLoading();
            uni.showToast({ title: `已连接${device.name}`, icon: "none" });
            uni.navigateTo({
              url: "../connect/connect?deviceId=" + device.deviceId,
              fail: (err) => {
                uni.showToast({ title: `连接失败，请稍后重试`, icon: "error" });
                uni.closeBLEConnection({
                  deviceId: device.deviceId,
                  success() {
                    console("断开连接成功");
                  }
                });
              }
            });
          },
          fail() {
            uni.hideLoading();
            uni.showToast({ title: `连接失败`, icon: "error" });
          }
        });
      }
    }
  };
  function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
    return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
      vue.createElementVNode("view", { class: "title-bar" }, [
        vue.createElementVNode("text", { class: "title" }, "连接设备"),
        vue.createElementVNode("button", {
          class: "scan-btn",
          disabled: $data.isScanning,
          onClick: _cache[0] || (_cache[0] = (...args) => $options.toggleScan && $options.toggleScan(...args))
        }, vue.toDisplayString($data.isScanning ? "停止扫描" : "开始扫描"), 9, ["disabled"])
      ]),
      $data.isScanning ? (vue.openBlock(), vue.createElementBlock("view", {
        key: 0,
        class: "status-tip"
      }, [
        vue.createElementVNode("text", null, "正在扫描设备..."),
        vue.createElementVNode("view", { class: "loading" })
      ])) : $data.foundDevices.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", {
        key: 1,
        class: "status-tip"
      }, [
        vue.createElementVNode("text", null, '未发现设备，请点击"开始扫描"')
      ])) : vue.createCommentVNode("v-if", true),
      vue.createElementVNode("view", { class: "device-list" }, [
        (vue.openBlock(true), vue.createElementBlock(
          vue.Fragment,
          null,
          vue.renderList($data.foundDevices, (device, index) => {
            return vue.openBlock(), vue.createElementBlock("view", {
              class: "device-item",
              key: device.deviceId,
              onClick: ($event) => $options.connectDevice(device)
            }, [
              vue.createElementVNode("view", { class: "device-name" }, [
                vue.createElementVNode(
                  "text",
                  null,
                  vue.toDisplayString(device.name || "未知设备"),
                  1
                  /* TEXT */
                ),
                device.is_bj ? (vue.openBlock(), vue.createElementBlock("view", {
                  key: 0,
                  class: "is_bj"
                }, "吧唧")) : vue.createCommentVNode("v-if", true),
                vue.createElementVNode(
                  "text",
                  { class: "device-id" },
                  vue.toDisplayString(device.deviceId),
                  1
                  /* TEXT */
                )
              ]),
              vue.createElementVNode("view", { class: "device-rssi" }, [
                vue.createElementVNode(
                  "text",
                  null,
                  "信号: " + vue.toDisplayString(device.rssi) + " dBm",
                  1
                  /* TEXT */
                ),
                vue.createElementVNode(
                  "view",
                  {
                    class: "rssi-bar",
                    style: vue.normalizeStyle({ width: $options.getRssiWidth(device.rssi) })
                  },
                  null,
                  4
                  /* STYLE */
                )
              ]),
              device.connected ? (vue.openBlock(), vue.createElementBlock("view", {
                key: 0,
                class: "device-status"
              }, [
                vue.createElementVNode("text", { class: "connected" }, "已连接")
              ])) : vue.createCommentVNode("v-if", true)
            ], 8, ["onClick"]);
          }),
          128
          /* KEYED_FRAGMENT */
        ))
      ])
    ]);
  }
  const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__scopeId", "data-v-1cf27b2a"], ["__file", "/Users/rdzleo/Desktop/uniapp_code/pages/index/index.vue"]]);
  const _sfc_main$1 = {
    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,
            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) {
              await this.delay(20 * (i + 1));
            } else {
              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) => {
          formatAppLog("log", "at pages/connect/connect.vue:266", "readImageAsArrayBuffer 开始, 路径:", filePath);
          plus.io.resolveLocalFileSystemURL(filePath, (fileEntry) => {
            formatAppLog("log", "at pages/connect/connect.vue:268", "resolveLocalFileSystemURL 成功");
            fileEntry.file((file) => {
              formatAppLog("log", "at pages/connect/connect.vue:270", "获取File对象成功, 大小:", file.size);
              const reader = new plus.io.FileReader();
              reader.onloadend = (e) => {
                formatAppLog("log", "at pages/connect/connect.vue:273", "FileReader onloadend, 有数据:", !!e.target.result);
                if (e.target.result) {
                  resolve(e.target.result);
                } else {
                  reject(new Error("读取文件结果为空"));
                }
              };
              reader.onerror = (e) => {
                formatAppLog("error", "at pages/connect/connect.vue:281", "FileReader onerror:", e);
                reject(new Error("FileReader错误"));
              };
              reader.readAsDataURL(file);
            }, (err) => {
              formatAppLog("error", "at pages/connect/connect.vue:286", "fileEntry.file 失败:", JSON.stringify(err));
              reject(err);
            });
          }, (err) => {
            formatAppLog("error", "at pages/connect/connect.vue:290", "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;
        formatAppLog("log", "at pages/connect/connect.vue:311", "开始传输图片:", filename, "大小:", len, "字节");
        const header = new Uint8Array(26);
        header[0] = 253;
        for (let i = 0; i < Math.min(filename.length, 22); i++) {
          header[i + 1] = filename.charCodeAt(i);
        }
        header[23] = len >> 16 & 255;
        header[24] = len >> 8 & 255;
        header[25] = len & 255;
        await this.bleWrite(this.imageWriteuuid, header.buffer);
        await this.delay(50);
        const CHUNK_SIZE = 507;
        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 ? 1 : 0;
          const packet = new Uint8Array(2 + chunkLen);
          packet[0] = packetNo & 255;
          packet[1] = isEnd;
          packet.set(data.slice(offset, offset + chunkLen), 2);
          await this.bleWrite(this.imageWriteuuid, packet.buffer);
          await this.delay(5);
          offset += chunkLen;
          packetNo++;
          if (packetNo % 10 === 0 || isEnd) {
            this.transferProgress = Math.floor(offset / len * 100);
            uni.showLoading({ title: "传输中 " + this.transferProgress + "%", mask: true });
          }
        }
        formatAppLog("log", "at pages/connect/connect.vue:355", "图片传输完成，共", 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();
          if (uuid === fullTarget)
            return true;
          if (uuid === hex4 || uuid === "0000" + hex4)
            return true;
          if (uuid.startsWith("0000" + hex4 + "-"))
            return true;
          return false;
        });
      },
      getBleService() {
        var that = this;
        uni.getBLEDeviceServices({
          deviceId: that.deviceId,
          success(res) {
            formatAppLog("log", "at pages/connect/connect.vue:378", "发现服务数量:", res.services.length);
            res.services.forEach((s, i) => {
              formatAppLog("log", "at pages/connect/connect.vue:380", "  服务[" + i + "]:", s.uuid);
            });
            const service = that.findByUuid16(res.services, 2816);
            if (service) {
              that.imageServiceuuid = service.uuid;
              formatAppLog("log", "at pages/connect/connect.vue:385", "图片服务已找到:", service.uuid);
              that.getBleChar();
            } else {
              formatAppLog("error", "at pages/connect/connect.vue:388", "未找到图片传输服务 0x0B00，请检查上方打印的UUID格式");
              uni.showToast({ title: "未找到图片服务", icon: "none" });
            }
          },
          fail() {
            formatAppLog("log", "at pages/connect/connect.vue:393", "获取服务Id失败");
          }
        });
      },
      getBleChar() {
        var that = this;
        uni.getBLEDeviceCharacteristics({
          deviceId: that.deviceId,
          serviceId: that.imageServiceuuid,
          success(res) {
            formatAppLog("log", "at pages/connect/connect.vue:403", "发现特征数量:", res.characteristics.length);
            res.characteristics.forEach((c, i) => {
              formatAppLog("log", "at pages/connect/connect.vue:405", "  特征[" + i + "]:", c.uuid, "属性:", JSON.stringify(c.properties));
            });
            const writeChar = that.findByUuid16(res.characteristics, 2817);
            const editChar = that.findByUuid16(res.characteristics, 2818);
            if (writeChar) {
              that.imageWriteuuid = writeChar.uuid;
              formatAppLog("log", "at pages/connect/connect.vue:411", "写入特征已找到:", writeChar.uuid);
            }
            if (editChar) {
              that.imageEdituuid = editChar.uuid;
              formatAppLog("log", "at pages/connect/connect.vue:415", "编辑特征已找到:", editChar.uuid);
            }
            if (!writeChar || !editChar) {
              formatAppLog("error", "at pages/connect/connect.vue:418", "特征发现不完整, write:", !!writeChar, "edit:", !!editChar);
            }
          },
          fail() {
            formatAppLog("log", "at pages/connect/connect.vue:422", "获取特征Id失败");
          }
        });
      },
      setBleMtu() {
        var that = this;
        uni.setBLEMTU({
          deviceId: that.deviceId,
          mtu: 512,
          success() {
            that.isConnected = true;
            formatAppLog("log", "at pages/connect/connect.vue:434", "MTU设置成功");
            that.getBleService();
          },
          fail() {
            formatAppLog("log", "at pages/connect/connect.vue:438", "MTU设置失败");
          }
        });
      },
      // 初始化图片保存目录
      initImageDir() {
        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 }, () => {
                formatAppLog("log", "at pages/connect/connect.vue:453", "目录创建成功");
              });
            });
          }
        );
      },
      loadSavedImages() {
        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;
            }
          });
        });
      },
      // 判断是否为图片文件
      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) => {
            formatAppLog("log", "at pages/connect/connect.vue:520", res);
            const tempFilePath = res.tempFilePaths[0];
            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);
              });
            });
            this.saveImageToLocal(tempFilePath);
          },
          fail: (err) => {
            formatAppLog("error", "at pages/connect/connect.vue:551", "选择图片失败:", err);
            uni.showToast({ title: "选择图片失败", icon: "none" });
          }
        });
      },
      // 选择GIF动图（不裁剪，保留原始动画）
      chooseGif() {
        uni.chooseImage({
          count: 1,
          sizeType: ["original"],
          sourceType: ["album"],
          success: (res) => {
            formatAppLog("log", "at pages/connect/connect.vue:564", res);
            const tempFilePath = res.tempFilePaths[0];
            if (!tempFilePath.toLowerCase().endsWith(".gif")) {
              uni.showToast({ title: "请选择GIF动图文件", icon: "none" });
              return;
            }
            uni.getImageInfo({
              src: tempFilePath,
              success: (imgInfo) => {
                formatAppLog("log", "at pages/connect/connect.vue:577", "GIF尺寸:", imgInfo.width, "×", imgInfo.height);
                const sizeOk = imgInfo.width === 360 && imgInfo.height === 360;
                const doSave = () => {
                  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);
                      }
                      const reader = new FileReader();
                      reader.onloadend = (e) => {
                        this.imageBuffer = e.target.result;
                        this.log = "GIF读取成功，大小：" + this.imageBuffer.byteLength + "字节";
                      };
                      reader.readAsArrayBuffer(file);
                    });
                  });
                };
                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: () => {
                formatAppLog("warn", "at pages/connect/connect.vue:632", "获取GIF尺寸失败，跳过检测");
                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);
                  });
                });
              }
            });
          },
          fail: (err) => {
            formatAppLog("error", "at pages/connect/connect.vue:653", "选择GIF失败:", err);
            uni.showToast({ title: "选择GIF失败", icon: "none" });
          }
        });
      },
      // 保存图片到本地目录
      saveImageToLocal(tempPath) {
        const isGif = tempPath.toLowerCase().endsWith(".gif");
        const fileName = `face_${Date.now()}.${isGif ? "gif" : "jpg"}`;
        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) => {
              formatAppLog("error", "at pages/connect/connect.vue:680", "保存图片失败:", err);
              uni.showToast({ title: "保存图片失败", icon: "none" });
            });
          });
        });
      },
      // 选择轮播中的图片
      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) => {
              formatAppLog("log", "at pages/connect/connect.vue:724", "JPEG压缩完成:", res.tempFilePath);
              resolve(res.tempFilePath);
            },
            fail: (err) => {
              formatAppLog("error", "at pages/connect/connect.vue:728", "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) {
            uni.showLoading({ title: "读取GIF...", mask: true });
            const dataURL = await this.readImageAsArrayBuffer(currentImage.url);
            buffer = this.dataURLtoArrayBuffer(dataURL);
            bleName = currentImage.name;
            formatAppLog("log", "at pages/connect/connect.vue:762", "GIF读取完成，大小:", buffer.byteLength, "字节");
            if (buffer.byteLength > 200 * 1024) {
              const sizeKB = (buffer.byteLength / 1024).toFixed(0);
              uni.showLoading({ title: `传输GIF ${sizeKB}KB...`, mask: true });
            }
          } else {
            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");
            formatAppLog("log", "at pages/connect/connect.vue:778", "JPEG读取完成，大小:", buffer.byteLength, "字节");
          }
          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;
          formatAppLog("error", "at pages/connect/connect.vue:791", "传输失败:", err);
          uni.showToast({ title: "传输失败: " + (err.errMsg || err.message || err), icon: "none" });
          setTimeout(() => {
            this.faceStatus = 0;
          }, 3e3);
        } 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;
            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 == 1e4) {
              uni.openBluetoothAdapter({
                success() {
                  that.isConnected = false;
                },
                fail() {
                  formatAppLog("log", "at pages/connect/connect.vue:844", "初始化失败");
                }
              });
            }
          }
        });
      },
      // 开始模拟数据更新
      startDataSimulation() {
        if (this.dataTimer) {
          clearInterval(this.dataTimer);
        }
        this.batteryLevel = Math.floor(Math.random() * 30) + 70;
        this.temperature = Math.floor(Math.random() * 10) + 20;
        this.humidity = Math.floor(Math.random() * 30) + 40;
        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)));
        }, 5e3);
      },
      // 停止数据模拟
      stopDataSimulation() {
        if (this.dataTimer) {
          clearInterval(this.dataTimer);
          this.dataTimer = null;
        }
      }
    }
  };
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
    const _component_uni_icons = vue.resolveComponent("uni-icons");
    return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
      vue.createElementVNode("view", { class: "nav-bar" }, [
        vue.createElementVNode("text", { class: "nav-title" }, "表盘管理器")
      ]),
      vue.createElementVNode("view", { class: "content" }, [
        vue.createElementVNode("view", { class: "preview-container" }, [
          vue.createElementVNode("view", { class: "preview-frame" }, [
            $data.currentImageUrl ? (vue.openBlock(), vue.createElementBlock("image", {
              key: 0,
              src: $data.currentImageUrl,
              class: "preview-image",
              mode: "aspectFill"
            }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", {
              key: 1,
              class: "empty-preview"
            }, [
              vue.createVNode(_component_uni_icons, {
                type: "image",
                size: "60",
                color: "#ccc"
              }),
              vue.createElementVNode("text", null, "请选择表盘图片")
            ]))
          ]),
          $data.currentImageUrl ? (vue.openBlock(), vue.createElementBlock("button", {
            key: 0,
            class: "set-btn",
            onClick: _cache[0] || (_cache[0] = (...args) => $options.setAsCurrentFace && $options.setAsCurrentFace(...args)),
            disabled: $data.isSending
          }, vue.toDisplayString($data.isSending ? "传输中 " + $data.transferProgress + "%" : "设置为当前表盘"), 9, ["disabled"])) : vue.createCommentVNode("v-if", true),
          vue.createElementVNode("view", { class: "btn-row" }, [
            vue.createElementVNode("button", {
              class: "upload-btn",
              onClick: _cache[1] || (_cache[1] = (...args) => $options.chooseImage && $options.chooseImage(...args))
            }, [
              vue.createVNode(_component_uni_icons, {
                type: "camera",
                size: "24",
                color: "#fff"
              }),
              vue.createElementVNode("text", null, "上传图片")
            ]),
            vue.createElementVNode("button", {
              class: "upload-btn gif-btn",
              onClick: _cache[2] || (_cache[2] = (...args) => $options.chooseGif && $options.chooseGif(...args))
            }, [
              vue.createVNode(_component_uni_icons, {
                type: "videocam",
                size: "24",
                color: "#fff"
              }),
              vue.createElementVNode("text", null, "上传GIF")
            ])
          ])
        ]),
        vue.createElementVNode("view", { class: "carousel-section" }, [
          vue.createElementVNode("text", { class: "section-title" }, "已上传表盘"),
          vue.createElementVNode("view", { class: "carousel-container" }, [
            vue.createElementVNode(
              "swiper",
              {
                class: "card-swiper",
                circular: "",
                "previous-margin": "200rpx",
                "next-margin": "200rpx",
                onChange: _cache[3] || (_cache[3] = (...args) => $options.handleCarouselChange && $options.handleCarouselChange(...args))
              },
              [
                (vue.openBlock(true), vue.createElementBlock(
                  vue.Fragment,
                  null,
                  vue.renderList($data.uploadedImages, (img, index) => {
                    return vue.openBlock(), vue.createElementBlock("swiper-item", { key: index }, [
                      vue.createElementVNode("view", {
                        class: "card-item",
                        onClick: ($event) => $options.selectImage(index)
                      }, [
                        vue.createElementVNode("view", { class: "card-frame" }, [
                          vue.createElementVNode("image", {
                            src: img.url,
                            class: "card-image",
                            mode: "aspectFill"
                          }, null, 8, ["src"]),
                          $data.currentImageIndex === index ? (vue.openBlock(), vue.createElementBlock("view", {
                            key: 0,
                            class: "card-overlay"
                          }, [
                            vue.createVNode(_component_uni_icons, {
                              type: "checkmark",
                              size: "30",
                              color: "#007aff"
                            })
                          ])) : vue.createCommentVNode("v-if", true)
                        ])
                      ], 8, ["onClick"])
                    ]);
                  }),
                  128
                  /* KEYED_FRAGMENT */
                ))
              ],
              32
              /* NEED_HYDRATION */
            ),
            $data.uploadedImages.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", {
              key: 0,
              class: "carousel-hint"
            }, [
              vue.createElementVNode("text", null, "暂无上传图片，请点击上方上传按钮添加")
            ])) : vue.createCommentVNode("v-if", true)
          ])
        ]),
        vue.createElementVNode("view", { class: "data-section" }, [
          vue.createElementVNode("text", { class: "section-title" }, "设备状态"),
          vue.createElementVNode("view", { class: "data-grid" }, [
            vue.createElementVNode("view", { class: "data-card" }, [
              vue.createElementVNode("view", { class: "data-icon battery-icon" }, [
                vue.createVNode(_component_uni_icons, {
                  type: "battery",
                  size: "36",
                  color: $options.batteryColor
                }, null, 8, ["color"])
              ]),
              vue.createElementVNode("view", { class: "data-info" }, [
                vue.createElementVNode(
                  "text",
                  { class: "data-value" },
                  vue.toDisplayString($data.batteryLevel) + "%",
                  1
                  /* TEXT */
                ),
                vue.createElementVNode("text", { class: "data-label" }, "电量")
              ])
            ]),
            vue.createElementVNode("view", { class: "data-card" }, [
              vue.createElementVNode("view", { class: "data-icon temp-icon" }, [
                vue.createVNode(_component_uni_icons, {
                  type: "thermometer",
                  size: "36",
                  color: "#ff7a45"
                })
              ]),
              vue.createElementVNode("view", { class: "data-info" }, [
                vue.createElementVNode(
                  "text",
                  { class: "data-value" },
                  vue.toDisplayString($data.temperature) + "°C",
                  1
                  /* TEXT */
                ),
                vue.createElementVNode("text", { class: "data-label" }, "温度")
              ])
            ]),
            vue.createElementVNode("view", { class: "data-card" }, [
              vue.createElementVNode("view", { class: "data-icon humidity-icon" }, [
                vue.createVNode(_component_uni_icons, {
                  type: "water",
                  size: "36",
                  color: "#40a9ff"
                })
              ]),
              vue.createElementVNode("view", { class: "data-info" }, [
                vue.createElementVNode(
                  "text",
                  { class: "data-value" },
                  vue.toDisplayString($data.humidity) + "%",
                  1
                  /* TEXT */
                ),
                vue.createElementVNode("text", { class: "data-label" }, "湿度")
              ])
            ]),
            vue.createElementVNode("view", { class: "data-card" }, [
              vue.createElementVNode("view", { class: "data-icon status-icon" }, [
                vue.createVNode(_component_uni_icons, {
                  type: "watch",
                  size: "36",
                  color: "#52c41a"
                })
              ]),
              vue.createElementVNode("view", { class: "data-info" }, [
                vue.createElementVNode(
                  "text",
                  { class: "data-value" },
                  vue.toDisplayString($options.faceStatusText),
                  1
                  /* TEXT */
                ),
                vue.createElementVNode("text", { class: "data-label" }, "表盘状态")
              ])
            ])
          ]),
          vue.createElementVNode("view", { class: "connection-status" }, [
            vue.createVNode(_component_uni_icons, {
              type: "bluetooth",
              size: "24",
              color: $data.isConnected ? "#52c41a" : "#ff4d4f",
              animation: $data.isScanning ? "spin" : ""
            }, null, 8, ["color", "animation"]),
            vue.createElementVNode(
              "view",
              {
                class: "status-pot",
                style: vue.normalizeStyle({
                  backgroundColor: $data.isConnected ? "Green" : "red"
                })
              },
              null,
              4
              /* STYLE */
            ),
            vue.createElementVNode(
              "text",
              { class: "status-text" },
              vue.toDisplayString($data.isConnected ? "已连接设备" : $data.isScanning ? "正在搜索设备..." : "未连接设备"),
              1
              /* TEXT */
            ),
            vue.createElementVNode("button", {
              class: "connect-btn",
              onClick: _cache[4] || (_cache[4] = (...args) => $options.toggleConnection && $options.toggleConnection(...args)),
              disabled: $data.isScanning
            }, vue.toDisplayString($data.isConnected ? "断开连接" : "连接设备"), 9, ["disabled"])
          ])
        ])
      ])
    ]);
  }
  const PagesConnectConnect = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-ea8c7664"], ["__file", "/Users/rdzleo/Desktop/uniapp_code/pages/connect/connect.vue"]]);
  __definePage("pages/index/index", PagesIndexIndex);
  __definePage("pages/connect/connect", PagesConnectConnect);
  const _sfc_main = {
    onLaunch: function() {
      formatAppLog("log", "at App.vue:7", "App Launch");
    },
    onShow: function() {
      formatAppLog("log", "at App.vue:10", "App Show");
    },
    onHide: function() {
      formatAppLog("log", "at App.vue:13", "App Hide");
    },
    onExit: function() {
      formatAppLog("log", "at App.vue:34", "App Exit");
    }
  };
  const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "/Users/rdzleo/Desktop/uniapp_code/App.vue"]]);
  function createApp() {
    const app = vue.createVueApp(App);
    return {
      app
    };
  }
  const { app: __app__, Vuex: __Vuex__, Pinia: __Pinia__ } = createApp();
  uni.Vuex = __Vuex__;
  uni.Pinia = __Pinia__;
  __app__.provide("__globalStyles", __uniConfig.styles);
  __app__._component.mpType = "app";
  __app__._component.render = () => {
  };
  __app__.mount("#app");
})(Vue);
