uniapp_code项目代码初始化,第一次上传至仓库
9
.hbuilderx/launch.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-android"
|
||||
}
|
||||
]
|
||||
}
|
||||
594
APP蓝牙传图接口说明.md
Normal file
@ -0,0 +1,594 @@
|
||||
# BLE 蓝牙传图接口说明
|
||||
|
||||
> 本文档供 APP 开发工程师参考,描述手机端与 ESP32-S3 设备端的 BLE 图片传输协议。
|
||||
> 设备固件:ESP-IDF 5.4 + Bluedroid BLE GATT Server
|
||||
> 适用平台:Android + iOS(Flutter 跨平台框架)
|
||||
> 更新日期:2026-02-27
|
||||
|
||||
---
|
||||
|
||||
## 一、设备信息
|
||||
|
||||
| 项目 | 值 |
|
||||
|------|-----|
|
||||
| 设备名称 | `Airhub_xx:xx:xx:xx:xx:xx`(动态名称,后缀为 BLE MAC 地址) |
|
||||
| 广播类型 | ADV_IND(可连接、可扫描) |
|
||||
| 广播间隔 | 20ms |
|
||||
| MTU | 512 字节(设备端已设置,APP 端连接后必须协商) |
|
||||
| 屏幕分辨率 | 360×360 圆形 LCD |
|
||||
| 图片格式 | JPEG(Baseline) |
|
||||
| 存储空间 | SPIFFS 2MB |
|
||||
| 厂商标识 | Scan Response 厂商字段 Company ID `0x4C44` + ASCII `dzbj` |
|
||||
|
||||
### 广播数据结构
|
||||
|
||||
设备广播分为两部分:
|
||||
|
||||
**ADV 数据(主广播包):**
|
||||
```
|
||||
02 01 06 — Flags: LE General Discoverable + BR/EDR Not Supported
|
||||
1C 09 41 69 72 68 75 62 5F xx xx ... — 完整设备名: "Airhub_xx:xx:xx:xx:xx:xx"(长度动态)
|
||||
```
|
||||
|
||||
**Scan Response 数据(扫描响应包):**
|
||||
```
|
||||
07 FF 4C 44 64 7A 62 6A — 厂商数据: Company ID 0x4C44 + "dzbj"
|
||||
03 03 00 0B — 16-bit 服务 UUID: 0x0B00
|
||||
```
|
||||
|
||||
**设备识别方法**:解析 Scan Response 厂商数据段,跳过前 2 字节 Company ID,取后 4 字节判断是否为 ASCII `dzbj`(`0x64 0x7A 0x62 0x6A`)。也可通过设备名称前缀 `Airhub_` 辅助识别。
|
||||
|
||||
---
|
||||
|
||||
## 二、BLE 服务与特征
|
||||
|
||||
设备仅注册一个自定义服务:
|
||||
|
||||
```
|
||||
图片传输服务 (Service UUID: 0x0B00)
|
||||
│
|
||||
├── 图片写入特征 (Characteristic UUID: 0x0B01)
|
||||
│ ├── 属性: Write + Write Without Response
|
||||
│ ├── 最大长度: 512 字节
|
||||
│ └── 用途: 传输图片数据(前序帧 + 分包数据帧)
|
||||
│
|
||||
└── 图片管理特征 (Characteristic UUID: 0x0B02)
|
||||
├── 属性: Write + Write Without Response
|
||||
├── 最大长度: 24 字节
|
||||
└── 用途: 管理命令(设置当前表盘 / 删除图片)
|
||||
```
|
||||
|
||||
> **重要**:
|
||||
> - 两个特征均支持 Write 和 Write Without Response,**推荐使用 Write Without Response(writeNoResponse)** 以提升传输速度
|
||||
> - APP 端发现服务和特征时,**必须通过 UUID 匹配**(`0x0B00` / `0x0B01` / `0x0B02`),不要用数组索引,不同固件版本的服务/特征顺序可能不同
|
||||
> - 16-bit UUID 在 BLE 协议栈中会被扩展为 128-bit 格式,例如 `0x0B00` → `00000b00-0000-1000-8000-00805f9b34fb`
|
||||
|
||||
---
|
||||
|
||||
## 三、连接流程
|
||||
|
||||
```
|
||||
1. 初始化蓝牙适配器(openBluetoothAdapter)
|
||||
2. 扫描设备(通过厂商数据 "dzbj" 或设备名前缀 "Airhub_" 识别目标设备)
|
||||
3. 建立 BLE 连接(createBLEConnection)
|
||||
4. 协商 MTU = 512(setBLEMTU) ← 必须!否则每包只能发 20 字节
|
||||
5. 发现服务,通过 UUID 匹配 0x0B00
|
||||
6. 发现特征,通过 UUID 匹配 0x0B01(写入)和 0x0B02(管理)
|
||||
7. 就绪,可以传输图片或发送管理命令
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、图片传输协议(写入特征 0x0B01)
|
||||
|
||||
### 4.1 关键参数
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
|------|-----|------|
|
||||
| MTU | 512 | 设备端设置,APP 端连接后协商 |
|
||||
| ATT 有效载荷 | **509** | MTU - 3(ATT 协议头占 3 字节) |
|
||||
| 帧头大小 | 2 | 包序号(1) + 结束标志(1) |
|
||||
| **CHUNK_SIZE** | **507** | 509 - 2 = 每包最大图片数据 |
|
||||
| 写入方式 | writeNoResponse | Write Without Response,不等 ACK |
|
||||
| 包间延时 | **5ms** | 防止 Android BLE 队列溢出 |
|
||||
| 前序帧延时 | **50ms** | 前序帧后等待设备端建立接收通道 |
|
||||
|
||||
> **严格约束:每个 BLE 数据包总长不得超过 509 字节(MTU - 3)**
|
||||
> 超出此限制时,Android 系统会**静默截断**数据包(不报错),导致设备端接收到的数据不完整,JPEG 解码失败。
|
||||
|
||||
### 4.2 前序帧(固定 26 字节,每次传图发 1 次)
|
||||
|
||||
| 字节偏移 | 长度 | 内容 | 说明 |
|
||||
|----------|------|------|------|
|
||||
| 0 | 1 | `0xFD` | 固定标识:开始图片传输 |
|
||||
| 1 ~ 22 | 22 | 文件名 | UTF-8/ASCII 编码,不足 22 字节补 `0x00` |
|
||||
| 23 | 1 | `(len >> 16) & 0xFF` | 图片总大小 - 高字节 |
|
||||
| 24 | 1 | `(len >> 8) & 0xFF` | 图片总大小 - 中字节 |
|
||||
| 25 | 1 | `len & 0xFF` | 图片总大小 - 低字节 |
|
||||
|
||||
> - 图片大小为 3 字节大端序,最大支持 16,777,215 字节(~16MB)
|
||||
> - 文件名**必须以 `.jpg` 结尾**,示例:`face_1708012345.jpg`
|
||||
> - 文件名不能超过 22 字节(含扩展名),建议用 `face_时间戳.jpg` 格式
|
||||
|
||||
### 4.3 数据帧(循环发送直到传完)
|
||||
|
||||
| 字节偏移 | 长度 | 内容 | 说明 |
|
||||
|----------|------|------|------|
|
||||
| 0 | 1 | 包序号 | 从 0 递增,溢出后回绕(0~255 循环) |
|
||||
| 1 | 1 | 结束标志 | `0x00` = 后续还有数据;`非0` = 最后一包 |
|
||||
| 2 ~ N | 最大 **507** | 图片数据 | 实际负载 = 本包总长 - 2 |
|
||||
|
||||
> 每个数据帧总长 = 2(帧头) + 图片数据 ≤ **509 字节**
|
||||
|
||||
### 4.4 传输示例
|
||||
|
||||
以一张 1521 字节的图片 `face_170801.jpg` 为例(CHUNK_SIZE = 507):
|
||||
|
||||
```
|
||||
第 1 包(前序帧,26 字节):
|
||||
FD 66 61 63 65 5F 31 37 30 38 30 31 2E 6A 70 67 00 ... 00 05 F1
|
||||
│ └─────── "face_170801.jpg" + 补零 ──────────────┘ └── 1521 大端序
|
||||
└─ 标识符 0xFD
|
||||
|
||||
[等待 50ms]
|
||||
|
||||
第 2 包(数据帧,509 字节 = 2 + 507):
|
||||
00 00 [507 字节图片数据]
|
||||
│ └─ 未结束
|
||||
└─ 包序号 0
|
||||
|
||||
[等待 5ms]
|
||||
|
||||
第 3 包(数据帧,509 字节 = 2 + 507):
|
||||
01 00 [507 字节图片数据]
|
||||
│ └─ 未结束
|
||||
└─ 包序号 1
|
||||
|
||||
[等待 5ms]
|
||||
|
||||
第 4 包(数据帧,最后一包,509 字节 = 2 + 507):
|
||||
02 01 [507 字节图片数据]
|
||||
│ └─ 结束标志 = 1
|
||||
└─ 包序号 2
|
||||
```
|
||||
|
||||
设备端收到结束帧后,自动:写入 SPIFFS → 更新 NVS → 跳转到图片浏览界面显示新图片。
|
||||
|
||||
---
|
||||
|
||||
## 五、图片管理命令(管理特征 0x0B02)
|
||||
|
||||
### 5.1 设置为当前表盘
|
||||
|
||||
| 字节偏移 | 长度 | 内容 | 说明 |
|
||||
|----------|------|------|------|
|
||||
| 0 ~ 22 | 23 | 文件名 | 与传输时使用的文件名一致,不足补 `0x00` |
|
||||
| 23 | 1 | `0xFF` | 命令标识:设置为当前表盘 |
|
||||
|
||||
设备端收到后:更新 NVS 记录 → 跳转到图片浏览界面显示指定图片。
|
||||
|
||||
### 5.2 删除图片
|
||||
|
||||
| 字节偏移 | 长度 | 内容 | 说明 |
|
||||
|----------|------|------|------|
|
||||
| 0 ~ 22 | 23 | 文件名 | 要删除的文件名 |
|
||||
| 23 | 1 | `0xF1` | 命令标识:删除该图片 |
|
||||
|
||||
设备端收到后从 SPIFFS 中物理删除该文件。
|
||||
|
||||
---
|
||||
|
||||
## 六、APP 端图片处理流程
|
||||
|
||||
APP 端在传输前**必须对图片进行预处理**,确保设备端能正确解码显示:
|
||||
|
||||
```
|
||||
用户选图/拍照
|
||||
│
|
||||
▼
|
||||
裁剪为 360×360(必须!设备屏幕分辨率)
|
||||
│
|
||||
▼
|
||||
保存为 .jpg 文件(文件名后缀必须是 .jpg)
|
||||
│
|
||||
▼
|
||||
JPEG 压缩(quality: 80~100)
|
||||
│
|
||||
▼
|
||||
读取为 ArrayBuffer
|
||||
│
|
||||
▼
|
||||
BLE 分包传输
|
||||
```
|
||||
|
||||
### 6.1 关键约束
|
||||
|
||||
| 约束项 | 要求 | 原因 |
|
||||
|--------|------|------|
|
||||
| 分辨率 | **裁剪**为 360×360 | 设备屏幕为 360×360 圆形 LCD |
|
||||
| 格式 | JPEG(Baseline) | 设备端 `esp_jpeg` 仅支持 Baseline JPEG 解码 |
|
||||
| 文件后缀 | `.jpg` | 文件后缀决定设备端解码方式 |
|
||||
| 压缩质量 | 80~100 | quality < 70 在 360×360 屏幕上画质明显模糊 |
|
||||
| 单张大小 | 建议 < 100KB | SPIFFS 总容量 2MB,兼顾传输速度和存储 |
|
||||
|
||||
> **踩坑提醒**:
|
||||
> - 裁剪 ≠ 缩放。使用 `crop` 参数进行裁剪,不要使用 `compressedWidth/compressedHeight`(那是缩放,会变形)
|
||||
> - 文件保存时后缀必须是 `.jpg`,如果用 `.png` 后缀,压缩工具会输出 PNG 格式而非 JPEG,设备端无法解码
|
||||
> - 不支持 Progressive JPEG,仅支持 Baseline JPEG
|
||||
|
||||
---
|
||||
|
||||
## 七、APP 端实现参考代码
|
||||
|
||||
### 7.1 通过 UUID 匹配服务和特征
|
||||
|
||||
```javascript
|
||||
// 16-bit UUID 在 BLE 协议栈中会被扩展为 128-bit 格式
|
||||
// 例如 0x0B00 → "00000b00-0000-1000-8000-00805f9b34fb"
|
||||
// Android 和 iOS 均返回 128-bit 格式,统一用小写匹配
|
||||
function findByUuid16(list, uuid16) {
|
||||
const target = `0000${uuid16.toString(16).padStart(4, '0')}-0000-1000-8000-00805f9b34fb`;
|
||||
return list.find(item => item.uuid.toLowerCase() === target.toLowerCase());
|
||||
}
|
||||
|
||||
// 使用示例
|
||||
uni.getBLEDeviceServices({
|
||||
deviceId: deviceId,
|
||||
success(res) {
|
||||
const imageService = findByUuid16(res.services, 0x0B00);
|
||||
if (!imageService) { console.error('未找到图片服务'); return; }
|
||||
|
||||
uni.getBLEDeviceCharacteristics({
|
||||
deviceId: deviceId,
|
||||
serviceId: imageService.uuid,
|
||||
success(charRes) {
|
||||
const writeChar = findByUuid16(charRes.characteristics, 0x0B01);
|
||||
const editChar = findByUuid16(charRes.characteristics, 0x0B02);
|
||||
// writeChar.uuid → 用于图片传输
|
||||
// editChar.uuid → 用于管理命令
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 7.2 BLE 写入封装
|
||||
|
||||
```javascript
|
||||
// 必须使用 writeNoResponse,传输速度更快
|
||||
function bleWrite(deviceId, serviceId, characteristicId, buffer) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.writeBLECharacteristicValue({
|
||||
deviceId,
|
||||
serviceId,
|
||||
characteristicId,
|
||||
value: buffer,
|
||||
writeType: 'writeNoResponse', // 关键!Write Without Response
|
||||
success: resolve,
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 图片选择与预处理
|
||||
|
||||
```javascript
|
||||
// 1. 选择图片并裁剪为 360×360
|
||||
function chooseAndCropImage() {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
crop: {
|
||||
quality: 100, // 裁剪时不压缩
|
||||
width: 360, // 裁剪宽度
|
||||
height: 360, // 裁剪高度
|
||||
resize: true
|
||||
},
|
||||
success: (res) => resolve(res.tempFilePaths[0]),
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 保存为 .jpg 后缀文件(关键!决定 compressImage 输出格式)
|
||||
function saveAsJpg(tempPath, targetDir) {
|
||||
const fileName = `face_${Date.now()}.jpg`; // 必须 .jpg 后缀
|
||||
// APP-PLUS 使用 plus.io 复制文件
|
||||
// 小程序端使用 getFileSystemManager
|
||||
// ... 平台相关实现
|
||||
return { fileName, filePath };
|
||||
}
|
||||
|
||||
// 3. JPEG 压缩(输入文件后缀必须是 .jpg)
|
||||
function compressToJpeg(srcPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.compressImage({
|
||||
src: srcPath, // 输入路径后缀必须是 .jpg
|
||||
quality: 80, // 80~100 推荐,兼顾画质和体积
|
||||
success: (res) => resolve(res.tempFilePath),
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 4. 读取文件为 ArrayBuffer(APP-PLUS 平台)
|
||||
function readImageAsArrayBuffer(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
plus.io.resolveLocalFileSystemURL(filePath, (fileEntry) => {
|
||||
fileEntry.file((file) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = (e) => {
|
||||
if (e.target.result) {
|
||||
resolve(e.target.result);
|
||||
} else {
|
||||
reject(new Error('读取文件失败'));
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 7.4 图片分包传输
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 发送图片到设备
|
||||
* @param {string} deviceId - BLE 设备 ID
|
||||
* @param {string} serviceUuid - 图片服务 UUID (0x0B00 的 128-bit 形式)
|
||||
* @param {string} writeUuid - 写入特征 UUID (0x0B01 的 128-bit 形式)
|
||||
* @param {string} filename - 文件名(须 .jpg 后缀,最长 22 字节)
|
||||
* @param {ArrayBuffer} imageData - JPEG 图片二进制数据
|
||||
* @param {function} onProgress - 进度回调 (0~100)
|
||||
*/
|
||||
async function sendImage(deviceId, serviceUuid, writeUuid, filename, imageData, onProgress) {
|
||||
const data = new Uint8Array(imageData);
|
||||
const len = data.length;
|
||||
|
||||
// 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 bleWrite(deviceId, serviceUuid, writeUuid, header.buffer);
|
||||
await delay(50); // 等待设备端建立接收通道
|
||||
|
||||
// 2. 分包发送图片数据
|
||||
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 bleWrite(deviceId, serviceUuid, writeUuid, packet.buffer);
|
||||
await delay(5); // 每包间隔 5ms,防止 Android BLE 队列溢出
|
||||
|
||||
offset += chunkLen;
|
||||
packetNo++;
|
||||
|
||||
if (onProgress) {
|
||||
onProgress(Math.floor(offset / len * 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.5 发送管理命令
|
||||
|
||||
```javascript
|
||||
// 设置为当前表盘
|
||||
async function setCurrentFace(deviceId, serviceUuid, editUuid, filename) {
|
||||
const cmd = new Uint8Array(24);
|
||||
for (let i = 0; i < Math.min(filename.length, 23); i++) {
|
||||
cmd[i] = filename.charCodeAt(i);
|
||||
}
|
||||
cmd[23] = 0xFF;
|
||||
await bleWrite(deviceId, serviceUuid, editUuid, cmd.buffer);
|
||||
}
|
||||
|
||||
// 删除图片
|
||||
async function deleteImage(deviceId, serviceUuid, editUuid, filename) {
|
||||
const cmd = new Uint8Array(24);
|
||||
for (let i = 0; i < Math.min(filename.length, 23); i++) {
|
||||
cmd[i] = filename.charCodeAt(i);
|
||||
}
|
||||
cmd[23] = 0xF1;
|
||||
await bleWrite(deviceId, serviceUuid, editUuid, cmd.buffer);
|
||||
}
|
||||
```
|
||||
|
||||
### 7.6 完整传输流程示例
|
||||
|
||||
```javascript
|
||||
async function uploadWatchFace(deviceId, serviceUuid, writeUuid) {
|
||||
// 1. 选图并裁剪为 360×360
|
||||
const tempPath = await chooseAndCropImage();
|
||||
|
||||
// 2. 保存为 .jpg 后缀(关键!)
|
||||
const { fileName, filePath } = saveAsJpg(tempPath, imageDir);
|
||||
|
||||
// 3. JPEG 压缩
|
||||
const jpegPath = await compressToJpeg(filePath);
|
||||
|
||||
// 4. 读取为 ArrayBuffer
|
||||
const buffer = await readImageAsArrayBuffer(jpegPath);
|
||||
console.log('JPEG 大小:', buffer.byteLength, '字节');
|
||||
|
||||
// 5. BLE 分包传输
|
||||
await sendImage(deviceId, serviceUuid, writeUuid, fileName, buffer, (progress) => {
|
||||
console.log('传输进度:', progress + '%');
|
||||
});
|
||||
|
||||
console.log('传输完成,设备将自动显示新图片');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、Android / iOS 兼容注意事项
|
||||
|
||||
### 8.1 BLE 差异汇总
|
||||
|
||||
| 差异项 | Android | iOS |
|
||||
|--------|---------|-----|
|
||||
| MTU 协商 | `setBLEMTU(512)` 通常成功 | 系统自动协商,可能返回不同值,需检查实际 MTU |
|
||||
| 广播数据 | 厂商数据在 `advertisData` 中 | 厂商数据可能在 `advertisData` 或其他字段中 |
|
||||
| 设备 ID 格式 | MAC 地址格式(如 `D0:CF:13:03:BB:F2`) | UUID 格式(每次配对可能不同) |
|
||||
| BLE 队列 | **队列有限,发送过快触发 10007 错误** | 队列较深,但仍建议加延时 |
|
||||
| writeNoResponse | 必须加 5ms+ 包间延时 | 可适当减少延时 |
|
||||
| 蓝牙缓存 | 无明显缓存问题 | **系统缓存服务/特征列表,设备固件更新后可能读到旧数据** |
|
||||
|
||||
### 8.2 Android 特别注意
|
||||
|
||||
1. **BLE 队列溢出(错误码 10007)**:Android 的 BLE 写入队列有限,使用 `writeNoResponse` 时如果发送速度过快,队列满后会返回错误码 10007。**必须在每包之间加 5ms 延时**。
|
||||
2. **MTU 协商**:部分 Android 设备可能协商到低于 512 的 MTU。建议协商后读取实际 MTU 值,动态调整 CHUNK_SIZE = `实际MTU - 3 - 2`。
|
||||
3. **数据包截断**:如果单包超过 `MTU - 3` 字节,Android **不会报错**,而是**静默截断**数据。这会导致设备端数据不完整,JPEG 解码报错(错误码 6 = JDR_FMT1)。
|
||||
|
||||
### 8.3 iOS 特别注意
|
||||
|
||||
1. **蓝牙缓存**:iOS 会缓存 BLE 设备的服务和特征信息。如果设备固件更新了 UUID 或服务结构,iOS 可能仍使用旧缓存。解决方法:关闭 iOS 蓝牙 → 重新打开 → 重连设备。
|
||||
2. **设备 ID 不固定**:iOS 返回的 `deviceId` 是系统分配的 UUID,**不是 MAC 地址**,且取消配对后可能变化。不要用 `deviceId` 做设备持久化标识。
|
||||
3. **MTU 自动协商**:iOS 不支持手动设置 MTU(`setBLEMTU` 可能不生效),系统自动协商。通常 iOS 12+ 协商到 185~512 之间。
|
||||
|
||||
### 8.4 统一兼容建议
|
||||
|
||||
```javascript
|
||||
// 连接后获取实际 MTU(兼容 Android/iOS)
|
||||
let actualMtu = 512;
|
||||
|
||||
// Android: 手动协商
|
||||
// #ifdef APP-PLUS
|
||||
if (uni.getSystemInfoSync().platform === 'android') {
|
||||
await new Promise((resolve) => {
|
||||
uni.setBLEMTU({
|
||||
deviceId,
|
||||
mtu: 512,
|
||||
success: (res) => { actualMtu = 512; resolve(); },
|
||||
fail: () => { actualMtu = 23; resolve(); } // 协商失败用默认 MTU
|
||||
});
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 动态计算 CHUNK_SIZE
|
||||
const CHUNK_SIZE = actualMtu - 3 - 2; // MTU - ATT头(3) - 帧头(2)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、错误排查指南
|
||||
|
||||
| 现象 | 可能原因 | 解决方案 |
|
||||
|------|----------|----------|
|
||||
| 设备端 JPEG 解码失败(错误码 6) | 数据包超过 MTU-3 被截断 | 确认 CHUNK_SIZE = MTU-3-2 = 507 |
|
||||
| Android 报错 10007 | BLE 写入队列溢出 | 每包间隔加 `await delay(5)` |
|
||||
| 设备收到的不是 JPEG | 文件后缀为 `.png` | 保存文件时后缀改为 `.jpg` |
|
||||
| 图片模糊 | JPEG quality 过低 | 提高 quality 至 80~100 |
|
||||
| 图片变形拉伸 | 使用了缩放而非裁剪 | 使用 `crop` 参数裁剪 360×360 |
|
||||
| 传输完成但设备无反应 | 前序帧 `type` 不是 `0xFD` | 检查前序帧第 0 字节 |
|
||||
| 找不到服务/特征 | UUID 匹配逻辑错误 | 16-bit UUID 需扩展为 128-bit 后比较 |
|
||||
| iOS 发现旧的服务结构 | iOS 蓝牙缓存 | 关闭/重开 iOS 蓝牙后重连 |
|
||||
| 传输中断无法恢复 | 无断点续传机制 | 需从头重新传输整张图片 |
|
||||
|
||||
---
|
||||
|
||||
## 十、完整时序图
|
||||
|
||||
```
|
||||
APP 端 设备端 (ESP32-S3)
|
||||
| |
|
||||
|--- BLE 扫描(过滤厂商数据 "dzbj" | 广播中
|
||||
| 或设备名前缀 "Airhub_")------------------->|
|
||||
| |
|
||||
|--- createBLEConnection --------------------->|
|
||||
|<-- 连接成功 ----------------------------------|
|
||||
| |
|
||||
|--- setBLEMTU(512) [Android] ---------------->|
|
||||
|<-- MTU 协商完成 -------------------------------|
|
||||
| |
|
||||
|--- getBLEDeviceServices -------------------->|
|
||||
|<-- 服务列表(匹配 UUID 0x0B00)----------------|
|
||||
| |
|
||||
|--- getBLEDeviceCharacteristics -------------->|
|
||||
|<-- 特征列表(0x0B01 写入 + 0x0B02 管理)--------|
|
||||
| |
|
||||
|=========== 图片预处理 ==========================|
|
||||
| |
|
||||
| 裁剪 360×360 → 保存 .jpg → JPEG 压缩 |
|
||||
| → 读取为 ArrayBuffer |
|
||||
| |
|
||||
|=========== 传输图片 ============================|
|
||||
| |
|
||||
|--- writeNoResponse 0x0B01: |
|
||||
| [0xFD + 文件名 + 大小] (26 字节) | 解析前序帧
|
||||
| | → malloc 接收缓冲区
|
||||
| [等待 50ms] | → fopen 创建文件
|
||||
| |
|
||||
|--- writeNoResponse 0x0B01: |
|
||||
| [0 + 0x00 + 507字节数据] (≤509字节) | 数据帧 1
|
||||
| [等待 5ms] |
|
||||
|--- writeNoResponse 0x0B01: |
|
||||
| [1 + 0x00 + 507字节数据] (≤509字节) | 数据帧 2
|
||||
| [等待 5ms] |
|
||||
|--- ... |
|
||||
|--- writeNoResponse 0x0B01: |
|
||||
| [N + 0x01 + 剩余数据] (≤509字节) | 末尾帧
|
||||
| | → fwrite 写入 SPIFFS
|
||||
| | → 更新 NVS 当前表盘
|
||||
| | → 自动跳转图片浏览界面
|
||||
| |
|
||||
|=========== 管理命令 ============================|
|
||||
| |
|
||||
|--- writeNoResponse 0x0B02: |
|
||||
| [文件名 + 0xFF] (24字节) | 设置为当前表盘
|
||||
| | → 跳转图片浏览界面
|
||||
| |
|
||||
|--- writeNoResponse 0x0B02: |
|
||||
| [文件名 + 0xF1] (24字节) | 删除指定图片
|
||||
| |
|
||||
|--- closeBLEConnection ---------------------->| → 自动恢复广播
|
||||
| |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 附录:协议参数速查
|
||||
|
||||
```
|
||||
设备名称: Airhub_xx:xx:xx:xx:xx:xx(动态,后缀为BLE MAC)
|
||||
服务 UUID: 0x0B00 (00000b00-0000-1000-8000-00805f9b34fb)
|
||||
写入特征 UUID: 0x0B01 (00000b01-0000-1000-8000-00805f9b34fb)
|
||||
管理特征 UUID: 0x0B02 (00000b02-0000-1000-8000-00805f9b34fb)
|
||||
MTU: 512
|
||||
单包最大值: 509 字节 (MTU - 3)
|
||||
CHUNK_SIZE: 507 字节 (509 - 2字节帧头)
|
||||
前序帧标识: 0xFD
|
||||
设置表盘命令: 0xFF
|
||||
删除图片命令: 0xF1
|
||||
图片格式: JPEG (Baseline)
|
||||
图片分辨率: 360 × 360
|
||||
写入方式: writeNoResponse
|
||||
包间延时: 5ms (数据帧) / 50ms (前序帧后)
|
||||
```
|
||||
0
APP运行日志.md
Normal file
48
App.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<script lang="uts">
|
||||
// #ifdef APP-ANDROID || APP-HARMONY
|
||||
let firstBackTime = 0
|
||||
// #endif
|
||||
export default {
|
||||
onLaunch: function () {
|
||||
console.log('App Launch')
|
||||
},
|
||||
onShow: function () {
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function () {
|
||||
console.log('App Hide')
|
||||
},
|
||||
// #ifdef APP-ANDROID || APP-HARMONY
|
||||
onLastPageBackPress: function () {
|
||||
console.log('App LastPageBackPress')
|
||||
if (firstBackTime == 0) {
|
||||
uni.showToast({
|
||||
title: '再按一次退出应用',
|
||||
position: 'bottom',
|
||||
})
|
||||
firstBackTime = Date.now()
|
||||
setTimeout(() => {
|
||||
firstBackTime = 0
|
||||
}, 2000)
|
||||
} else if (Date.now() - firstBackTime < 2000) {
|
||||
firstBackTime = Date.now()
|
||||
uni.exit()
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
onExit: function () {
|
||||
console.log('App Exit')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*每个页面公共css */
|
||||
.uni-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
20
index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main"></script>
|
||||
</body>
|
||||
</html>
|
||||
22
main.js
Normal file
@ -0,0 +1,22 @@
|
||||
import App from './App'
|
||||
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
Vue.config.productionTip = false
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
import { createSSRApp } from 'vue'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
77
manifest.json
Normal file
@ -0,0 +1,77 @@
|
||||
{
|
||||
"name" : "电子吧唧",
|
||||
"appid" : "__UNI__F18BB63",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {
|
||||
"Bluetooth" : {},
|
||||
"Camera" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {
|
||||
"dSYMs" : false
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
24
pages.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "连接设备",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/connect/connect",
|
||||
"style": {
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8",
|
||||
"navigationStyle": "custom"
|
||||
},
|
||||
"uniIdRouter": {}
|
||||
}
|
||||
1174
pages/connect/connect.vue
Normal file
367
pages/index/index.vue
Normal file
@ -0,0 +1,367 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="title-bar">
|
||||
<text class="title">连接设备</text>
|
||||
<button
|
||||
class="scan-btn"
|
||||
:disabled="isScanning"
|
||||
@click="toggleScan"
|
||||
>
|
||||
{{ isScanning ? '停止扫描' : '开始扫描' }}
|
||||
</button>
|
||||
</view>
|
||||
<view class="status-tip" v-if="isScanning">
|
||||
<text>正在扫描设备...</text>
|
||||
<view class="loading"></view>
|
||||
</view>
|
||||
<view class="status-tip" v-else-if="foundDevices.length === 0">
|
||||
<text>未发现设备,请点击"开始扫描"</text>
|
||||
</view>
|
||||
<view class="device-list">
|
||||
<view
|
||||
class="device-item"
|
||||
v-for="(device, index) in foundDevices"
|
||||
:key="device.deviceId"
|
||||
@click="connectDevice(device)"
|
||||
>
|
||||
<!-- 设备名称 -->
|
||||
<view class="device-name">
|
||||
<text>{{ device.name || '未知设备' }}</text>
|
||||
<view class="is_bj" v-if="device.is_bj" >吧唧</view>
|
||||
<text class="device-id">{{ device.deviceId }}</text>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 信号强度 -->
|
||||
<view class="device-rssi">
|
||||
<text>信号: {{ device.rssi }} dBm</text>
|
||||
<view class="rssi-bar" :style="{ width: getRssiWidth(device.rssi) }"></view>
|
||||
</view>
|
||||
|
||||
<!-- 连接状态 -->
|
||||
<view class="device-status" v-if="device.connected">
|
||||
<text class="connected">已连接</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
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;
|
||||
// uni.showToast({ title: '蓝牙初始化成功', icon: 'none' });
|
||||
},
|
||||
fail: (err) => {
|
||||
this.bluetoothEnabled = false;
|
||||
uni.showModal({
|
||||
title: '蓝牙开启失败',
|
||||
content: '请检查设备蓝牙是否开启',
|
||||
showCancel: false
|
||||
});
|
||||
console.error('蓝牙初始化失败:', err);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 切换扫描状态(开始/停止)
|
||||
toggleScan() {
|
||||
if (!this.bluetoothEnabled) {
|
||||
this.initBluetooth();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isScanning) {
|
||||
this.stopScan();
|
||||
} else {
|
||||
this.startScan();
|
||||
}
|
||||
},
|
||||
|
||||
// 开始扫描设备
|
||||
startScan() {
|
||||
this.isScanning = true;
|
||||
this.foundDevices = []; // 清空历史列表
|
||||
|
||||
// 开始扫描(空services表示扫描所有设备)
|
||||
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' });
|
||||
console.error('扫描失败:', err);
|
||||
}
|
||||
});
|
||||
|
||||
// 10秒后自动停止扫描(避免耗电)
|
||||
setTimeout(() => {
|
||||
if (this.isScanning) this.stopScan();
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
// 停止扫描
|
||||
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) => {
|
||||
console.error('停止扫描失败:', err);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 设备发现回调(处理去重和数据格式化)
|
||||
onDeviceFound(res) {
|
||||
const devices = res.devices || [];
|
||||
devices.forEach(device => {
|
||||
var that = this
|
||||
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 companyidData = (advData[0]<<8)| advData[1];
|
||||
const devicenameData = advData.slice(2, 6);
|
||||
const devicename = String.fromCharCode(...devicenameData)
|
||||
if(devicename == 'dzbj') is_bj = true;
|
||||
this.foundDevices.push({
|
||||
is_bj: 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)); // 限制在0-1之间
|
||||
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' });
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 16rpx;
|
||||
background-color: #f5f5f5;
|
||||
/* min-height: 100vh; */
|
||||
}
|
||||
|
||||
/* 标题栏 */
|
||||
.title-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 80rpx;
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.scan-btn {
|
||||
background-color: #00c900;
|
||||
color: white;
|
||||
padding: 0rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
.scan-btn:disabled {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
/* 状态提示 */
|
||||
.status-tip {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.loading {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border: 3rpx solid #007aff;
|
||||
border-top-color: transparent;
|
||||
border-radius: 50%;
|
||||
margin: 20rpx auto;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 设备列表 */
|
||||
.device-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.device-item {
|
||||
background-color: white;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.device-name {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.device-name text:first-child {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.is_bj{
|
||||
padding: 3px 8px;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
background-color: rgba(30, 228, 156, 0.4);
|
||||
position: relative;
|
||||
right: 30px;
|
||||
}
|
||||
|
||||
.device-id {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.device-rssi {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.device-rssi text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.rssi-bar {
|
||||
height: 8rpx;
|
||||
background-color: #eee;
|
||||
border-radius: 4rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rssi-bar::after {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, #ff4d4f, #faad14, #52c41a);
|
||||
}
|
||||
|
||||
.device-status {
|
||||
margin-top: 16rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.connected {
|
||||
font-size: 26rpx;
|
||||
color: #07c160;
|
||||
background-color: #f0fff4;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
</style>
|
||||
BIN
static/logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
76
uni.scss
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
/* 颜色变量 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color:#333;//基本色
|
||||
$uni-text-color-inverse:#fff;//反色
|
||||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable:#c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color:#ffffff;
|
||||
$uni-bg-color-grey:#f8f8f8;
|
||||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color:#c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm:12px;
|
||||
$uni-font-size-base:14px;
|
||||
$uni-font-size-lg:16px;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm:20px;
|
||||
$uni-img-size-base:26px;
|
||||
$uni-img-size-lg:40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2C405A; // 文章标题颜色
|
||||
$uni-font-size-title:20px;
|
||||
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||
$uni-font-size-subtitle:26px;
|
||||
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||
$uni-font-size-paragraph:15px;
|
||||
20
unpackage/cache/.app-android/src/.manifest.json
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"version": "1",
|
||||
"env": {
|
||||
"compiler_version": "4.75"
|
||||
},
|
||||
"files": {
|
||||
"index.kt": {
|
||||
"md5": "b0472b5db44be590378fc50326855998d60e269f",
|
||||
"class": ""
|
||||
},
|
||||
"pages/index/index.kt": {
|
||||
"md5": "1a4e97ed30f53bc3dfac7578dc936112fdea97ac",
|
||||
"class": "GenPagesIndexIndex"
|
||||
},
|
||||
"pages/connect/connect.kt": {
|
||||
"class": "GenPagesConnectConnect",
|
||||
"md5": "26eaeeb2bc930c21bc0dfa3ec88ca0c191fa336f"
|
||||
}
|
||||
}
|
||||
}
|
||||
212
unpackage/cache/.app-android/src/index.kt
vendored
Normal file
454
unpackage/cache/.app-android/src/pages/connect/connect.kt
vendored
Normal file
259
unpackage/cache/.app-android/src/pages/index/index.kt
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
@file:Suppress("UNCHECKED_CAST", "USELESS_CAST", "INAPPLICABLE_JVM_NAME", "UNUSED_ANONYMOUS_PARAMETER", "NAME_SHADOWING", "UNNECESSARY_NOT_NULL_ASSERTION")
|
||||
package uni.UNIuniappx
|
||||
import io.dcloud.uniapp.*
|
||||
import io.dcloud.uniapp.extapi.*
|
||||
import io.dcloud.uniapp.framework.*
|
||||
import io.dcloud.uniapp.runtime.*
|
||||
import io.dcloud.uniapp.vue.*
|
||||
import io.dcloud.uniapp.vue.shared.*
|
||||
import io.dcloud.unicloud.*
|
||||
import io.dcloud.uts.*
|
||||
import io.dcloud.uts.Map
|
||||
import io.dcloud.uts.Set
|
||||
import io.dcloud.uts.UTSAndroid
|
||||
import io.dcloud.uniapp.extapi.closeBLEConnection as uni_closeBLEConnection
|
||||
import io.dcloud.uniapp.extapi.closeBluetoothAdapter as uni_closeBluetoothAdapter
|
||||
import io.dcloud.uniapp.extapi.createBLEConnection as uni_createBLEConnection
|
||||
import io.dcloud.uniapp.extapi.hideLoading as uni_hideLoading
|
||||
import io.dcloud.uniapp.extapi.navigateTo as uni_navigateTo
|
||||
import io.dcloud.uniapp.extapi.offBluetoothDeviceFound as uni_offBluetoothDeviceFound
|
||||
import io.dcloud.uniapp.extapi.onBluetoothDeviceFound as uni_onBluetoothDeviceFound
|
||||
import io.dcloud.uniapp.extapi.openBluetoothAdapter as uni_openBluetoothAdapter
|
||||
import io.dcloud.uniapp.extapi.showLoading as uni_showLoading
|
||||
import io.dcloud.uniapp.extapi.showModal as uni_showModal
|
||||
import io.dcloud.uniapp.extapi.showToast as uni_showToast
|
||||
import io.dcloud.uniapp.extapi.startBluetoothDevicesDiscovery as uni_startBluetoothDevicesDiscovery
|
||||
import io.dcloud.uniapp.extapi.stopBluetoothDevicesDiscovery as uni_stopBluetoothDevicesDiscovery
|
||||
open class GenPagesIndexIndex : BasePage {
|
||||
constructor(__ins: ComponentInternalInstance, __renderer: String?) : super(__ins, __renderer) {
|
||||
onLoad(fun(_: OnLoadOptions) {
|
||||
this.initBluetooth()
|
||||
}
|
||||
, __ins)
|
||||
onUnload(fun() {
|
||||
this.stopScan()
|
||||
uni_closeBluetoothAdapter()
|
||||
uni_offBluetoothDeviceFound(this.onDeviceFound)
|
||||
}
|
||||
, __ins)
|
||||
}
|
||||
@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
|
||||
override fun `$render`(): Any? {
|
||||
val _ctx = this
|
||||
val _cache = this.`$`.renderCache
|
||||
return _cE("view", _uM("class" to "container"), _uA(
|
||||
_cE("view", _uM("class" to "title-bar"), _uA(
|
||||
_cE("text", _uM("class" to "title"), "连接设备"),
|
||||
_cE("button", _uM("class" to "scan-btn", "disabled" to _ctx.isScanning, "onClick" to _ctx.toggleScan), _tD(if (_ctx.isScanning) {
|
||||
"停止扫描"
|
||||
} else {
|
||||
"开始扫描"
|
||||
}
|
||||
), 9, _uA(
|
||||
"disabled",
|
||||
"onClick"
|
||||
))
|
||||
)),
|
||||
if (isTrue(_ctx.isScanning)) {
|
||||
_cE("view", _uM("key" to 0, "class" to "status-tip"), _uA(
|
||||
_cE("text", null, "正在扫描设备..."),
|
||||
_cE("view", _uM("class" to "loading"))
|
||||
))
|
||||
} else {
|
||||
if (_ctx.foundDevices.length === 0) {
|
||||
_cE("view", _uM("key" to 1, "class" to "status-tip"), _uA(
|
||||
_cE("text", null, "未发现设备,请点击\"开始扫描\"")
|
||||
))
|
||||
} else {
|
||||
_cC("v-if", true)
|
||||
}
|
||||
}
|
||||
,
|
||||
_cE("view", _uM("class" to "device-list"), _uA(
|
||||
_cE(Fragment, null, RenderHelpers.renderList(_ctx.foundDevices, fun(device, index, __index, _cached): Any {
|
||||
return _cE("view", _uM("class" to "device-item", "key" to device.deviceId, "onClick" to fun(){
|
||||
_ctx.connectDevice(device)
|
||||
}
|
||||
), _uA(
|
||||
_cE("view", _uM("class" to "device-name"), _uA(
|
||||
_cE("text", null, _tD(device.name || "未知设备"), 1),
|
||||
if (isTrue(device.is_bj)) {
|
||||
_cE("view", _uM("key" to 0, "class" to "is_bj"), "吧唧")
|
||||
} else {
|
||||
_cC("v-if", true)
|
||||
}
|
||||
,
|
||||
_cE("text", _uM("class" to "device-id"), _tD(device.deviceId), 1)
|
||||
)),
|
||||
_cE("view", _uM("class" to "device-rssi"), _uA(
|
||||
_cE("text", null, "信号: " + _tD(device.rssi) + " dBm", 1),
|
||||
_cE("view", _uM("class" to "rssi-bar", "style" to _nS(_uM("width" to _ctx.getRssiWidth(device.rssi)))), null, 4)
|
||||
)),
|
||||
if (isTrue(device.connected)) {
|
||||
_cE("view", _uM("key" to 0, "class" to "device-status"), _uA(
|
||||
_cE("text", _uM("class" to "connected"), "已连接")
|
||||
))
|
||||
} else {
|
||||
_cC("v-if", true)
|
||||
}
|
||||
), 8, _uA(
|
||||
"onClick"
|
||||
))
|
||||
}
|
||||
), 128)
|
||||
))
|
||||
))
|
||||
}
|
||||
open var foundDevices: UTSArray<Any?> by `$data`
|
||||
open var isScanning: Boolean by `$data`
|
||||
open var bluetoothEnabled: Boolean by `$data`
|
||||
open var connectedDeviceId: String by `$data`
|
||||
@Suppress("USELESS_CAST")
|
||||
override fun data(): Map<String, Any?> {
|
||||
return _uM("foundDevices" to _uA(), "isScanning" to false, "bluetoothEnabled" to false, "connectedDeviceId" to "")
|
||||
}
|
||||
open var initBluetooth = ::gen_initBluetooth_fn
|
||||
open fun gen_initBluetooth_fn() {
|
||||
uni_openBluetoothAdapter(OpenBluetoothAdapterOptions(success = fun(_){
|
||||
this.bluetoothEnabled = true
|
||||
}
|
||||
, fail = fun(err){
|
||||
this.bluetoothEnabled = false
|
||||
uni_showModal(ShowModalOptions(title = "蓝牙开启失败", content = "请检查设备蓝牙是否开启", showCancel = false))
|
||||
console.error("蓝牙初始化失败:", err, " at pages/index/index.uvue:88")
|
||||
}
|
||||
))
|
||||
}
|
||||
open var toggleScan = ::gen_toggleScan_fn
|
||||
open fun gen_toggleScan_fn() {
|
||||
if (!this.bluetoothEnabled) {
|
||||
this.initBluetooth()
|
||||
return
|
||||
}
|
||||
if (this.isScanning) {
|
||||
this.stopScan()
|
||||
} else {
|
||||
this.startScan()
|
||||
}
|
||||
}
|
||||
open var startScan = ::gen_startScan_fn
|
||||
open fun gen_startScan_fn() {
|
||||
this.isScanning = true
|
||||
this.foundDevices = _uA()
|
||||
uni_startBluetoothDevicesDiscovery(StartBluetoothDevicesDiscoveryOptions(services = _uA(), allowDuplicatesKey = false, success = fun(_){
|
||||
uni_showToast(ShowToastOptions(title = "开始扫描", icon = "none"))
|
||||
uni_onBluetoothDeviceFound(this.onDeviceFound)
|
||||
}
|
||||
, fail = fun(err){
|
||||
this.isScanning = false
|
||||
uni_showToast(ShowToastOptions(title = "扫描失败", icon = "none"))
|
||||
console.error("扫描失败:", err, " at pages/index/index.uvue:124")
|
||||
}
|
||||
))
|
||||
setTimeout(fun(){
|
||||
if (this.isScanning) {
|
||||
this.stopScan()
|
||||
}
|
||||
}
|
||||
, 5000)
|
||||
}
|
||||
open var stopScan = ::gen_stopScan_fn
|
||||
open fun gen_stopScan_fn() {
|
||||
if (!this.isScanning) {
|
||||
return
|
||||
}
|
||||
uni_stopBluetoothDevicesDiscovery(StopBluetoothDevicesDiscoveryOptions(success = fun(_){
|
||||
this.isScanning = false
|
||||
if (this.foundDevices.length == 0) {
|
||||
uni_showToast(ShowToastOptions(title = "\u6682\u672A\u626B\u63CF\u5230\u4EFB\u4F55\u8BBE\u5907", icon = "none"))
|
||||
return
|
||||
}
|
||||
uni_showToast(ShowToastOptions(title = "\u626B\u63CF\u5B8C\u6210\uFF0C\u53D1\u73B0" + this.foundDevices.length + "\u53F0\u8BBE\u5907", icon = "none"))
|
||||
}
|
||||
, fail = fun(err){
|
||||
console.error("停止扫描失败:", err, " at pages/index/index.uvue:154")
|
||||
}
|
||||
))
|
||||
}
|
||||
open var onDeviceFound = ::gen_onDeviceFound_fn
|
||||
open fun gen_onDeviceFound_fn(res) {
|
||||
val devices = res.devices || _uA()
|
||||
devices.forEach(fun(device){
|
||||
if (!device.deviceId) {
|
||||
return
|
||||
}
|
||||
val isExist = this.foundDevices.some(fun(d): Boolean {
|
||||
return d.deviceId === device.deviceId
|
||||
}
|
||||
)
|
||||
if (isExist) {
|
||||
return
|
||||
}
|
||||
var is_bj = false
|
||||
val advData = Uint8Array(device.advertisData)
|
||||
val devicenameData = advData.slice(2, 6)
|
||||
val devicename = String.fromCharCode(*devicenameData.toTypedArray())
|
||||
if (devicename == "dzbj") {
|
||||
is_bj = true
|
||||
}
|
||||
this.foundDevices.push(_uO("is_bj" to is_bj, "name" to (device.name || "未知设备"), "deviceId" to device.deviceId, "rssi" to device.RSSI, "connected" to (device.deviceId === this.connectedDeviceId)))
|
||||
}
|
||||
)
|
||||
}
|
||||
open var getRssiWidth = ::gen_getRssiWidth_fn
|
||||
open fun gen_getRssiWidth_fn(rssi): String {
|
||||
val minRssi: Number = -100
|
||||
val maxRssi: Number = -30
|
||||
var ratio = (rssi - minRssi) / (maxRssi - minRssi)
|
||||
ratio = Math.max(0, Math.min(1, ratio))
|
||||
return "" + ratio * 100 + "%"
|
||||
}
|
||||
open var connectDevice = ::gen_connectDevice_fn
|
||||
open fun gen_connectDevice_fn(device) {
|
||||
var that = this
|
||||
this.stopScan()
|
||||
uni_showLoading(ShowLoadingOptions(title = "连接中..."))
|
||||
uni_createBLEConnection(CreateBLEConnectionOptions(deviceId = device.deviceId, success = fun(res) {
|
||||
that.foundDevices = that.foundDevices.map(fun(d){
|
||||
return UTSJSONObject.assign(UTSJSONObject(), d, object : UTSJSONObject() {
|
||||
var connected = d.deviceId === device.deviceId
|
||||
})
|
||||
}
|
||||
)
|
||||
uni_hideLoading()
|
||||
uni_showToast(ShowToastOptions(title = "\u5DF2\u8FDE\u63A5" + device.name, icon = "none"))
|
||||
uni_navigateTo(NavigateToOptions(url = "../connect/connect?deviceId=" + device.deviceId, fail = fun(err){
|
||||
uni_showToast(ShowToastOptions(title = "\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", icon = "error"))
|
||||
uni_closeBLEConnection(CloseBLEConnectionOptions(deviceId = device.deviceId, success = fun(_) {
|
||||
console("断开连接成功")
|
||||
}
|
||||
))
|
||||
}
|
||||
))
|
||||
}
|
||||
, fail = fun(_) {
|
||||
uni_hideLoading()
|
||||
uni_showToast(ShowToastOptions(title = "\u8FDE\u63A5\u5931\u8D25", icon = "error"))
|
||||
}
|
||||
))
|
||||
}
|
||||
companion object {
|
||||
val styles: Map<String, Map<String, Map<String, Any>>> by lazy {
|
||||
_nCS(_uA(
|
||||
styles0
|
||||
), _uA(
|
||||
GenApp.styles
|
||||
))
|
||||
}
|
||||
val styles0: Map<String, Map<String, Map<String, Any>>>
|
||||
get() {
|
||||
return _uM("container" to _pS(_uM("paddingTop" to "16rpx", "paddingRight" to "16rpx", "paddingBottom" to "16rpx", "paddingLeft" to "16rpx", "backgroundColor" to "#f5f5f5")), "title-bar" to _pS(_uM("display" to "flex", "justifyContent" to "space-between", "alignItems" to "center", "paddingTop" to "20rpx", "paddingRight" to 0, "paddingBottom" to "20rpx", "paddingLeft" to 0, "borderBottomWidth" to 1, "borderBottomStyle" to "solid", "borderBottomColor" to "#eeeeee", "marginBottom" to "20rpx", "marginTop" to "80rpx")), "title" to _pS(_uM("fontSize" to "36rpx", "fontWeight" to "bold", "color" to "#333333")), "scan-btn" to _pS(_uM("backgroundColor" to "#00c900", "color" to "#FFFFFF", "paddingTop" to "0rpx", "paddingRight" to "24rpx", "paddingBottom" to "0rpx", "paddingLeft" to "24rpx", "borderTopLeftRadius" to "8rpx", "borderTopRightRadius" to "8rpx", "borderBottomRightRadius" to "8rpx", "borderBottomLeftRadius" to "8rpx", "fontSize" to "28rpx", "marginRight" to "5%", "backgroundColor:disabled" to "#cccccc")), "status-tip" to _pS(_uM("textAlign" to "center", "paddingTop" to "40rpx", "paddingRight" to 0, "paddingBottom" to "40rpx", "paddingLeft" to 0, "color" to "#666666", "fontSize" to "28rpx")), "loading" to _pS(_uM("width" to "30rpx", "height" to "30rpx", "borderTopWidth" to "3rpx", "borderRightWidth" to "3rpx", "borderBottomWidth" to "3rpx", "borderLeftWidth" to "3rpx", "borderTopStyle" to "solid", "borderRightStyle" to "solid", "borderBottomStyle" to "solid", "borderLeftStyle" to "solid", "borderTopColor" to "rgba(0,0,0,0)", "borderRightColor" to "#007aff", "borderBottomColor" to "#007aff", "borderLeftColor" to "#007aff", "marginTop" to "20rpx", "marginRight" to "auto", "marginBottom" to "20rpx", "marginLeft" to "auto", "animation" to "spin 1s linear infinite")), "device-list" to _pS(_uM("display" to "flex", "flexDirection" to "column", "gap" to "16rpx")), "device-item" to _pS(_uM("backgroundColor" to "#FFFFFF", "borderTopLeftRadius" to "12rpx", "borderTopRightRadius" to "12rpx", "borderBottomRightRadius" to "12rpx", "borderBottomLeftRadius" to "12rpx", "paddingTop" to "24rpx", "paddingRight" to "24rpx", "paddingBottom" to "24rpx", "paddingLeft" to "24rpx", "boxShadow" to "0 2rpx 8rpx rgba(0,0,0,0.1)", "cursor" to "pointer")), "device-name" to _pS(_uM("display" to "flex", "justifyContent" to "space-between", "marginBottom" to "16rpx")), "is_bj" to _pS(_uM("paddingTop" to 3, "paddingRight" to 8, "paddingBottom" to 3, "paddingLeft" to 8, "borderTopLeftRadius" to 5, "borderTopRightRadius" to 5, "borderBottomRightRadius" to 5, "borderBottomLeftRadius" to 5, "color" to "#FFFFFF", "backgroundColor" to "rgba(30,228,156,0.4)", "position" to "relative", "right" to 30)), "device-id" to _pS(_uM("fontSize" to "24rpx", "color" to "#999999")), "device-rssi" to _pS(_uM("display" to "flex", "flexDirection" to "column", "gap" to "8rpx")), "rssi-bar" to _pS(_uM("height" to "8rpx", "backgroundColor" to "#eeeeee", "borderTopLeftRadius" to "4rpx", "borderTopRightRadius" to "4rpx", "borderBottomRightRadius" to "4rpx", "borderBottomLeftRadius" to "4rpx", "overflow" to "hidden", "content::after" to "''", "height::after" to "100%", "backgroundImage::after" to "linear-gradient(to right, #ff4d4f, #faad14, #52c41a)", "backgroundColor::after" to "rgba(0,0,0,0)")), "device-status" to _pS(_uM("marginTop" to "16rpx", "textAlign" to "right")), "connected" to _pS(_uM("fontSize" to "26rpx", "color" to "#07c160", "backgroundColor" to "#f0fff4", "paddingTop" to "4rpx", "paddingRight" to "16rpx", "paddingBottom" to "4rpx", "paddingLeft" to "16rpx", "borderTopLeftRadius" to "12rpx", "borderTopRightRadius" to "12rpx", "borderBottomRightRadius" to "12rpx", "borderBottomLeftRadius" to "12rpx")), "@FONT-FACE" to _uM("0" to _uM()))
|
||||
}
|
||||
var inheritAttrs = true
|
||||
var inject: Map<String, Map<String, Any?>> = _uM()
|
||||
var emits: Map<String, Any?> = _uM()
|
||||
var props = _nP(_uM())
|
||||
var propsNeedCastKeys: UTSArray<String> = _uA()
|
||||
var components: Map<String, CreateVueComponent> = _uM()
|
||||
}
|
||||
}
|
||||
1
unpackage/cache/.app-android/tsc/app-android/.tsbuildInfo
vendored
Normal file
BIN
unpackage/cache/apk/__UNI__F18BB63_cm.apk
vendored
Normal file
1
unpackage/cache/apk/apkurl
vendored
Normal file
@ -0,0 +1 @@
|
||||
https://app.liuyingyong.cn/build/download/94072910-00bc-11f1-8671-85bf92ef3a20
|
||||
1
unpackage/cache/apk/cmManifestCache.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
b1kWame9yBmby5SJKXZdMiBIfIZ7jYUx3ZnXt20I8klef9B7ZTIAFKtSJZT7FZLkzKWKT9W6pVd8W3D0oyyg68ZjK8usUw2Toml0WV8t5QFWqr7P89AaSN8HUAszjVXW1MTW5vkTdkhlvsbW3fbL5AbghM72zG0rued7+eRmRt+1Jn/eYqbLM+g65OPdI5QhFMPb49NcXcw+Vu8FXdaBtcN+w/JXJ4BQztTi1BY8F54ipgU0ugffXgTOzZCMQBLqCasZHJYLlyuMhUn0QEqYIVBVp0GZiQr2UmabZgoHhXDRFTL4fSPtnXCDHpBlPkqMzoteSc683WNGpWb4pyf60MN85hK92DlgJcUvua4jsfJoh8+dxCAlz3Un/Lrjy/0FCTSacipV53EHKrrVFMo0dy449zameraaGqYWsFaRflEX/X9vaI1141lyDRAHcyyVBYeJanS0MTGzuaSftW4jVrMapUsCrJTsFvtfRsSjxR5WBi44KvjHw0EEnGABqwUWZK+UwlllNY+FhMMqzLbd49bWhPEo4UBuR8nNPr9N4XJZ/K6KJVst0pgwq4v0SRNp+gcnAmsyiL1rpKHtU2EaQe+G6cnC5JsLrulJ+tpopxLwadoCFxgnC7koRwCtqp5P3lYUf9dFZ1b8Z5nrrgpzoKtvONRaIWKStFomxMlgfQvXrsf72zRuriUD2ex4aWBgF8aCZpM19tf971pvigSKP+0x425P016Ziel4QrwKK13l96x1ITKN/itq+RIW89WyoBTAzPub1qReIDbzBU5kuokhG2069F9wdbIQPhnb+ef3MnOb/U43ixonzfcQ4tw/6Ws6uUrbzIl7YqRG0HOiW2h5/28QbigB6RdRa1e3Q3byxLO/ZVP04c9NYdFOu4JjP3pvlKO93OpmfwKVxUzIDiA3Qfr5AV8pFNLekSPpKN+TeCsk+o4rpNPecU75cwtyucFsjtwE7PVHVtd6bB5KP/jJgp655nnaiKPV21nJIcXFx5dJUqYL+3qf/EDIQD7xtMu+FH2DaKvOCxrnoiBvvj9hi+m3okYGXx+GuKe1DcMAkTqBSCzEf0GglPBERTfXH5N/lYNfUgG3XhxeEcpPcXWXDTgrTJGM0yhHPuRT7qgsx3w56GnITYO5uExxQCWHZhPZwP8mxBci1crPQfw864OtaYgt5DDfQwuu3rAl6MwF7e3oMtel7Qt0OVVhUczxu+D/YptjpnQ25Ylf4d8O4i0bqqdLpBzsSE9loQ+h4xUE9LPmhoxLjghF1ViY/rd67bQhEwRGpZlHvNyMZzrgBfUy2L2Z4ofX7+3T3aGIKgkHpEehrvAILNNj9l6F3fqOAd3pU3nEwg79GeMqBXUAqOWYQxTEI2hJg918gCWY2B5oKy5l3jG9vL7PiEgw6/vVv1evN3z0wPFvPZ4iSSiauV/fs1HyZUEou2nqq34/EVOhVvMQ1oyRLJj8GaoQShYw2MsWEhjdpPN5LVf6TTjN9YNgJcItgX5JaitQ3RuO7+QifHuTjlAKbcMkKfnBLdZXUVEqma+YJ1ecviFQmplGjP+a1RfDHYMuk+AS+oSpCKkQVqLAu9jgctvdXfWXcesj+F3ELZ+2PemsTLed0VlhB2uHe57T0h3sbtmfXeXrdCLifYGbFzypI1IXU8QBY3ZNUjtGv0+d5S1+Qiyt4fR6QFzeLrwMGFDUgWWh2BMhp5VGpsvie+QSP+odus/TXsuDqOpSgPuSEZh3BnUiKTbroUEKc7NQ6xgNSYOVIon57ZzrVNiREIyvgCrr3PIheIwywo/9824G/Jmt61aw1Ms9DoibvSrvIG/98R5T4Bphb51awa4PIzhaKoTHXnPpEziG5x1Wilme65GfiSQ7wRtzuoZU67wICTiR65ZZKGSykuTA2mZ74odYR543h2EJ4p+ZSHIXpsCmLr04Pn1+yMLRggHmWWbZwGNWBzfh+JUg1F02waxaw9oOTM/+2BKMLoBscCd3Pi4kg2awynB7ef/AHPC3qkxkSofRodWQWcJeut8/iZdhEZZ2xbcBo+uoI/2l4DmkSBVhNlpsGNpXzCpJLndoDSgqvOzojF4x7oT2al9Vaf2kq4BRyyMw2IBExksnjXbMf/K0lPBzYIxX+TvTKUgXuWpOnr7nQGJr12hNT6tfdO5lCZI7T7BQPxj4klew5P9isiYnOQH4ECudYsoaLg+14tfHG1LHcCWcxO1qtNv9C6uB1jLj+zaHHvHCrFqUi1zd3w+s3mKvp7HqfcmlEoCsdSkqD3NVBYeSDWXIjfZfk7Y1vidOIHBqEt8clr4kdGPPMuNT4vJsVl0ZOaduVoAUCeCK1E8K8x1hxmpF/481vp0+HzW1eerUsb5z76dGsJ0lOcUSfv8bilGSVOM0snxuwrtVkiKN4zD8TP1MkSQBXsedjM/xHnxk989Qdo7zPX/e8GLXNpnjhkl0NFNm560bd7tsuc7z9HKuTPG99F++ETEyVZ6jPNzlRMe3sUPBQpOuWlCvZGUUsNeyUHxjQ77TAbTkDMO6xOFrY0vruAO+5VPMqEk6UJqS3nuDKcdQFypQo3dGQClZ3VC4NUt/SEDQd9PdYlhvR6ZQG9o4HGyjFOcr+pbGXpRgdCjXs/Z6VSIEo+WneTCQbLMYR6bJ0i7fJ849yLlCrWbkEfC9BoJc1DhetkK4ElgLy6Hx3J8e/nFxz+a6AKRPYB84ZUk/2Ixrlf5awtW8LXjZuUkGYznSvSpvpW69b9ziU/FtZ3ucMOX6oY+HB2nlrrV48ppp1/+f2C3nG0swNgy1LIAEicyYNq+ufoaCRHwPG3Oa7csIzxCrsJtEV/u1GXa2bY3bcmf9SBuDSCx6zvj+zEm9hUgGCPrW2OVCAWE4oQsm7NNGko5NxjjTgVUbTY6Q2XnFfbrx6RMAwa+qMTkT1Ypk7eA+oJYe5+vp0nrK94SYX3ag1hxi+SL8CCjnr02Hnsd2mAU+OxaH6zeLSiVkTaKTPvyX/oEJLYEynpIV0zFLZ9mMn8epgq2gkJy3DaMNpzOFDccUwszWTxuSBtVhHbGUweZ74p+N9sg148XmFnx7WRuyYfEBF6hTza6MgRBpihD64iNU1j9PkGZAS4TlegofkmpyiZoknyx6r0VWZfbV2S6JV4XEhdiuwRcPTFfgitr0O6J/1J6kzhhyQpK5q3O2b30y2+D7YtzPFfssTvidpvSuCZkHy06MjdZBeTt03mY2C/koDP7PSFQAUO2yAhDh1ahLbl8EPd965f5vFTIdOYAJ5txk2iErTlBH3PWfu44nraG+EX7R37HGSon3ATBqAtqm/1TJEu6Luow4YcqvI3vP1svlfBCeJUuF7+CbCULvuJCySxtqzYMnuwlTxaVG7HEzTS8qIMb4zU/L+PfgI/MsWKQNp11AmUTOxIMJdmb4eXRkgmiVNqpR8SD+bAdn2nI1ar6jth6blGoPufSRL/0l
|
||||
4
unpackage/cache/certdata
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
andrCertfile=D:/HBuilderX/plugins/app-safe-pack/Test.keystore
|
||||
andrCertAlias=android
|
||||
andrCertPass=ep/Tdjka4Y7WYqDB6/S7dw==
|
||||
storePassword=ep/Tdjka4Y7WYqDB6/S7dw==
|
||||
4
unpackage/cache/cloudcertificate/certini
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[General]
|
||||
andrCertfile=package.keystore
|
||||
andrCertAlias=__UNI__F18BB63
|
||||
andrCertPass="53DWTUGpKLtjkDlwhCDiOA=="
|
||||
BIN
unpackage/cache/cloudcertificate/package.keystore
vendored
Normal file
16
unpackage/cache/wgt/__UNI__F18BB63/__uniappautomator.js
vendored
Normal file
32
unpackage/cache/wgt/__UNI__F18BB63/__uniappchooselocation.js
vendored
Normal file
BIN
unpackage/cache/wgt/__UNI__F18BB63/__uniapperror.png
vendored
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
32
unpackage/cache/wgt/__UNI__F18BB63/__uniappopenlocation.js
vendored
Normal file
33
unpackage/cache/wgt/__UNI__F18BB63/__uniapppicker.js
vendored
Normal file
8
unpackage/cache/wgt/__UNI__F18BB63/__uniappquill.js
vendored
Normal file
1
unpackage/cache/wgt/__UNI__F18BB63/__uniappquillimageresize.js
vendored
Normal file
32
unpackage/cache/wgt/__UNI__F18BB63/__uniappscan.js
vendored
Normal file
BIN
unpackage/cache/wgt/__UNI__F18BB63/__uniappsuccess.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
24
unpackage/cache/wgt/__UNI__F18BB63/__uniappview.html
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>View</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<link rel="stylesheet" href="app.css" />
|
||||
<script>var __uniConfig = {"globalStyle":{},"darkmode":false}</script>
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="uni-app-view.umd.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
11
unpackage/cache/wgt/__UNI__F18BB63/app-config-service.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
;(function(){
|
||||
let u=void 0,isReady=false,onReadyCallbacks=[],isServiceReady=false,onServiceReadyCallbacks=[];
|
||||
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#F8F8F8","navigationBar":{"backgroundColor":"#F8F8F8","titleText":"","style":"custom","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"dzbj","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"4.75","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
|
||||
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"navigationBar":{"titleText":"连接设备","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/connect/connect","meta":{"navigationBar":{"type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
|
||||
__uniConfig.styles=[];//styles
|
||||
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:16})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:u,window:u,document:u,frames:u,self:u,location:u,navigator:u,localStorage:u,history:u,Caches:u,screen:u,alert:u,confirm:u,prompt:u,fetch:u,XMLHttpRequest:u,WebSocket:u,webkit:u,print:u}}}});
|
||||
})();
|
||||
|
||||
1
unpackage/cache/wgt/__UNI__F18BB63/app-config.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(function(){})();
|
||||
1
unpackage/cache/wgt/__UNI__F18BB63/app-service.js
vendored
Normal file
3
unpackage/cache/wgt/__UNI__F18BB63/app.css
vendored
Normal file
1
unpackage/cache/wgt/__UNI__F18BB63/app.css.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.css.js","sources":["uni-app:///D:/HBuilderX/plugins/uniapp-cli-vite/app.css.js"],"sourcesContent":null,"names":[],"mappings":";;;;;;;AAGA,YAAQ,SAAS,CAAC,QAAQ;AAAA;AAAA;"}
|
||||
1
unpackage/cache/wgt/__UNI__F18BB63/app.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.js","sources":[],"sourcesContent":null,"names":[],"mappings":";;"}
|
||||
1
unpackage/cache/wgt/__UNI__F18BB63/manifest.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__F18BB63","name":"dzbj","version":{"name":"1.0.0","code":"100"},"description":"","developer":{"name":"","email":"","url":""},"permissions":{"Bluetooth":{},"Camera":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":true,"delay":0,"target":"id:1","waiting":true},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"packagename":"uni.app.UNI08167A6","custompermissions":true},"apple":{"dSYMs":false,"devices":"universal"},"plugins":{"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}},"orientation":"portrait-primary"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"control":"uni-v3","vueVersion":"3","compilerVersion":"4.75","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal","webView":{"minUserAgentVersion":"49.0"}},"adid":"128665270412"},"app-harmony":{"useragent":{"value":"uni-app","concatenate":true},"uniStatistics":{"enable":false}},"launch_path":"__uniappview.html"}
|
||||
1
unpackage/cache/wgt/__UNI__F18BB63/pages/connect/connect.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.status-pot[data-v-6b60e2e0]{width:16px;height:16px;border-radius:50%}.container[data-v-6b60e2e0]{background-color:#f5f5f7;min-height:100vh}.nav-bar[data-v-6b60e2e0]{display:flex;justify-content:space-between;align-items:center;padding:.625rem .9375rem;background-color:#fff}.nav-title[data-v-6b60e2e0]{color:#fff;font-size:1.125rem;font-weight:500}.upload-btn[data-v-6b60e2e0]{align-items:center;gap:.25rem;background-color:#28d50e;color:#fff;width:35%;margin-top:10px;padding:.4375rem 0;border-radius:.25rem;font-size:.8125rem}.content[data-v-6b60e2e0]{padding:.9375rem}.section-title[data-v-6b60e2e0]{display:block;font-size:1rem;color:#333;margin:.9375rem 0 .625rem;font-weight:500}.preview-container[data-v-6b60e2e0]{display:flex;flex-direction:column;align-items:center;margin-bottom:.625rem}.preview-frame[data-v-6b60e2e0]{width:15rem;height:15rem;border-radius:50%;background-color:#fff;box-shadow:0 .125rem .375rem rgba(0,0,0,.1);display:flex;justify-content:center;align-items:center;overflow:hidden;position:relative}.preview-image[data-v-6b60e2e0]{width:100%;height:100%}.empty-preview[data-v-6b60e2e0]{display:flex;flex-direction:column;align-items:center;color:#ccc}.empty-preview uni-text[data-v-6b60e2e0]{margin-top:.625rem;font-size:.875rem}.set-btn[data-v-6b60e2e0]{margin-top:.625rem;background-color:#3cbb19;color:#fff;width:35%;padding:.46875rem 0;border-radius:.25rem;font-size:.875rem}.carousel-section[data-v-6b60e2e0]{margin-bottom:.9375rem}.carousel-container[data-v-6b60e2e0]{background-color:#fff;border-radius:.5rem;padding:.625rem 0;box-shadow:0 .0625rem .25rem rgba(0,0,0,.05);overflow:hidden}.card-swiper[data-v-6b60e2e0]{width:100%;height:7.5rem}.card-swiper .swiper-item[data-v-6b60e2e0]{display:flex;justify-content:center;align-items:center;transition:all .3s ease}.card-item[data-v-6b60e2e0]{width:7.5rem;height:7.5rem}.card-frame[data-v-6b60e2e0]{width:7.5rem;height:100%;border-radius:50%;overflow:hidden;box-shadow:0 .1875rem .5rem rgba(0,0,0,.15);position:relative}.card-image[data-v-6b60e2e0]{width:7.5rem;height:100%}.card-overlay[data-v-6b60e2e0]{position:absolute;top:0;left:0;width:7.5rem;height:100%;background-color:rgba(0,0,0,.3);display:flex;justify-content:center;align-items:center}.card-swiper .swiper-item[data-v-6b60e2e0]:not(.swiper-item-active){transform:scale(.8);opacity:.6;z-index:1}.card-swiper .swiper-item-active[data-v-6b60e2e0]{transform:scale(1);z-index:2}.carousel-hint[data-v-6b60e2e0]{height:6.25rem;display:flex;justify-content:center;align-items:center;color:#999;font-size:.8125rem;text-align:center}.data-section[data-v-6b60e2e0]{background-color:#fff;border-radius:.5rem;padding:.625rem .9375rem;box-shadow:0 .0625rem .25rem rgba(0,0,0,.05)}.data-grid[data-v-6b60e2e0]{display:grid;grid-template-columns:1fr 1fr;gap:.625rem;margin-bottom:.9375rem}.data-card[data-v-6b60e2e0]{background-color:#f9f9f9;border-radius:.375rem;padding:.625rem;display:flex;align-items:center;gap:.625rem}.data-icon[data-v-6b60e2e0]{width:1.875rem;height:1.875rem;border-radius:.375rem;display:flex;justify-content:center;align-items:center}.battery-icon[data-v-6b60e2e0]{background-color:#f6ffed}.temp-icon[data-v-6b60e2e0]{background-color:#fff7e6}.humidity-icon[data-v-6b60e2e0]{background-color:#e6f7ff}.status-icon[data-v-6b60e2e0]{background-color:#f0f9ff}.data-info[data-v-6b60e2e0]{flex:1}.data-value[data-v-6b60e2e0]{font-size:1rem;font-weight:700;color:#333}.data-label[data-v-6b60e2e0]{font-size:.75rem;color:#666}.connection-status[data-v-6b60e2e0]{display:flex;justify-content:space-between;align-items:center;padding:.46875rem 0;border-top:.03125rem solid #f0f0f0}.status-text[data-v-6b60e2e0]{flex:1;margin:0 .46875rem;font-size:.875rem;color:#333}.connect-btn[data-v-6b60e2e0]{padding:.375rem .75rem;border-radius:.25rem;font-size:.8125rem;background-color:#007aff;color:#fff}.connect-btn[data-v-6b60e2e0]:disabled{background-color:#ccc}
|
||||
1
unpackage/cache/wgt/__UNI__F18BB63/pages/index/index.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.container[data-v-a57057ce]{padding:.5rem;background-color:#f5f5f5}.title-bar[data-v-a57057ce]{display:flex;justify-content:space-between;align-items:center;padding:.625rem 0;border-bottom:1px solid #eee;margin-bottom:.625rem;margin-top:2.5rem}.title[data-v-a57057ce]{font-size:1.125rem;font-weight:700;color:#333}.scan-btn[data-v-a57057ce]{background-color:#00c900;color:#fff;padding:0 .75rem;border-radius:.25rem;font-size:.875rem;margin-right:5%}.scan-btn[data-v-a57057ce]:disabled{background-color:#ccc}.status-tip[data-v-a57057ce]{text-align:center;padding:1.25rem 0;color:#666;font-size:.875rem}.loading[data-v-a57057ce]{width:.9375rem;height:.9375rem;border:.09375rem solid #007aff;border-top-color:transparent;border-radius:50%;margin:.625rem auto;animation:spin-a57057ce 1s linear infinite}@keyframes spin-a57057ce{to{transform:rotate(360deg)}}.device-list[data-v-a57057ce]{display:flex;flex-direction:column;gap:.5rem}.device-item[data-v-a57057ce]{background-color:#fff;border-radius:.375rem;padding:.75rem;box-shadow:0 .0625rem .25rem rgba(0,0,0,.1);cursor:pointer}.device-name[data-v-a57057ce]{display:flex;justify-content:space-between;margin-bottom:.5rem}.device-name uni-text[data-v-a57057ce]:first-child{font-size:1rem;color:#333}.is_bj[data-v-a57057ce]{padding:3px 8px;border-radius:5px;color:#fff;background-color:rgba(30,228,156,.4);position:relative;right:30px}.device-id[data-v-a57057ce]{font-size:.75rem;color:#999}.device-rssi[data-v-a57057ce]{display:flex;flex-direction:column;gap:.25rem}.device-rssi uni-text[data-v-a57057ce]{font-size:.8125rem;color:#666}.rssi-bar[data-v-a57057ce]{height:.25rem;background-color:#eee;border-radius:.125rem;overflow:hidden}.rssi-bar[data-v-a57057ce]:after{content:"";display:block;height:100%;background:linear-gradient(to right,#ff4d4f,#faad14,#52c41a)}.device-status[data-v-a57057ce]{margin-top:.5rem;text-align:right}.connected[data-v-a57057ce]{font-size:.8125rem;color:#07c160;background-color:#f0fff4;padding:.125rem .5rem;border-radius:.375rem}
|
||||
BIN
unpackage/cache/wgt/__UNI__F18BB63/static/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
7
unpackage/cache/wgt/__UNI__F18BB63/uni-app-view.umd.js
vendored
Normal file
7
unpackage/dist/build/.app-harmony/app-config.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
const __uniConfig = {"pages":[],"globalStyle":{"navigationBarTextStyle":"black","navigationBarTitleText":"","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom"},"appname":"电子吧唧_old","compilerVersion":"4.75","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","themeConfig":{}};
|
||||
__uniConfig.getTabBarConfig = () => {return undefined};
|
||||
__uniConfig.tabBar = __uniConfig.getTabBarConfig();
|
||||
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"navigationBarTitleText":"连接设备","navigationStyle":"custom"}},{"path":"pages/connect/connect","meta":{}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute)).concat(typeof __uniSystemRoutes !== 'undefined' ? __uniSystemRoutes : []);
|
||||
|
||||
globalThis.__uniConfig = __uniConfig;
|
||||
globalThis.__uniRoutes = __uniRoutes;
|
||||
694
unpackage/dist/build/.app-harmony/app-service.js
vendored
Normal file
1
unpackage/dist/build/.app-harmony/import/app-config.ets
vendored
Normal file
@ -0,0 +1 @@
|
||||
import '../app-config'
|
||||
1
unpackage/dist/build/.app-harmony/import/app-service.ets
vendored
Normal file
@ -0,0 +1 @@
|
||||
import '../app-service'
|
||||
13
unpackage/dist/build/.app-harmony/manifest.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "__UNI__08167A6",
|
||||
"name": "电子吧唧_old",
|
||||
"description": "",
|
||||
"version": {
|
||||
"name": "1.0.0",
|
||||
"code": "100"
|
||||
},
|
||||
"uni-app-x": {
|
||||
"compilerVersion": "4.75"
|
||||
},
|
||||
"app-harmony": {}
|
||||
}
|
||||
BIN
unpackage/dist/build/.app-harmony/static/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
3
unpackage/dist/build/.app-harmony/uni_modules/build-profile.json5
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"modules": []
|
||||
}
|
||||
12
unpackage/dist/build/.app-harmony/uni_modules/index.generated.ets
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// This file is automatically generated by uni-app.
|
||||
// Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
import { uni } from '@dcloudio/uni-app-x-runtime'
|
||||
|
||||
export function initUniModules() {
|
||||
initUniExtApi()
|
||||
|
||||
}
|
||||
|
||||
function initUniExtApi() {
|
||||
|
||||
}
|
||||
3
unpackage/dist/build/.app-harmony/uni_modules/oh-package.json5
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"dependencies": {}
|
||||
}
|
||||
11
unpackage/dist/build/.nvue/app.css.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var require_app_css = __commonJS({
|
||||
"app.css.js"(exports) {
|
||||
const _style_0 = {};
|
||||
exports.styles = [_style_0];
|
||||
}
|
||||
});
|
||||
export default require_app_css();
|
||||
1
unpackage/dist/build/.nvue/app.css.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.css.js","sources":["uni-app:///D:/HBuilderX/plugins/uniapp-cli-vite/app.css.js"],"sourcesContent":null,"names":[],"mappings":";;;;;;;AAGA,YAAQ,SAAS,CAAC,QAAQ;AAAA;AAAA;"}
|
||||
2
unpackage/dist/build/.nvue/app.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
Promise.resolve("./app.css.js").then(() => {
|
||||
});
|
||||
1
unpackage/dist/build/.nvue/app.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.js","sources":[],"sourcesContent":null,"names":[],"mappings":";;"}
|
||||
1
unpackage/dist/build/.sourcemap/app-android/index.kt.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["App.uvue","main.uts"],"sourcesContent":["<script lang=\"uts\">\r\n\r\n\tlet firstBackTime = 0\r\n\r\n\texport default {\r\n\t\tonLaunch: function () {\r\n\t\t\tconsole.log('App Launch')\r\n\t\t},\r\n\t\tonShow: function () {\r\n\t\t\tconsole.log('App Show')\r\n\t\t},\r\n\t\tonHide: function () {\r\n\t\t\tconsole.log('App Hide')\r\n\t\t},\r\n\r\n\t\tonLastPageBackPress: function () {\r\n\t\t\tconsole.log('App LastPageBackPress')\r\n\t\t\tif (firstBackTime == 0) {\r\n\t\t\t\tuni.showToast({\r\n\t\t\t\t\ttitle: '再按一次退出应用',\r\n\t\t\t\t\tposition: 'bottom',\r\n\t\t\t\t})\r\n\t\t\t\tfirstBackTime = Date.now()\r\n\t\t\t\tsetTimeout(() => {\r\n\t\t\t\t\tfirstBackTime = 0\r\n\t\t\t\t}, 2000)\r\n\t\t\t} else if (Date.now() - firstBackTime < 2000) {\r\n\t\t\t\tfirstBackTime = Date.now()\r\n\t\t\t\tuni.exit()\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tonExit: function () {\r\n\t\t\tconsole.log('App Exit')\r\n\t\t},\r\n\t}\r\n</script>\r\n\r\n<style>\r\n\t/*每个页面公共css */\r\n\t.uni-row {\r\n\t\tflex-direction: row;\r\n\t}\r\n\r\n\t.uni-column {\r\n\t\tflex-direction: column;\r\n\t}\r\n</style>","import App from './App.uvue'\r\n\r\nimport { createSSRApp } from 'vue'\r\nexport function createApp() {\r\n\tconst app = createSSRApp(App)\r\n\treturn {\r\n\t\tapp\r\n\t}\r\n}\nexport function main(app: IApp) {\n definePageRoutes();\n defineAppConfig();\n (createApp()['app'] as VueApp).mount(app, GenUniApp());\n}\n\nexport class UniAppConfig extends io.dcloud.uniapp.appframe.AppConfig {\n override name: string = \"电子吧唧_old\"\n override appid: string = \"__UNI__08167A6\"\n override versionName: string = \"1.0.0\"\n override versionCode: string = \"100\"\n override uniCompilerVersion: string = \"4.75\"\n \n constructor() { super() }\n}\n\nimport GenPagesIndexIndexClass from './pages/index/index.uvue'\nimport GenPagesConnectConnectClass from './pages/connect/connect.uvue'\nfunction definePageRoutes() {\n__uniRoutes.push({ path: \"pages/index/index\", component: GenPagesIndexIndexClass, meta: { isQuit: true } as UniPageMeta, style: _uM([[\"navigationBarTitleText\",\"连接设备\"],[\"navigationStyle\",\"custom\"]]) } as UniPageRoute)\n__uniRoutes.push({ path: \"pages/connect/connect\", component: GenPagesConnectConnectClass, meta: { isQuit: false } as UniPageMeta, style: _uM() } as UniPageRoute)\n}\nconst __uniTabBar: Map<string, any | null> | null = null\nconst __uniLaunchPage: Map<string, any | null> = _uM([[\"url\",\"pages/index/index\"],[\"style\",_uM([[\"navigationBarTitleText\",\"连接设备\"],[\"navigationStyle\",\"custom\"]])]])\nfunction defineAppConfig(){\n __uniConfig.entryPagePath = '/pages/index/index'\n __uniConfig.globalStyle = _uM([[\"navigationBarTextStyle\",\"black\"],[\"navigationBarTitleText\",\"\"],[\"navigationBarBackgroundColor\",\"#F8F8F8\"],[\"backgroundColor\",\"#F8F8F8\"],[\"navigationStyle\",\"custom\"]])\n __uniConfig.getTabBarConfig = ():Map<string, any> | null => null\n __uniConfig.tabBar = __uniConfig.getTabBarConfig()\n __uniConfig.conditionUrl = ''\n __uniConfig.uniIdRouter = _uM()\n \n __uniConfig.ready = true\n}\n"],"names":[],"mappings":";;;;;;;;;;;;+BA4BQ;+BAVA;;;;;;AAhBP,IAAI,wBAAgB,CAAA;AAEf;;iBACM,wBAAA;YACT,QAAQ,GAAG,CAAC;QACb;;kBACQ,sBAAA;YACP,QAAQ,GAAG,CAAC;QACb;;kBACQ,MAAA;YACP,QAAQ,GAAG,CAAC;QACb;;4BAEqB,MAAA;YACpB,QAAQ,GAAG,CAAC;YACZ,IAAI,iBAAiB,CAAC,EAAE;gBACvB,+BACC,QAAO,YACP,WAAU;gBAEX,gBAAgB,KAAK,GAAG;gBACxB,WAAW,KAAI;oBACd,gBAAgB,CAAA;gBACjB,GAAG,IAAI;mBACD,IAAI,KAAK,GAAG,KAAK,gBAAgB,IAAI,EAAE;gBAC7C,gBAAgB,KAAK,GAAG;gBACxB;;QAEF;;eAEQ,MAAA;YACP,QAAQ,GAAG,CAAC;QACb;;;;;;;;;;;;;;AACD;;;;;;;;;;;;;;;;;;;;;;AChCK,IAAU,aAAS,cAAA;IACxB,IAAM,MAAM;IACZ,OAAO,IACN,SAAA;AAEF;AACM,IAAU,KAAK,KAAK,IAAI,EAAA;IAC1B;IACA;IACA,CAAC,WAAW,CAAC,MAAM,CAAA,EAAA,CAAI,MAAM,EAAE,KAAK,CAAC,KAAK;AAC9C;AAEM,WAAO,eAAqB,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS;IACjE,aAAS,MAAM,MAAM,GAAG,UAAU;IAClC,aAAS,OAAO,MAAM,GAAG,gBAAgB;IACzC,aAAS,aAAa,MAAM,GAAG,OAAO;IACtC,aAAS,aAAa,MAAM,GAAG,KAAK;IACpC,aAAS,oBAAoB,MAAM,GAAG,MAAM;IAE5C,gBAAgB,KAAK,GAArB,CAAwB;;AAK5B,IAAS,mBAAgB;IACzB,YAAY,IAAI,cAAG,OAAM,qBAAqB,qCAAoC,mBAAQ,SAAQ,IAAI,GAAmB,QAAO,IAAM,4BAAyB,QAAS,qBAAkB;IAC1L,YAAY,IAAI,cAAG,OAAM,yBAAyB,yCAAwC,mBAAQ,SAAQ,KAAK,GAAmB,QAAO;AACzI;AAEA,IAAM,iBAAiB,IAAI,MAAM,EAAE,GAAG,KAAW,IAAM,SAAM,qBAAsB,WAAQ,IAAM,4BAAyB,QAAS,qBAAkB;AACrJ,IAAS,kBAAe;IACtB,YAAY,aAAa,GAAG;IAC5B,YAAY,WAAW,GAAG,IAAM,4BAAyB,SAAU,4BAAyB,IAAK,kCAA+B,WAAY,qBAAkB,WAAY,qBAAkB;IAC5L,YAAY,eAAe,GAAG,OAAG,IAAI,MAAM,EAAE,GAAG;eAAa,IAAI;;IACjE,YAAY,MAAM,GAAG,YAAY,eAAe;IAChD,YAAY,YAAY,GAAG;IAC3B,YAAY,WAAW,GAAG;IAE1B,YAAY,KAAK,GAAG,IAAI;AAC1B;;;;8BA1CA,EAAA;;;;8BAAA,EAAA;;;;uBAAA,EAAA"}
|
||||
1
unpackage/dist/build/.sourcemap/app-android/pages/connect/connect.kt.map
vendored
Normal file
1
unpackage/dist/build/.sourcemap/app-android/pages/index/index.kt.map
vendored
Normal file
1
unpackage/dist/build/.sourcemap/app/app-service.js.map
vendored
Normal file
132
unpackage/dist/build/app-android/.uniappx/android/src/index.kt
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
@file:Suppress("UNCHECKED_CAST", "USELESS_CAST", "INAPPLICABLE_JVM_NAME", "UNUSED_ANONYMOUS_PARAMETER", "NAME_SHADOWING", "UNNECESSARY_NOT_NULL_ASSERTION")
|
||||
package uni.UNI08167A6
|
||||
import io.dcloud.uniapp.*
|
||||
import io.dcloud.uniapp.extapi.*
|
||||
import io.dcloud.uniapp.framework.*
|
||||
import io.dcloud.uniapp.runtime.*
|
||||
import io.dcloud.uniapp.vue.*
|
||||
import io.dcloud.uniapp.vue.shared.*
|
||||
import io.dcloud.uts.*
|
||||
import io.dcloud.uts.Map
|
||||
import io.dcloud.uts.Set
|
||||
import io.dcloud.uts.UTSAndroid
|
||||
import io.dcloud.uniapp.extapi.exit as uni_exit
|
||||
import io.dcloud.uniapp.extapi.showToast as uni_showToast
|
||||
val runBlock1 = run {
|
||||
__uniConfig.getAppStyles = fun(): Map<String, Map<String, Map<String, Any>>> {
|
||||
return GenApp.styles
|
||||
}
|
||||
}
|
||||
var firstBackTime: Number = 0
|
||||
open class GenApp : BaseApp {
|
||||
constructor(__ins: ComponentInternalInstance) : super(__ins) {
|
||||
onLaunch(fun(_: OnLaunchOptions) {
|
||||
console.log("App Launch")
|
||||
}
|
||||
, __ins)
|
||||
onAppShow(fun(_: OnShowOptions) {
|
||||
console.log("App Show")
|
||||
}
|
||||
, __ins)
|
||||
onAppHide(fun() {
|
||||
console.log("App Hide")
|
||||
}
|
||||
, __ins)
|
||||
onLastPageBackPress(fun() {
|
||||
console.log("App LastPageBackPress")
|
||||
if (firstBackTime == 0) {
|
||||
uni_showToast(ShowToastOptions(title = "再按一次退出应用", position = "bottom"))
|
||||
firstBackTime = Date.now()
|
||||
setTimeout(fun(){
|
||||
firstBackTime = 0
|
||||
}, 2000)
|
||||
} else if (Date.now() - firstBackTime < 2000) {
|
||||
firstBackTime = Date.now()
|
||||
uni_exit(null)
|
||||
}
|
||||
}
|
||||
, __ins)
|
||||
onExit(fun() {
|
||||
console.log("App Exit")
|
||||
}
|
||||
, __ins)
|
||||
}
|
||||
companion object {
|
||||
val styles: Map<String, Map<String, Map<String, Any>>> by lazy {
|
||||
_nCS(_uA(
|
||||
styles0
|
||||
))
|
||||
}
|
||||
val styles0: Map<String, Map<String, Map<String, Any>>>
|
||||
get() {
|
||||
return _uM("uni-row" to _pS(_uM("flexDirection" to "row")), "uni-column" to _pS(_uM("flexDirection" to "column")))
|
||||
}
|
||||
}
|
||||
}
|
||||
val GenAppClass = CreateVueAppComponent(GenApp::class.java, fun(): VueComponentOptions {
|
||||
return VueComponentOptions(type = "app", name = "", inheritAttrs = true, inject = Map(), props = Map(), propsNeedCastKeys = _uA(), emits = Map(), components = Map(), styles = GenApp.styles)
|
||||
}
|
||||
, fun(instance): GenApp {
|
||||
return GenApp(instance)
|
||||
}
|
||||
)
|
||||
val GenPagesIndexIndexClass = CreateVueComponent(GenPagesIndexIndex::class.java, fun(): VueComponentOptions {
|
||||
return VueComponentOptions(type = "page", name = "", inheritAttrs = GenPagesIndexIndex.inheritAttrs, inject = GenPagesIndexIndex.inject, props = GenPagesIndexIndex.props, propsNeedCastKeys = GenPagesIndexIndex.propsNeedCastKeys, emits = GenPagesIndexIndex.emits, components = GenPagesIndexIndex.components, styles = GenPagesIndexIndex.styles)
|
||||
}
|
||||
, fun(instance, renderer): GenPagesIndexIndex {
|
||||
return GenPagesIndexIndex(instance, renderer)
|
||||
}
|
||||
)
|
||||
val GenPagesConnectConnectClass = CreateVueComponent(GenPagesConnectConnect::class.java, fun(): VueComponentOptions {
|
||||
return VueComponentOptions(type = "page", name = "", inheritAttrs = GenPagesConnectConnect.inheritAttrs, inject = GenPagesConnectConnect.inject, props = GenPagesConnectConnect.props, propsNeedCastKeys = GenPagesConnectConnect.propsNeedCastKeys, emits = GenPagesConnectConnect.emits, components = GenPagesConnectConnect.components, styles = GenPagesConnectConnect.styles)
|
||||
}
|
||||
, fun(instance, renderer): GenPagesConnectConnect {
|
||||
return GenPagesConnectConnect(instance, renderer)
|
||||
}
|
||||
)
|
||||
fun createApp(): UTSJSONObject {
|
||||
val app = createSSRApp(GenAppClass)
|
||||
return _uO("app" to app)
|
||||
}
|
||||
fun main(app: IApp) {
|
||||
definePageRoutes()
|
||||
defineAppConfig()
|
||||
(createApp()["app"] as VueApp).mount(app, GenUniApp())
|
||||
}
|
||||
open class UniAppConfig : io.dcloud.uniapp.appframe.AppConfig {
|
||||
override var name: String = "电子吧唧_old"
|
||||
override var appid: String = "__UNI__08167A6"
|
||||
override var versionName: String = "1.0.0"
|
||||
override var versionCode: String = "100"
|
||||
override var uniCompilerVersion: String = "4.75"
|
||||
constructor() : super() {}
|
||||
}
|
||||
fun definePageRoutes() {
|
||||
__uniRoutes.push(UniPageRoute(path = "pages/index/index", component = GenPagesIndexIndexClass, meta = UniPageMeta(isQuit = true), style = _uM("navigationBarTitleText" to "连接设备", "navigationStyle" to "custom")))
|
||||
__uniRoutes.push(UniPageRoute(path = "pages/connect/connect", component = GenPagesConnectConnectClass, meta = UniPageMeta(isQuit = false), style = _uM()))
|
||||
}
|
||||
val __uniLaunchPage: Map<String, Any?> = _uM("url" to "pages/index/index", "style" to _uM("navigationBarTitleText" to "连接设备", "navigationStyle" to "custom"))
|
||||
fun defineAppConfig() {
|
||||
__uniConfig.entryPagePath = "/pages/index/index"
|
||||
__uniConfig.globalStyle = _uM("navigationBarTextStyle" to "black", "navigationBarTitleText" to "", "navigationBarBackgroundColor" to "#F8F8F8", "backgroundColor" to "#F8F8F8", "navigationStyle" to "custom")
|
||||
__uniConfig.getTabBarConfig = fun(): Map<String, Any>? {
|
||||
return null
|
||||
}
|
||||
__uniConfig.tabBar = __uniConfig.getTabBarConfig()
|
||||
__uniConfig.conditionUrl = ""
|
||||
__uniConfig.uniIdRouter = _uM()
|
||||
__uniConfig.ready = true
|
||||
}
|
||||
open class GenUniApp : UniAppImpl() {
|
||||
open val vm: GenApp?
|
||||
get() {
|
||||
return getAppVm() as GenApp?
|
||||
}
|
||||
open val `$vm`: GenApp?
|
||||
get() {
|
||||
return getAppVm() as GenApp?
|
||||
}
|
||||
}
|
||||
fun getApp(): GenUniApp {
|
||||
return getUniApp() as GenUniApp
|
||||
}
|
||||
453
unpackage/dist/build/app-android/.uniappx/android/src/pages/connect/connect.kt
vendored
Normal file
258
unpackage/dist/build/app-android/.uniappx/android/src/pages/index/index.kt
vendored
Normal file
@ -0,0 +1,258 @@
|
||||
@file:Suppress("UNCHECKED_CAST", "USELESS_CAST", "INAPPLICABLE_JVM_NAME", "UNUSED_ANONYMOUS_PARAMETER", "NAME_SHADOWING", "UNNECESSARY_NOT_NULL_ASSERTION")
|
||||
package uni.UNI08167A6
|
||||
import io.dcloud.uniapp.*
|
||||
import io.dcloud.uniapp.extapi.*
|
||||
import io.dcloud.uniapp.framework.*
|
||||
import io.dcloud.uniapp.runtime.*
|
||||
import io.dcloud.uniapp.vue.*
|
||||
import io.dcloud.uniapp.vue.shared.*
|
||||
import io.dcloud.uts.*
|
||||
import io.dcloud.uts.Map
|
||||
import io.dcloud.uts.Set
|
||||
import io.dcloud.uts.UTSAndroid
|
||||
import io.dcloud.uniapp.extapi.closeBLEConnection as uni_closeBLEConnection
|
||||
import io.dcloud.uniapp.extapi.closeBluetoothAdapter as uni_closeBluetoothAdapter
|
||||
import io.dcloud.uniapp.extapi.createBLEConnection as uni_createBLEConnection
|
||||
import io.dcloud.uniapp.extapi.hideLoading as uni_hideLoading
|
||||
import io.dcloud.uniapp.extapi.navigateTo as uni_navigateTo
|
||||
import io.dcloud.uniapp.extapi.offBluetoothDeviceFound as uni_offBluetoothDeviceFound
|
||||
import io.dcloud.uniapp.extapi.onBluetoothDeviceFound as uni_onBluetoothDeviceFound
|
||||
import io.dcloud.uniapp.extapi.openBluetoothAdapter as uni_openBluetoothAdapter
|
||||
import io.dcloud.uniapp.extapi.showLoading as uni_showLoading
|
||||
import io.dcloud.uniapp.extapi.showModal as uni_showModal
|
||||
import io.dcloud.uniapp.extapi.showToast as uni_showToast
|
||||
import io.dcloud.uniapp.extapi.startBluetoothDevicesDiscovery as uni_startBluetoothDevicesDiscovery
|
||||
import io.dcloud.uniapp.extapi.stopBluetoothDevicesDiscovery as uni_stopBluetoothDevicesDiscovery
|
||||
open class GenPagesIndexIndex : BasePage {
|
||||
constructor(__ins: ComponentInternalInstance, __renderer: String?) : super(__ins, __renderer) {
|
||||
onLoad(fun(_: OnLoadOptions) {
|
||||
this.initBluetooth()
|
||||
}
|
||||
, __ins)
|
||||
onUnload(fun() {
|
||||
this.stopScan()
|
||||
uni_closeBluetoothAdapter()
|
||||
uni_offBluetoothDeviceFound(this.onDeviceFound)
|
||||
}
|
||||
, __ins)
|
||||
}
|
||||
@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
|
||||
override fun `$render`(): Any? {
|
||||
val _ctx = this
|
||||
val _cache = this.`$`.renderCache
|
||||
return _cE("view", _uM("class" to "container"), _uA(
|
||||
_cE("view", _uM("class" to "title-bar"), _uA(
|
||||
_cE("text", _uM("class" to "title"), "连接设备"),
|
||||
_cE("button", _uM("class" to "scan-btn", "disabled" to _ctx.isScanning, "onClick" to _ctx.toggleScan), _tD(if (_ctx.isScanning) {
|
||||
"停止扫描"
|
||||
} else {
|
||||
"开始扫描"
|
||||
}
|
||||
), 9, _uA(
|
||||
"disabled",
|
||||
"onClick"
|
||||
))
|
||||
)),
|
||||
if (isTrue(_ctx.isScanning)) {
|
||||
_cE("view", _uM("key" to 0, "class" to "status-tip"), _uA(
|
||||
_cE("text", null, "正在扫描设备..."),
|
||||
_cE("view", _uM("class" to "loading"))
|
||||
))
|
||||
} else {
|
||||
if (_ctx.foundDevices.length === 0) {
|
||||
_cE("view", _uM("key" to 1, "class" to "status-tip"), _uA(
|
||||
_cE("text", null, "未发现设备,请点击\"开始扫描\"")
|
||||
))
|
||||
} else {
|
||||
_cC("v-if", true)
|
||||
}
|
||||
}
|
||||
,
|
||||
_cE("view", _uM("class" to "device-list"), _uA(
|
||||
_cE(Fragment, null, RenderHelpers.renderList(_ctx.foundDevices, fun(device, index, __index, _cached): Any {
|
||||
return _cE("view", _uM("class" to "device-item", "key" to device.deviceId, "onClick" to fun(){
|
||||
_ctx.connectDevice(device)
|
||||
}
|
||||
), _uA(
|
||||
_cE("view", _uM("class" to "device-name"), _uA(
|
||||
_cE("text", null, _tD(device.name || "未知设备"), 1),
|
||||
if (isTrue(device.is_bj)) {
|
||||
_cE("view", _uM("key" to 0, "class" to "is_bj"), "吧唧")
|
||||
} else {
|
||||
_cC("v-if", true)
|
||||
}
|
||||
,
|
||||
_cE("text", _uM("class" to "device-id"), _tD(device.deviceId), 1)
|
||||
)),
|
||||
_cE("view", _uM("class" to "device-rssi"), _uA(
|
||||
_cE("text", null, "信号: " + _tD(device.rssi) + " dBm", 1),
|
||||
_cE("view", _uM("class" to "rssi-bar", "style" to _nS(_uM("width" to _ctx.getRssiWidth(device.rssi)))), null, 4)
|
||||
)),
|
||||
if (isTrue(device.connected)) {
|
||||
_cE("view", _uM("key" to 0, "class" to "device-status"), _uA(
|
||||
_cE("text", _uM("class" to "connected"), "已连接")
|
||||
))
|
||||
} else {
|
||||
_cC("v-if", true)
|
||||
}
|
||||
), 8, _uA(
|
||||
"onClick"
|
||||
))
|
||||
}
|
||||
), 128)
|
||||
))
|
||||
))
|
||||
}
|
||||
open var foundDevices: UTSArray<Any?> by `$data`
|
||||
open var isScanning: Boolean by `$data`
|
||||
open var bluetoothEnabled: Boolean by `$data`
|
||||
open var connectedDeviceId: String by `$data`
|
||||
@Suppress("USELESS_CAST")
|
||||
override fun data(): Map<String, Any?> {
|
||||
return _uM("foundDevices" to _uA(), "isScanning" to false, "bluetoothEnabled" to false, "connectedDeviceId" to "")
|
||||
}
|
||||
open var initBluetooth = ::gen_initBluetooth_fn
|
||||
open fun gen_initBluetooth_fn() {
|
||||
uni_openBluetoothAdapter(OpenBluetoothAdapterOptions(success = fun(_){
|
||||
this.bluetoothEnabled = true
|
||||
}
|
||||
, fail = fun(err){
|
||||
this.bluetoothEnabled = false
|
||||
uni_showModal(ShowModalOptions(title = "蓝牙开启失败", content = "请检查设备蓝牙是否开启", showCancel = false))
|
||||
console.error("蓝牙初始化失败:", err)
|
||||
}
|
||||
))
|
||||
}
|
||||
open var toggleScan = ::gen_toggleScan_fn
|
||||
open fun gen_toggleScan_fn() {
|
||||
if (!this.bluetoothEnabled) {
|
||||
this.initBluetooth()
|
||||
return
|
||||
}
|
||||
if (this.isScanning) {
|
||||
this.stopScan()
|
||||
} else {
|
||||
this.startScan()
|
||||
}
|
||||
}
|
||||
open var startScan = ::gen_startScan_fn
|
||||
open fun gen_startScan_fn() {
|
||||
this.isScanning = true
|
||||
this.foundDevices = _uA()
|
||||
uni_startBluetoothDevicesDiscovery(StartBluetoothDevicesDiscoveryOptions(services = _uA(), allowDuplicatesKey = false, success = fun(_){
|
||||
uni_showToast(ShowToastOptions(title = "开始扫描", icon = "none"))
|
||||
uni_onBluetoothDeviceFound(this.onDeviceFound)
|
||||
}
|
||||
, fail = fun(err){
|
||||
this.isScanning = false
|
||||
uni_showToast(ShowToastOptions(title = "扫描失败", icon = "none"))
|
||||
console.error("扫描失败:", err)
|
||||
}
|
||||
))
|
||||
setTimeout(fun(){
|
||||
if (this.isScanning) {
|
||||
this.stopScan()
|
||||
}
|
||||
}
|
||||
, 5000)
|
||||
}
|
||||
open var stopScan = ::gen_stopScan_fn
|
||||
open fun gen_stopScan_fn() {
|
||||
if (!this.isScanning) {
|
||||
return
|
||||
}
|
||||
uni_stopBluetoothDevicesDiscovery(StopBluetoothDevicesDiscoveryOptions(success = fun(_){
|
||||
this.isScanning = false
|
||||
if (this.foundDevices.length == 0) {
|
||||
uni_showToast(ShowToastOptions(title = "\u6682\u672A\u626B\u63CF\u5230\u4EFB\u4F55\u8BBE\u5907", icon = "none"))
|
||||
return
|
||||
}
|
||||
uni_showToast(ShowToastOptions(title = "\u626B\u63CF\u5B8C\u6210\uFF0C\u53D1\u73B0" + this.foundDevices.length + "\u53F0\u8BBE\u5907", icon = "none"))
|
||||
}
|
||||
, fail = fun(err){
|
||||
console.error("停止扫描失败:", err)
|
||||
}
|
||||
))
|
||||
}
|
||||
open var onDeviceFound = ::gen_onDeviceFound_fn
|
||||
open fun gen_onDeviceFound_fn(res) {
|
||||
val devices = res.devices || _uA()
|
||||
devices.forEach(fun(device){
|
||||
if (!device.deviceId) {
|
||||
return
|
||||
}
|
||||
val isExist = this.foundDevices.some(fun(d): Boolean {
|
||||
return d.deviceId === device.deviceId
|
||||
}
|
||||
)
|
||||
if (isExist) {
|
||||
return
|
||||
}
|
||||
var is_bj = false
|
||||
val advData = Uint8Array(device.advertisData)
|
||||
val devicenameData = advData.slice(2, 6)
|
||||
val devicename = String.fromCharCode(*devicenameData.toTypedArray())
|
||||
if (devicename == "dzbj") {
|
||||
is_bj = true
|
||||
}
|
||||
this.foundDevices.push(_uO("is_bj" to is_bj, "name" to (device.name || "未知设备"), "deviceId" to device.deviceId, "rssi" to device.RSSI, "connected" to (device.deviceId === this.connectedDeviceId)))
|
||||
}
|
||||
)
|
||||
}
|
||||
open var getRssiWidth = ::gen_getRssiWidth_fn
|
||||
open fun gen_getRssiWidth_fn(rssi): String {
|
||||
val minRssi: Number = -100
|
||||
val maxRssi: Number = -30
|
||||
var ratio = (rssi - minRssi) / (maxRssi - minRssi)
|
||||
ratio = Math.max(0, Math.min(1, ratio))
|
||||
return "" + ratio * 100 + "%"
|
||||
}
|
||||
open var connectDevice = ::gen_connectDevice_fn
|
||||
open fun gen_connectDevice_fn(device) {
|
||||
var that = this
|
||||
this.stopScan()
|
||||
uni_showLoading(ShowLoadingOptions(title = "连接中..."))
|
||||
uni_createBLEConnection(CreateBLEConnectionOptions(deviceId = device.deviceId, success = fun(res) {
|
||||
that.foundDevices = that.foundDevices.map(fun(d){
|
||||
return UTSJSONObject.assign(UTSJSONObject(), d, object : UTSJSONObject() {
|
||||
var connected = d.deviceId === device.deviceId
|
||||
})
|
||||
}
|
||||
)
|
||||
uni_hideLoading()
|
||||
uni_showToast(ShowToastOptions(title = "\u5DF2\u8FDE\u63A5" + device.name, icon = "none"))
|
||||
uni_navigateTo(NavigateToOptions(url = "../connect/connect?deviceId=" + device.deviceId, fail = fun(err){
|
||||
uni_showToast(ShowToastOptions(title = "\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5", icon = "error"))
|
||||
uni_closeBLEConnection(CloseBLEConnectionOptions(deviceId = device.deviceId, success = fun(_) {
|
||||
console("断开连接成功")
|
||||
}
|
||||
))
|
||||
}
|
||||
))
|
||||
}
|
||||
, fail = fun(_) {
|
||||
uni_hideLoading()
|
||||
uni_showToast(ShowToastOptions(title = "\u8FDE\u63A5\u5931\u8D25", icon = "error"))
|
||||
}
|
||||
))
|
||||
}
|
||||
companion object {
|
||||
val styles: Map<String, Map<String, Map<String, Any>>> by lazy {
|
||||
_nCS(_uA(
|
||||
styles0
|
||||
), _uA(
|
||||
GenApp.styles
|
||||
))
|
||||
}
|
||||
val styles0: Map<String, Map<String, Map<String, Any>>>
|
||||
get() {
|
||||
return _uM("container" to _pS(_uM("paddingTop" to "16rpx", "paddingRight" to "16rpx", "paddingBottom" to "16rpx", "paddingLeft" to "16rpx", "backgroundColor" to "#f5f5f5")), "title-bar" to _pS(_uM("display" to "flex", "justifyContent" to "space-between", "alignItems" to "center", "paddingTop" to "20rpx", "paddingRight" to 0, "paddingBottom" to "20rpx", "paddingLeft" to 0, "borderBottomWidth" to 1, "borderBottomStyle" to "solid", "borderBottomColor" to "#eeeeee", "marginBottom" to "20rpx", "marginTop" to "80rpx")), "title" to _pS(_uM("fontSize" to "36rpx", "fontWeight" to "bold", "color" to "#333333")), "scan-btn" to _pS(_uM("backgroundColor" to "#00c900", "color" to "#FFFFFF", "paddingTop" to "0rpx", "paddingRight" to "24rpx", "paddingBottom" to "0rpx", "paddingLeft" to "24rpx", "borderTopLeftRadius" to "8rpx", "borderTopRightRadius" to "8rpx", "borderBottomRightRadius" to "8rpx", "borderBottomLeftRadius" to "8rpx", "fontSize" to "28rpx", "marginRight" to "5%", "backgroundColor:disabled" to "#cccccc")), "status-tip" to _pS(_uM("textAlign" to "center", "paddingTop" to "40rpx", "paddingRight" to 0, "paddingBottom" to "40rpx", "paddingLeft" to 0, "color" to "#666666", "fontSize" to "28rpx")), "loading" to _pS(_uM("width" to "30rpx", "height" to "30rpx", "borderTopWidth" to "3rpx", "borderRightWidth" to "3rpx", "borderBottomWidth" to "3rpx", "borderLeftWidth" to "3rpx", "borderTopStyle" to "solid", "borderRightStyle" to "solid", "borderBottomStyle" to "solid", "borderLeftStyle" to "solid", "borderTopColor" to "rgba(0,0,0,0)", "borderRightColor" to "#007aff", "borderBottomColor" to "#007aff", "borderLeftColor" to "#007aff", "marginTop" to "20rpx", "marginRight" to "auto", "marginBottom" to "20rpx", "marginLeft" to "auto", "animation" to "spin 1s linear infinite")), "device-list" to _pS(_uM("display" to "flex", "flexDirection" to "column", "gap" to "16rpx")), "device-item" to _pS(_uM("backgroundColor" to "#FFFFFF", "borderTopLeftRadius" to "12rpx", "borderTopRightRadius" to "12rpx", "borderBottomRightRadius" to "12rpx", "borderBottomLeftRadius" to "12rpx", "paddingTop" to "24rpx", "paddingRight" to "24rpx", "paddingBottom" to "24rpx", "paddingLeft" to "24rpx", "boxShadow" to "0 2rpx 8rpx rgba(0,0,0,0.1)", "cursor" to "pointer")), "device-name" to _pS(_uM("display" to "flex", "justifyContent" to "space-between", "marginBottom" to "16rpx")), "is_bj" to _pS(_uM("paddingTop" to 3, "paddingRight" to 8, "paddingBottom" to 3, "paddingLeft" to 8, "borderTopLeftRadius" to 5, "borderTopRightRadius" to 5, "borderBottomRightRadius" to 5, "borderBottomLeftRadius" to 5, "color" to "#FFFFFF", "backgroundColor" to "rgba(30,228,156,0.4)", "position" to "relative", "right" to 30)), "device-id" to _pS(_uM("fontSize" to "24rpx", "color" to "#999999")), "device-rssi" to _pS(_uM("display" to "flex", "flexDirection" to "column", "gap" to "8rpx")), "rssi-bar" to _pS(_uM("height" to "8rpx", "backgroundColor" to "#eeeeee", "borderTopLeftRadius" to "4rpx", "borderTopRightRadius" to "4rpx", "borderBottomRightRadius" to "4rpx", "borderBottomLeftRadius" to "4rpx", "overflow" to "hidden", "content::after" to "''", "height::after" to "100%", "backgroundImage::after" to "linear-gradient(to right, #ff4d4f, #faad14, #52c41a)", "backgroundColor::after" to "rgba(0,0,0,0)")), "device-status" to _pS(_uM("marginTop" to "16rpx", "textAlign" to "right")), "connected" to _pS(_uM("fontSize" to "26rpx", "color" to "#07c160", "backgroundColor" to "#f0fff4", "paddingTop" to "4rpx", "paddingRight" to "16rpx", "paddingBottom" to "4rpx", "paddingLeft" to "16rpx", "borderTopLeftRadius" to "12rpx", "borderTopRightRadius" to "12rpx", "borderBottomRightRadius" to "12rpx", "borderBottomLeftRadius" to "12rpx")), "@FONT-FACE" to _uM("0" to _uM()))
|
||||
}
|
||||
var inheritAttrs = true
|
||||
var inject: Map<String, Map<String, Any?>> = _uM()
|
||||
var emits: Map<String, Any?> = _uM()
|
||||
var props = _nP(_uM())
|
||||
var propsNeedCastKeys: UTSArray<String> = _uA()
|
||||
var components: Map<String, CreateVueComponent> = _uM()
|
||||
}
|
||||
}
|
||||
32
unpackage/dist/build/app-android/manifest.json
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"id": "__UNI__08167A6",
|
||||
"name": "电子吧唧_old",
|
||||
"description": "",
|
||||
"version": {
|
||||
"name": "1.0.0",
|
||||
"code": "100"
|
||||
},
|
||||
"uni-app-x": {
|
||||
"compilerVersion": "4.75"
|
||||
},
|
||||
"app-android": {
|
||||
"distribute": {
|
||||
"modules": {
|
||||
"uni-exit": {},
|
||||
"uni-prompt": {},
|
||||
"uni-media": {},
|
||||
"uni-storage": {},
|
||||
"uni-fileSystemManager": {}
|
||||
},
|
||||
"icons": {
|
||||
"hdpi": "",
|
||||
"xhdpi": "",
|
||||
"xxhdpi": "",
|
||||
"xxxhdpi": ""
|
||||
},
|
||||
"splashScreens": {
|
||||
"default": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
unpackage/dist/build/app-android/static/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
5
unpackage/dist/build/app-ios/app-config.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
const __uniConfig = {"pages":[],"globalStyle":{"navigationBarTextStyle":"black","navigationBarTitleText":"","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","navigationStyle":"custom"},"appname":"电子吧唧_old","compilerVersion":"4.75","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","themeConfig":{}};
|
||||
__uniConfig.getTabBarConfig = () => {return undefined};
|
||||
__uniConfig.tabBar = __uniConfig.getTabBarConfig();
|
||||
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"navigationBarTitleText":"连接设备","navigationStyle":"custom"}},{"path":"pages/connect/connect","meta":{}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute)).concat(typeof __uniSystemRoutes !== 'undefined' ? __uniSystemRoutes : []);
|
||||
|
||||
675
unpackage/dist/build/app-ios/app-service.js
vendored
Normal file
24
unpackage/dist/build/app-ios/manifest.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": "__UNI__08167A6",
|
||||
"name": "电子吧唧_old",
|
||||
"description": "",
|
||||
"version": {
|
||||
"name": "1.0.0",
|
||||
"code": "100"
|
||||
},
|
||||
"uni-app-x": {
|
||||
"compilerVersion": "4.75"
|
||||
},
|
||||
"app-ios": {
|
||||
"distribute": {
|
||||
"modules": {
|
||||
"uni-prompt": {},
|
||||
"uni-storage": {},
|
||||
"uni-media": {},
|
||||
"uni-fileSystemManager": {}
|
||||
},
|
||||
"icons": {},
|
||||
"splashScreens": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
unpackage/dist/build/app-ios/static/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
16
unpackage/dist/build/app-plus/__uniappautomator.js
vendored
Normal file
32
unpackage/dist/build/app-plus/__uniappchooselocation.js
vendored
Normal file
BIN
unpackage/dist/build/app-plus/__uniapperror.png
vendored
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
32
unpackage/dist/build/app-plus/__uniappopenlocation.js
vendored
Normal file
33
unpackage/dist/build/app-plus/__uniapppicker.js
vendored
Normal file
8
unpackage/dist/build/app-plus/__uniappquill.js
vendored
Normal file
1
unpackage/dist/build/app-plus/__uniappquillimageresize.js
vendored
Normal file
32
unpackage/dist/build/app-plus/__uniappscan.js
vendored
Normal file
BIN
unpackage/dist/build/app-plus/__uniappsuccess.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
24
unpackage/dist/build/app-plus/__uniappview.html
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>View</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<link rel="stylesheet" href="app.css" />
|
||||
<script>var __uniConfig = {"globalStyle":{},"darkmode":false}</script>
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="uni-app-view.umd.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
11
unpackage/dist/build/app-plus/app-config-service.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
;(function(){
|
||||
let u=void 0,isReady=false,onReadyCallbacks=[],isServiceReady=false,onServiceReadyCallbacks=[];
|
||||
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#F8F8F8","navigationBar":{"backgroundColor":"#F8F8F8","titleText":"","style":"custom","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"dzbj","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"4.75","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
|
||||
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"navigationBar":{"titleText":"连接设备","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/connect/connect","meta":{"navigationBar":{"type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
|
||||
__uniConfig.styles=[];//styles
|
||||
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:16})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:u,window:u,document:u,frames:u,self:u,location:u,navigator:u,localStorage:u,history:u,Caches:u,screen:u,alert:u,confirm:u,prompt:u,fetch:u,XMLHttpRequest:u,WebSocket:u,webkit:u,print:u}}}});
|
||||
})();
|
||||
|
||||
1
unpackage/dist/build/app-plus/app-config.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(function(){})();
|
||||
1
unpackage/dist/build/app-plus/app-service.js
vendored
Normal file
3
unpackage/dist/build/app-plus/app.css
vendored
Normal file
1
unpackage/dist/build/app-plus/app.css.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.css.js","sources":["uni-app:///D:/HBuilderX/plugins/uniapp-cli-vite/app.css.js"],"sourcesContent":null,"names":[],"mappings":";;;;;;;AAGA,YAAQ,SAAS,CAAC,QAAQ;AAAA;AAAA;"}
|
||||
1
unpackage/dist/build/app-plus/app.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.js","sources":[],"sourcesContent":null,"names":[],"mappings":";;"}
|
||||
111
unpackage/dist/build/app-plus/manifest.json
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
{
|
||||
"@platforms": [
|
||||
"android",
|
||||
"iPhone",
|
||||
"iPad"
|
||||
],
|
||||
"id": "__UNI__F18BB63",
|
||||
"name": "dzbj",
|
||||
"version": {
|
||||
"name": "1.0.0",
|
||||
"code": "100"
|
||||
},
|
||||
"description": "",
|
||||
"developer": {
|
||||
"name": "",
|
||||
"email": "",
|
||||
"url": ""
|
||||
},
|
||||
"permissions": {
|
||||
"Bluetooth": {},
|
||||
"Camera": {},
|
||||
"UniNView": {
|
||||
"description": "UniNView原生渲染"
|
||||
}
|
||||
},
|
||||
"plus": {
|
||||
"useragent": {
|
||||
"value": "uni-app",
|
||||
"concatenate": true
|
||||
},
|
||||
"splashscreen": {
|
||||
"target": "id:1",
|
||||
"autoclose": true,
|
||||
"waiting": true,
|
||||
"delay": 0
|
||||
},
|
||||
"popGesture": "close",
|
||||
"launchwebview": {
|
||||
"render": "always",
|
||||
"id": "1",
|
||||
"kernel": "WKWebview"
|
||||
},
|
||||
"usingComponents": true,
|
||||
"nvueStyleCompiler": "uni-app",
|
||||
"compilerVersion": 3,
|
||||
"distribute": {
|
||||
"google": {
|
||||
"permissions": [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
"apple": {
|
||||
"dSYMs": false
|
||||
},
|
||||
"plugins": {
|
||||
"audio": {
|
||||
"mp3": {
|
||||
"description": "Android平台录音支持MP3格式文件"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"statusbar": {
|
||||
"immersed": "supportedDevice",
|
||||
"style": "dark",
|
||||
"background": "#F8F8F8"
|
||||
},
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
},
|
||||
"allowsInlineMediaPlayback": true,
|
||||
"uni-app": {
|
||||
"control": "uni-v3",
|
||||
"vueVersion": "3",
|
||||
"compilerVersion": "4.75",
|
||||
"nvueCompiler": "uni-app",
|
||||
"renderer": "auto",
|
||||
"nvue": {
|
||||
"flex-direction": "column"
|
||||
},
|
||||
"nvueLaunchMode": "normal",
|
||||
"webView": {
|
||||
"minUserAgentVersion": "49.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"app-harmony": {
|
||||
"useragent": {
|
||||
"value": "uni-app",
|
||||
"concatenate": true
|
||||
},
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"launch_path": "__uniappview.html"
|
||||
}
|
||||
1
unpackage/dist/build/app-plus/pages/connect/connect.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.status-pot[data-v-6b60e2e0]{width:16px;height:16px;border-radius:50%}.container[data-v-6b60e2e0]{background-color:#f5f5f7;min-height:100vh}.nav-bar[data-v-6b60e2e0]{display:flex;justify-content:space-between;align-items:center;padding:.625rem .9375rem;background-color:#fff}.nav-title[data-v-6b60e2e0]{color:#fff;font-size:1.125rem;font-weight:500}.upload-btn[data-v-6b60e2e0]{align-items:center;gap:.25rem;background-color:#28d50e;color:#fff;width:35%;margin-top:10px;padding:.4375rem 0;border-radius:.25rem;font-size:.8125rem}.content[data-v-6b60e2e0]{padding:.9375rem}.section-title[data-v-6b60e2e0]{display:block;font-size:1rem;color:#333;margin:.9375rem 0 .625rem;font-weight:500}.preview-container[data-v-6b60e2e0]{display:flex;flex-direction:column;align-items:center;margin-bottom:.625rem}.preview-frame[data-v-6b60e2e0]{width:15rem;height:15rem;border-radius:50%;background-color:#fff;box-shadow:0 .125rem .375rem rgba(0,0,0,.1);display:flex;justify-content:center;align-items:center;overflow:hidden;position:relative}.preview-image[data-v-6b60e2e0]{width:100%;height:100%}.empty-preview[data-v-6b60e2e0]{display:flex;flex-direction:column;align-items:center;color:#ccc}.empty-preview uni-text[data-v-6b60e2e0]{margin-top:.625rem;font-size:.875rem}.set-btn[data-v-6b60e2e0]{margin-top:.625rem;background-color:#3cbb19;color:#fff;width:35%;padding:.46875rem 0;border-radius:.25rem;font-size:.875rem}.carousel-section[data-v-6b60e2e0]{margin-bottom:.9375rem}.carousel-container[data-v-6b60e2e0]{background-color:#fff;border-radius:.5rem;padding:.625rem 0;box-shadow:0 .0625rem .25rem rgba(0,0,0,.05);overflow:hidden}.card-swiper[data-v-6b60e2e0]{width:100%;height:7.5rem}.card-swiper .swiper-item[data-v-6b60e2e0]{display:flex;justify-content:center;align-items:center;transition:all .3s ease}.card-item[data-v-6b60e2e0]{width:7.5rem;height:7.5rem}.card-frame[data-v-6b60e2e0]{width:7.5rem;height:100%;border-radius:50%;overflow:hidden;box-shadow:0 .1875rem .5rem rgba(0,0,0,.15);position:relative}.card-image[data-v-6b60e2e0]{width:7.5rem;height:100%}.card-overlay[data-v-6b60e2e0]{position:absolute;top:0;left:0;width:7.5rem;height:100%;background-color:rgba(0,0,0,.3);display:flex;justify-content:center;align-items:center}.card-swiper .swiper-item[data-v-6b60e2e0]:not(.swiper-item-active){transform:scale(.8);opacity:.6;z-index:1}.card-swiper .swiper-item-active[data-v-6b60e2e0]{transform:scale(1);z-index:2}.carousel-hint[data-v-6b60e2e0]{height:6.25rem;display:flex;justify-content:center;align-items:center;color:#999;font-size:.8125rem;text-align:center}.data-section[data-v-6b60e2e0]{background-color:#fff;border-radius:.5rem;padding:.625rem .9375rem;box-shadow:0 .0625rem .25rem rgba(0,0,0,.05)}.data-grid[data-v-6b60e2e0]{display:grid;grid-template-columns:1fr 1fr;gap:.625rem;margin-bottom:.9375rem}.data-card[data-v-6b60e2e0]{background-color:#f9f9f9;border-radius:.375rem;padding:.625rem;display:flex;align-items:center;gap:.625rem}.data-icon[data-v-6b60e2e0]{width:1.875rem;height:1.875rem;border-radius:.375rem;display:flex;justify-content:center;align-items:center}.battery-icon[data-v-6b60e2e0]{background-color:#f6ffed}.temp-icon[data-v-6b60e2e0]{background-color:#fff7e6}.humidity-icon[data-v-6b60e2e0]{background-color:#e6f7ff}.status-icon[data-v-6b60e2e0]{background-color:#f0f9ff}.data-info[data-v-6b60e2e0]{flex:1}.data-value[data-v-6b60e2e0]{font-size:1rem;font-weight:700;color:#333}.data-label[data-v-6b60e2e0]{font-size:.75rem;color:#666}.connection-status[data-v-6b60e2e0]{display:flex;justify-content:space-between;align-items:center;padding:.46875rem 0;border-top:.03125rem solid #f0f0f0}.status-text[data-v-6b60e2e0]{flex:1;margin:0 .46875rem;font-size:.875rem;color:#333}.connect-btn[data-v-6b60e2e0]{padding:.375rem .75rem;border-radius:.25rem;font-size:.8125rem;background-color:#007aff;color:#fff}.connect-btn[data-v-6b60e2e0]:disabled{background-color:#ccc}
|
||||
1
unpackage/dist/build/app-plus/pages/index/index.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.container[data-v-a57057ce]{padding:.5rem;background-color:#f5f5f5}.title-bar[data-v-a57057ce]{display:flex;justify-content:space-between;align-items:center;padding:.625rem 0;border-bottom:1px solid #eee;margin-bottom:.625rem;margin-top:2.5rem}.title[data-v-a57057ce]{font-size:1.125rem;font-weight:700;color:#333}.scan-btn[data-v-a57057ce]{background-color:#00c900;color:#fff;padding:0 .75rem;border-radius:.25rem;font-size:.875rem;margin-right:5%}.scan-btn[data-v-a57057ce]:disabled{background-color:#ccc}.status-tip[data-v-a57057ce]{text-align:center;padding:1.25rem 0;color:#666;font-size:.875rem}.loading[data-v-a57057ce]{width:.9375rem;height:.9375rem;border:.09375rem solid #007aff;border-top-color:transparent;border-radius:50%;margin:.625rem auto;animation:spin-a57057ce 1s linear infinite}@keyframes spin-a57057ce{to{transform:rotate(360deg)}}.device-list[data-v-a57057ce]{display:flex;flex-direction:column;gap:.5rem}.device-item[data-v-a57057ce]{background-color:#fff;border-radius:.375rem;padding:.75rem;box-shadow:0 .0625rem .25rem rgba(0,0,0,.1);cursor:pointer}.device-name[data-v-a57057ce]{display:flex;justify-content:space-between;margin-bottom:.5rem}.device-name uni-text[data-v-a57057ce]:first-child{font-size:1rem;color:#333}.is_bj[data-v-a57057ce]{padding:3px 8px;border-radius:5px;color:#fff;background-color:rgba(30,228,156,.4);position:relative;right:30px}.device-id[data-v-a57057ce]{font-size:.75rem;color:#999}.device-rssi[data-v-a57057ce]{display:flex;flex-direction:column;gap:.25rem}.device-rssi uni-text[data-v-a57057ce]{font-size:.8125rem;color:#666}.rssi-bar[data-v-a57057ce]{height:.25rem;background-color:#eee;border-radius:.125rem;overflow:hidden}.rssi-bar[data-v-a57057ce]:after{content:"";display:block;height:100%;background:linear-gradient(to right,#ff4d4f,#faad14,#52c41a)}.device-status[data-v-a57057ce]{margin-top:.5rem;text-align:right}.connected[data-v-a57057ce]{font-size:.8125rem;color:#07c160;background-color:#f0fff4;padding:.125rem .5rem;border-radius:.375rem}
|
||||
BIN
unpackage/dist/build/app-plus/static/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
7
unpackage/dist/build/app-plus/uni-app-view.umd.js
vendored
Normal file
8
unpackage/dist/cache/.vite/deps/_metadata.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"hash": "82ed7da1",
|
||||
"configHash": "0414020c",
|
||||
"lockfileHash": "c52ceb15",
|
||||
"browserHash": "5470c59f",
|
||||
"optimized": {},
|
||||
"chunks": {}
|
||||
}
|
||||
3
unpackage/dist/cache/.vite/deps/package.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
11
unpackage/dist/dev/.nvue/app.css.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var require_app_css = __commonJS({
|
||||
"app.css.js"(exports) {
|
||||
const _style_0 = {};
|
||||
exports.styles = [_style_0];
|
||||
}
|
||||
});
|
||||
export default require_app_css();
|
||||
2
unpackage/dist/dev/.nvue/app.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
Promise.resolve("./app.css.js").then(() => {
|
||||
});
|
||||
26
unpackage/dist/dev/app-android/manifest.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "",
|
||||
"name": "电子吧唧_old",
|
||||
"description": "",
|
||||
"version": {
|
||||
"name": "1.0.0",
|
||||
"code": "100"
|
||||
},
|
||||
"uni-app-x": {
|
||||
"compilerVersion": "4.75"
|
||||
},
|
||||
"app-android": {
|
||||
"distribute": {
|
||||
"modules": {},
|
||||
"icons": {
|
||||
"hdpi": "",
|
||||
"xhdpi": "",
|
||||
"xxhdpi": "",
|
||||
"xxxhdpi": ""
|
||||
},
|
||||
"splashScreens": {
|
||||
"default": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
unpackage/dist/dev/app-android/static/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
16
unpackage/dist/dev/app-plus/__uniappautomator.js
vendored
Normal file
32
unpackage/dist/dev/app-plus/__uniappchooselocation.js
vendored
Normal file
BIN
unpackage/dist/dev/app-plus/__uniapperror.png
vendored
Normal file
|
After Width: | Height: | Size: 5.7 KiB |