feat:绑定设备和设备详情
This commit is contained in:
11
src/pages/add-device/add-device.api.ts
Normal file
11
src/pages/add-device/add-device.api.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { request } from '@/api/request'
|
||||
import type { BindDeviceBody } from './add-device.types'
|
||||
|
||||
/** POST /app/device/bind — 绑定设备(设备编号及蓝牙配对信息) */
|
||||
export function bindDevice(data: BindDeviceBody) {
|
||||
return request<void>({
|
||||
url: '/app/device/bind',
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
||||
@@ -51,6 +51,11 @@
|
||||
background: linear-gradient(98deg, #45d685 0%, #21c25e 100%);
|
||||
box-shadow: 0 8rpx 28rpx rgba(33, 194, 94, 0.28);
|
||||
margin-bottom: 28rpx;
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.65;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.add-device-page__btn-text {
|
||||
|
||||
@@ -9,3 +9,60 @@ export interface BindFeatureItem {
|
||||
desc: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
/** POST /app/device/bind 请求体 */
|
||||
export interface BindDeviceBody {
|
||||
deviceNo: string
|
||||
productId?: number
|
||||
model?: string
|
||||
imei?: string
|
||||
mac?: string
|
||||
name?: string
|
||||
homeId?: number
|
||||
locationId?: number
|
||||
}
|
||||
|
||||
/** 绑定流程页间传递的设备信息 */
|
||||
export interface BindDeviceContext {
|
||||
deviceNo: string
|
||||
name: string
|
||||
serialMasked: string
|
||||
productId?: number
|
||||
model?: string
|
||||
imei?: string
|
||||
mac?: string
|
||||
}
|
||||
|
||||
export function buildBindDeviceQuery(ctx: BindDeviceContext): string {
|
||||
const parts = [
|
||||
`deviceNo=${encodeURIComponent(ctx.deviceNo)}`,
|
||||
`name=${encodeURIComponent(ctx.name)}`,
|
||||
`serial=${encodeURIComponent(ctx.serialMasked)}`,
|
||||
]
|
||||
if (ctx.productId != null) parts.push(`productId=${ctx.productId}`)
|
||||
if (ctx.model) parts.push(`model=${encodeURIComponent(ctx.model)}`)
|
||||
if (ctx.imei) parts.push(`imei=${encodeURIComponent(ctx.imei)}`)
|
||||
if (ctx.mac) parts.push(`mac=${encodeURIComponent(ctx.mac)}`)
|
||||
return parts.join('&')
|
||||
}
|
||||
|
||||
function parseQueryNumber(raw: unknown): number | undefined {
|
||||
if (raw === undefined || raw === null || raw === '') return undefined
|
||||
const n = Number(raw)
|
||||
return Number.isFinite(n) ? n : undefined
|
||||
}
|
||||
|
||||
export function readBindDeviceContext(
|
||||
query: Record<string, string | undefined>,
|
||||
): Partial<BindDeviceContext> {
|
||||
const ctx: Partial<BindDeviceContext> = {}
|
||||
if (query.deviceNo) ctx.deviceNo = decodeURIComponent(String(query.deviceNo))
|
||||
if (query.name) ctx.name = decodeURIComponent(String(query.name))
|
||||
if (query.serial) ctx.serialMasked = decodeURIComponent(String(query.serial))
|
||||
const productId = parseQueryNumber(query.productId)
|
||||
if (productId != null) ctx.productId = productId
|
||||
if (query.model) ctx.model = decodeURIComponent(String(query.model))
|
||||
if (query.imei) ctx.imei = decodeURIComponent(String(query.imei))
|
||||
if (query.mac) ctx.mac = decodeURIComponent(String(query.mac))
|
||||
return ctx
|
||||
}
|
||||
|
||||
@@ -210,6 +210,11 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.65;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.complete-page__submit-text {
|
||||
|
||||
@@ -73,8 +73,14 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="complete-page__footer">
|
||||
<view class="complete-page__submit" @tap="onFinishAdd">
|
||||
<text class="complete-page__submit-text">完成添加</text>
|
||||
<view
|
||||
class="complete-page__submit"
|
||||
:class="{ 'complete-page__submit--disabled': loading }"
|
||||
@tap="onFinishAdd"
|
||||
>
|
||||
<text class="complete-page__submit-text">
|
||||
{{ loading ? '提交中...' : '完成添加' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -93,17 +99,14 @@ const {
|
||||
deviceName,
|
||||
serialMasked,
|
||||
roomName,
|
||||
loading,
|
||||
applyQuery,
|
||||
onPickRoom,
|
||||
onFinishAdd,
|
||||
} = useCompleteDevice()
|
||||
|
||||
onLoad((query) => {
|
||||
if (query?.name) {
|
||||
deviceName.value = decodeURIComponent(String(query.name))
|
||||
}
|
||||
if (query?.serial) {
|
||||
serialMasked.value = decodeURIComponent(String(query.serial))
|
||||
}
|
||||
applyQuery(query ?? {})
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,34 +1,85 @@
|
||||
import { ref } from 'vue'
|
||||
import { getErrorMessage } from '@/utils/api-error'
|
||||
import { bindDevice } from '../add-device.api'
|
||||
import { readBindDeviceContext } from '../add-device.types'
|
||||
|
||||
const ROOM_OPTIONS = ['客厅', '主卧', '卧室', '厨房', '卫生间']
|
||||
const ROOM_OPTIONS = [
|
||||
{ name: '客厅', locationId: 1 },
|
||||
{ name: '主卧', locationId: 2 },
|
||||
{ name: '卧室', locationId: 3 },
|
||||
{ name: '厨房', locationId: 4 },
|
||||
{ name: '卫生间', locationId: 5 },
|
||||
] as const
|
||||
|
||||
export function useCompleteDevice() {
|
||||
const currentStep = 4
|
||||
const deviceNo = ref('')
|
||||
const deviceName = ref('Z2 空气净化器')
|
||||
const serialMasked = ref('****A3B2')
|
||||
const roomName = ref('客厅')
|
||||
const roomOptions = ROOM_OPTIONS
|
||||
const productId = ref<number>()
|
||||
const model = ref<string>()
|
||||
const imei = ref<string>()
|
||||
const mac = ref<string>()
|
||||
const roomName = ref(ROOM_OPTIONS[0].name)
|
||||
const locationId = ref<number | undefined>(ROOM_OPTIONS[0].locationId)
|
||||
const loading = ref(false)
|
||||
|
||||
function applyQuery(query: Record<string, string | undefined>) {
|
||||
const ctx = readBindDeviceContext(query)
|
||||
if (ctx.deviceNo) deviceNo.value = ctx.deviceNo
|
||||
if (ctx.name) deviceName.value = ctx.name
|
||||
if (ctx.serialMasked) serialMasked.value = ctx.serialMasked
|
||||
if (ctx.productId != null) productId.value = ctx.productId
|
||||
if (ctx.model) model.value = ctx.model
|
||||
if (ctx.imei) imei.value = ctx.imei
|
||||
if (ctx.mac) mac.value = ctx.mac
|
||||
}
|
||||
|
||||
function onPickRoom() {
|
||||
uni.showActionSheet({
|
||||
itemList: roomOptions,
|
||||
itemList: ROOM_OPTIONS.map((item) => item.name),
|
||||
success: (res) => {
|
||||
const picked = roomOptions[res.tapIndex]
|
||||
if (picked) roomName.value = picked
|
||||
const picked = ROOM_OPTIONS[res.tapIndex]
|
||||
if (picked) {
|
||||
roomName.value = picked.name
|
||||
locationId.value = picked.locationId
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function onFinishAdd() {
|
||||
async function onFinishAdd() {
|
||||
const name = deviceName.value.trim()
|
||||
if (!name) {
|
||||
uni.showToast({ title: '请输入设备名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.showToast({ title: '添加成功', icon: 'success' })
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({ url: '/pages/device/index' })
|
||||
}, 400)
|
||||
if (!deviceNo.value.trim()) {
|
||||
uni.showToast({ title: '缺少设备编号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (loading.value) return
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
await bindDevice({
|
||||
deviceNo: deviceNo.value.trim(),
|
||||
name,
|
||||
...(productId.value != null ? { productId: productId.value } : {}),
|
||||
...(model.value ? { model: model.value } : {}),
|
||||
...(imei.value ? { imei: imei.value } : {}),
|
||||
...(mac.value ? { mac: mac.value } : {}),
|
||||
...(locationId.value != null ? { locationId: locationId.value } : {}),
|
||||
})
|
||||
uni.showToast({ title: '添加成功', icon: 'success' })
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({ url: '/pages/device/index' })
|
||||
}, 400)
|
||||
} catch (err) {
|
||||
uni.showToast({ title: getErrorMessage(err, '绑定失败,请重试'), icon: 'none' })
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -36,6 +87,8 @@ export function useCompleteDevice() {
|
||||
deviceName,
|
||||
serialMasked,
|
||||
roomName,
|
||||
loading,
|
||||
applyQuery,
|
||||
onPickRoom,
|
||||
onFinishAdd,
|
||||
}
|
||||
|
||||
@@ -11,8 +11,14 @@
|
||||
</text>
|
||||
<bind-feature-list :items="BIND_FEATURES" />
|
||||
<view class="add-device-page__footer">
|
||||
<view class="add-device-page__btn" @tap="onOpenBluetooth">
|
||||
<text class="add-device-page__btn-text">去开启蓝牙</text>
|
||||
<view
|
||||
class="add-device-page__btn"
|
||||
:class="{ 'add-device-page__btn--disabled': opening }"
|
||||
@tap="onOpenBluetooth"
|
||||
>
|
||||
<text class="add-device-page__btn-text">
|
||||
{{ opening ? '正在开启...' : '去开启蓝牙' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="add-device-page__later-wrap" @tap="onBindLater">
|
||||
<text class="add-device-page__later">稍后绑定</text>
|
||||
@@ -29,7 +35,7 @@ import BindFeatureList from './components/bind-feature-list/index.vue'
|
||||
import BindSteps from './components/bind-steps/index.vue'
|
||||
import { BIND_FEATURES, BIND_STEPS, useAddDevice } from './use-add-device'
|
||||
|
||||
const { currentStep, onOpenBluetooth, onBindLater } = useAddDevice()
|
||||
const { currentStep, opening, onOpenBluetooth, onBindLater } = useAddDevice()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -45,18 +45,21 @@ import { BIND_STEPS } from '../use-add-device'
|
||||
import PairCheckList from './components/pair-check-list/index.vue'
|
||||
import PairDeviceSummary from './components/pair-device-summary/index.vue'
|
||||
import PairHero from './components/pair-hero/index.vue'
|
||||
import { readBindDeviceContext } from '../add-device.types'
|
||||
import { usePairDevice } from './use-pair-device'
|
||||
|
||||
const { currentStep, device, progress, etaSeconds, checkItems, onCancelPair } =
|
||||
usePairDevice()
|
||||
|
||||
onLoad((query) => {
|
||||
if (query?.name) {
|
||||
device.value.name = decodeURIComponent(String(query.name))
|
||||
}
|
||||
if (query?.serial) {
|
||||
device.value.serialMasked = decodeURIComponent(String(query.serial))
|
||||
}
|
||||
const ctx = readBindDeviceContext(query ?? {})
|
||||
if (ctx.name) device.value.name = ctx.name
|
||||
if (ctx.serialMasked) device.value.serialMasked = ctx.serialMasked
|
||||
if (ctx.deviceNo) device.value.deviceNo = ctx.deviceNo
|
||||
if (ctx.productId != null) device.value.productId = ctx.productId
|
||||
if (ctx.model) device.value.model = ctx.model
|
||||
if (ctx.imei) device.value.imei = ctx.imei
|
||||
if (ctx.mac) device.value.mac = ctx.mac
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -10,4 +10,9 @@ export interface PairCheckItem {
|
||||
export interface PairDeviceInfo {
|
||||
name: string
|
||||
serialMasked: string
|
||||
deviceNo: string
|
||||
productId?: number
|
||||
model?: string
|
||||
imei?: string
|
||||
mac?: string
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { onUnmounted, ref, watch } from 'vue'
|
||||
import { buildBindDeviceQuery } from '../add-device.types'
|
||||
import type { PairCheckItem, PairDeviceInfo } from './pair.types'
|
||||
|
||||
const DEFAULT_DEVICE: PairDeviceInfo = {
|
||||
name: 'Z2 空气净化器',
|
||||
serialMasked: '****A3B2',
|
||||
name: '',
|
||||
serialMasked: '',
|
||||
deviceNo: '',
|
||||
}
|
||||
|
||||
export function usePairDevice(initial?: Partial<PairDeviceInfo>) {
|
||||
@@ -45,10 +47,15 @@ export function usePairDevice(initial?: Partial<PairDeviceInfo>) {
|
||||
if (value < 100 || navigated) return
|
||||
navigated = true
|
||||
const d = device.value
|
||||
const q = [
|
||||
`name=${encodeURIComponent(d.name)}`,
|
||||
`serial=${encodeURIComponent(d.serialMasked)}`,
|
||||
].join('&')
|
||||
const q = buildBindDeviceQuery({
|
||||
deviceNo: d.deviceNo,
|
||||
name: d.name,
|
||||
serialMasked: d.serialMasked,
|
||||
productId: d.productId,
|
||||
model: d.model,
|
||||
imei: d.imei,
|
||||
mac: d.mac,
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({ url: `/pages/add-device/complete/index?${q}` })
|
||||
}, 600)
|
||||
|
||||
@@ -20,7 +20,15 @@
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="scan-page__list">
|
||||
<view v-if="scanError" class="scan-page__empty">
|
||||
<text class="scan-page__empty-text">{{ scanError }}</text>
|
||||
</view>
|
||||
<view v-else-if="devices.length === 0" class="scan-page__empty">
|
||||
<text class="scan-page__empty-text">
|
||||
{{ scanning ? '正在搜索附近蓝牙设备...' : '未发现附近设备,请确认设备已开机并靠近手机' }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-else class="scan-page__list">
|
||||
<scan-device-item
|
||||
v-for="item in devices"
|
||||
:key="item.id"
|
||||
@@ -52,6 +60,7 @@ const {
|
||||
selectedId,
|
||||
secondsLeft,
|
||||
scanning,
|
||||
scanError,
|
||||
onSelectDevice,
|
||||
onDeviceAction,
|
||||
} = useScanDevice()
|
||||
|
||||
@@ -76,3 +76,19 @@
|
||||
.scan-page__list {
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.scan-page__empty {
|
||||
margin: 0 32rpx;
|
||||
padding: 48rpx 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.scan-page__empty-text {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #98a2b3;
|
||||
line-height: 1.65;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@ export interface ScannedDeviceItem {
|
||||
id: string
|
||||
name: string
|
||||
serialMasked: string
|
||||
deviceNo: string
|
||||
productId?: number
|
||||
model?: string
|
||||
imei?: string
|
||||
mac?: string
|
||||
/** 是否可添加(未知设备为 false 时箭头置灰) */
|
||||
canAdd: boolean
|
||||
}
|
||||
|
||||
37
src/pages/add-device/scan/scan.utils.ts
Normal file
37
src/pages/add-device/scan/scan.utils.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import type { ScannedDeviceItem } from './scan.types'
|
||||
|
||||
function normalizeMac(deviceId: string): string | undefined {
|
||||
const macPattern = /^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/
|
||||
if (macPattern.test(deviceId)) return deviceId.toUpperCase()
|
||||
return undefined
|
||||
}
|
||||
|
||||
/** 扫描列表展示用:优先 MAC,否则完整 deviceId */
|
||||
function formatDeviceSerial(deviceId: string): string {
|
||||
return normalizeMac(deviceId) ?? deviceId
|
||||
}
|
||||
|
||||
function buildDeviceNo(deviceId: string): string {
|
||||
const mac = normalizeMac(deviceId)
|
||||
if (mac) return mac.replace(/:/g, '')
|
||||
const compact = deviceId.replace(/[^a-zA-Z0-9]/g, '').toUpperCase()
|
||||
return compact || deviceId
|
||||
}
|
||||
|
||||
function resolveDisplayName(device: UniApp.BluetoothDeviceInfo): string {
|
||||
return (device.name || device.localName || '').trim() || '未命名设备'
|
||||
}
|
||||
|
||||
/** 将蓝牙广播设备映射为扫描列表项(使用真实广播数据) */
|
||||
export function mapBluetoothDevice(device: UniApp.BluetoothDeviceInfo): ScannedDeviceItem {
|
||||
const serial = formatDeviceSerial(device.deviceId)
|
||||
|
||||
return {
|
||||
id: device.deviceId,
|
||||
name: resolveDisplayName(device),
|
||||
serialMasked: serial,
|
||||
deviceNo: buildDeviceNo(device.deviceId),
|
||||
mac: normalizeMac(device.deviceId),
|
||||
canAdd: true,
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,73 @@
|
||||
import { onUnmounted, ref } from 'vue'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import {
|
||||
ensureBluetoothReady,
|
||||
getBluetoothErrorMessage,
|
||||
getDiscoveredBluetoothDevices,
|
||||
isBluetoothApiSupported,
|
||||
startBluetoothDiscovery,
|
||||
stopBluetoothDiscovery,
|
||||
subscribeBluetoothDevicesFound,
|
||||
} from '@/utils/bluetooth'
|
||||
import { buildBindDeviceQuery } from '../add-device.types'
|
||||
import type { ScannedDeviceItem } from './scan.types'
|
||||
|
||||
const MOCK_DEVICES: ScannedDeviceItem[] = [
|
||||
{
|
||||
id: 'z2-purifier',
|
||||
name: 'Z2 空气净化器',
|
||||
serialMasked: '****A3B2',
|
||||
canAdd: true,
|
||||
},
|
||||
{
|
||||
id: 'unknown',
|
||||
name: '未知设备',
|
||||
serialMasked: '****7C91',
|
||||
canAdd: false,
|
||||
},
|
||||
]
|
||||
import { mapBluetoothDevice } from './scan.utils'
|
||||
|
||||
const SCAN_SECONDS = 20
|
||||
|
||||
export function useScanDevice() {
|
||||
const currentStep = 2
|
||||
const devices = ref<ScannedDeviceItem[]>(MOCK_DEVICES)
|
||||
const selectedId = ref(MOCK_DEVICES[0]?.id ?? '')
|
||||
const devices = ref<ScannedDeviceItem[]>([])
|
||||
const selectedId = ref('')
|
||||
const secondsLeft = ref(SCAN_SECONDS)
|
||||
const scanning = ref(true)
|
||||
const scanError = ref('')
|
||||
|
||||
let unsubscribeFound: (() => void) | undefined
|
||||
|
||||
function upsertDevice(item: ScannedDeviceItem) {
|
||||
const idx = devices.value.findIndex((d) => d.id === item.id)
|
||||
if (idx >= 0) {
|
||||
devices.value[idx] = item
|
||||
return
|
||||
}
|
||||
devices.value.push(item)
|
||||
if (!selectedId.value) selectedId.value = item.id
|
||||
}
|
||||
|
||||
function ingestBluetoothDevices(found: UniApp.BluetoothDeviceInfo[]) {
|
||||
for (const device of found) {
|
||||
upsertDevice(mapBluetoothDevice(device))
|
||||
}
|
||||
}
|
||||
|
||||
async function beginDiscovery() {
|
||||
if (!isBluetoothApiSupported()) {
|
||||
scanning.value = false
|
||||
scanError.value = '当前环境不支持蓝牙扫描,请使用 App 或微信小程序'
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await ensureBluetoothReady()
|
||||
|
||||
unsubscribeFound = subscribeBluetoothDevicesFound((found) => {
|
||||
ingestBluetoothDevices(found)
|
||||
})
|
||||
|
||||
const existing = await getDiscoveredBluetoothDevices()
|
||||
ingestBluetoothDevices(existing)
|
||||
|
||||
await startBluetoothDiscovery()
|
||||
} catch (err) {
|
||||
scanning.value = false
|
||||
scanError.value = getBluetoothErrorMessage(err)
|
||||
uni.showToast({ title: scanError.value, icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void beginDiscovery()
|
||||
})
|
||||
|
||||
const timer = setInterval(() => {
|
||||
if (secondsLeft.value <= 0) {
|
||||
@@ -33,11 +77,14 @@ export function useScanDevice() {
|
||||
secondsLeft.value -= 1
|
||||
if (secondsLeft.value === 0) {
|
||||
scanning.value = false
|
||||
void stopBluetoothDiscovery().catch(() => {})
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer)
|
||||
unsubscribeFound?.()
|
||||
void stopBluetoothDiscovery().catch(() => {})
|
||||
})
|
||||
|
||||
function onSelectDevice(id: string) {
|
||||
@@ -50,10 +97,15 @@ export function useScanDevice() {
|
||||
uni.showToast({ title: '暂无法添加该设备', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const q = [
|
||||
`name=${encodeURIComponent(device.name)}`,
|
||||
`serial=${encodeURIComponent(device.serialMasked)}`,
|
||||
].join('&')
|
||||
const q = buildBindDeviceQuery({
|
||||
deviceNo: device.deviceNo,
|
||||
name: device.name,
|
||||
serialMasked: device.serialMasked,
|
||||
productId: device.productId,
|
||||
model: device.model,
|
||||
imei: device.imei,
|
||||
mac: device.mac,
|
||||
})
|
||||
uni.navigateTo({ url: `/pages/add-device/pair/index?${q}` })
|
||||
}
|
||||
|
||||
@@ -63,6 +115,7 @@ export function useScanDevice() {
|
||||
selectedId,
|
||||
secondsLeft,
|
||||
scanning,
|
||||
scanError,
|
||||
onSelectDevice,
|
||||
onDeviceAction,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ref } from 'vue'
|
||||
import { ensureBluetoothReady, getBluetoothErrorMessage } from '@/utils/bluetooth'
|
||||
import { staticAssets } from '@/utils/static-assets'
|
||||
import type { BindFeatureItem, BindStepItem } from './add-device.types'
|
||||
|
||||
@@ -31,9 +33,24 @@ export const BIND_FEATURES: BindFeatureItem[] = [
|
||||
|
||||
export function useAddDevice() {
|
||||
const currentStep = 1
|
||||
const opening = ref(false)
|
||||
|
||||
function onOpenBluetooth() {
|
||||
uni.navigateTo({ url: '/pages/add-device/scan/index' })
|
||||
async function onOpenBluetooth() {
|
||||
if (opening.value) return
|
||||
opening.value = true
|
||||
try {
|
||||
await ensureBluetoothReady()
|
||||
uni.navigateTo({ url: '/pages/add-device/scan/index' })
|
||||
} catch (err) {
|
||||
uni.showModal({
|
||||
title: '无法开启蓝牙',
|
||||
content: getBluetoothErrorMessage(err),
|
||||
showCancel: false,
|
||||
confirmText: '知道了',
|
||||
})
|
||||
} finally {
|
||||
opening.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function onBindLater() {
|
||||
@@ -42,6 +59,7 @@ export function useAddDevice() {
|
||||
|
||||
return {
|
||||
currentStep,
|
||||
opening,
|
||||
onOpenBluetooth,
|
||||
onBindLater,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user