1097 lines
30 KiB
Vue
1097 lines
30 KiB
Vue
<template>
|
||
<view>
|
||
<scroll-view
|
||
v-if="deviceInfo"
|
||
scroll-y="true"
|
||
:style="{
|
||
height: deviceInfo.windowHeight - deviceInfo.safeArea.top + 'px'
|
||
}"
|
||
@refresherrefresh="refresher"
|
||
:refresher-enabled="true"
|
||
:refresher-triggered="refresherTriggered"
|
||
>
|
||
<view class="select-lock-row">
|
||
<image
|
||
src="https://cos-lock.skychip.top/mp/icon_add_round.png"
|
||
mode="aspectFill"
|
||
style="width: 48rpx; height: 48rpx"
|
||
@click="toSearchDevice"
|
||
></image>
|
||
<!-- 普通 picker -->
|
||
<picker :range="pickerOptions" @change="onPickerChange">
|
||
<view class="lock-name">
|
||
<text>
|
||
{{ $bluetooth.currentLockInfo.lockAlias }}
|
||
</text>
|
||
<image
|
||
class="icon-down"
|
||
src="https://cos-lock.skychip.top/mp/icon_down.png"
|
||
mode="aspectFill"
|
||
>
|
||
</image>
|
||
</view>
|
||
</picker>
|
||
|
||
<view class="power" @click="powerTip">
|
||
<image
|
||
class="power-icon"
|
||
:src="$lock.getPowerIcon($bluetooth.currentLockInfo.electricQuantity)"
|
||
mode="aspectFill"
|
||
></image>
|
||
<view class="power-text">{{ $bluetooth.currentLockInfo.electricQuantity }}%</view>
|
||
<image
|
||
class="power-tips"
|
||
src="https://cos-lock.skychip.top/mp/icon_tips.png"
|
||
mode="aspectFill"
|
||
>
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<view
|
||
class="open-lock-btn"
|
||
@click="openDoorOperate('open')"
|
||
@longpress="openDoorOperate('close')"
|
||
>
|
||
<image
|
||
class="open-lock-btn-image-1"
|
||
ref="sLoading"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_openLockBtn_center.png"
|
||
></image>
|
||
<image
|
||
class="open-lock-btn-image-2"
|
||
:class="{ rotate: isRotating }"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_openLockBtn_circle.png"
|
||
></image>
|
||
</view>
|
||
|
||
<view class="days" v-if="$bluetooth.currentLockInfo.days"
|
||
>钥匙将在{{ $bluetooth.currentLockInfo.days }}天后失效
|
||
</view>
|
||
|
||
<view class="switch-text">点击开锁,长按闭锁</view>
|
||
<view class="other-text">
|
||
<view class="bottom-side">
|
||
<image
|
||
class="bottom-icon"
|
||
style="width: 32rpx; height: 32rpx"
|
||
src="https://cos-lock.skychip.top/mp/icon_role.png"
|
||
mode="aspectFill"
|
||
></image>
|
||
<view>{{
|
||
$lock.getRole($bluetooth.currentLockInfo.userType, $bluetooth.currentLockInfo.keyRight)
|
||
}}</view>
|
||
</view>
|
||
<view class="bottom-side">
|
||
<image
|
||
class="bottom-icon"
|
||
:src="
|
||
$bluetooth.currentLockInfo.appUnlockOnline
|
||
? 'https://cos-lock.skychip.top/mp/icon_cloud_active.png'
|
||
: 'https://cos-lock.skychip.top/mp/icon_cloud.png'
|
||
"
|
||
mode="aspectFill"
|
||
style="width: 40rpx; height: 40rpx"
|
||
></image>
|
||
<view
|
||
:style="{
|
||
color: $bluetooth.currentLockInfo.appUnlockOnline ? '#4777ee' : '#a3a3a3'
|
||
}"
|
||
>手机需联网</view
|
||
>
|
||
</view>
|
||
</view>
|
||
<view class="menu">
|
||
<view class="menu-main">
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'keyList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_electronicKey.png"
|
||
></image>
|
||
<view>电子钥匙</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.lockFeature.password &&
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'passwordList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_password.png"
|
||
>
|
||
</image>
|
||
<view>密码</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.lockFeature.icCard &&
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'cardList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image transform-scale-110"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_icCard.png"
|
||
></image>
|
||
<view>卡</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.lockFeature.fingerprint &&
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'fingerprintList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_fingerprint.png"
|
||
>
|
||
</image>
|
||
<view>指纹</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.lockFeature.bluetoothRemoteControl &&
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view transform-scale-110"
|
||
@click="$basic.routeJump({ name: 'remoteList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_remoteControl.png"
|
||
></image>
|
||
<view>遥控</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.lockFeature.d3Face &&
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'faceList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_face.png"
|
||
></image>
|
||
<view>人脸</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.lockFeature.palmVein &&
|
||
$bluetooth.currentLockInfo.keyRight === 1 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'palmVeinList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_palm.png"
|
||
></image>
|
||
<view>掌静脉</view>
|
||
</view>
|
||
<view
|
||
v-if="$bluetooth.currentLockInfo.transportType === transportType.TRANSPORT_TENCENT_YUN"
|
||
class="menu-main-view"
|
||
@click="jumpToPlayer"
|
||
>
|
||
<image
|
||
class="menu-main-image transform-scale-140"
|
||
src="https://oss-lock.xhjcn.ltd/mp/icon_catEyes.png"
|
||
></image>
|
||
<view>监控</view>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
$bluetooth.currentLockInfo.userType === 110301 &&
|
||
$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN
|
||
"
|
||
class="menu-main-view"
|
||
@click="$basic.routeJump({ name: 'adminList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image transform-scale-140"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_authorizedAdmin.png"
|
||
></image>
|
||
<view>授权管理员</view>
|
||
</view>
|
||
<view
|
||
v-if="$bluetooth.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN"
|
||
class="menu-main-view transform-scale-105"
|
||
@click="$basic.routeJump({ name: 'recordList' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_operatingRecord.png"
|
||
></image>
|
||
<view>操作记录</view>
|
||
</view>
|
||
<view
|
||
v-if="$bluetooth.currentLockInfo.transportType === transportType.TRANSPORT_TENCENT_YUN"
|
||
class="menu-main-view transform-scale-105"
|
||
@click="$basic.routeJump({ name: 'videoLog' })"
|
||
>
|
||
<image
|
||
class="menu-main-image"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_operatingRecord.png"
|
||
></image>
|
||
<view>门锁记录</view>
|
||
</view>
|
||
<view class="menu-main-view" @click="$basic.routeJump({ name: 'setting' })">
|
||
<image
|
||
class="menu-main-image transform-scale-110"
|
||
src="https://cos-lock.skychip.top/mp/icon_main_set.png"
|
||
></image>
|
||
<view>设置</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<view v-else class="not-devices-box">
|
||
<image class="menu-main-image" src="https://cos-lock.skychip.top/mp/icon_noData.png"></image>
|
||
<text>暂无智能锁</text>
|
||
<image
|
||
src="https://cos-lock.skychip.top/mp/icon_add_round.png"
|
||
mode="aspectFill"
|
||
class="button-add-big"
|
||
@click="toSearchDevice"
|
||
></image>
|
||
</view>
|
||
|
||
<up-popup
|
||
:show="show"
|
||
@close="closePopup"
|
||
mode="center"
|
||
:closeOnClickOverlay="true"
|
||
bgColor="transparent"
|
||
>
|
||
<view class="popup" @click="closePopup">
|
||
<image
|
||
class="popup-background"
|
||
:src="
|
||
typeValue === 'close'
|
||
? 'https://oss-lock.xhjcn.ltd/mp/background_close_door.png'
|
||
: 'https://oss-lock.xhjcn.ltd/mp/background_open_door.png'
|
||
"
|
||
mode="aspectFill"
|
||
/>
|
||
<view>
|
||
<view class="popup-name">{{ $bluetooth.currentLockInfo.lockAlias }}</view>
|
||
<view class="popup-time">{{ timeFormat('', 'mm/dd h:M') }}</view>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { timeFormat } from 'uview-plus'
|
||
import { onMounted, onUnmounted, ref } from 'vue'
|
||
import { useBluetoothStore } from '@/stores/bluetooth'
|
||
import { useBasicStore } from '@/stores/basic'
|
||
import SwitchLoading from '@/components/SwitchLoading/SwitchLoading.vue'
|
||
import { useLockStore } from '@/stores/lock'
|
||
import { useUserStore } from '@/stores/user'
|
||
import { getLockDetailRequest, getLockNetTokenRequest, deleteLockRequest } from '@/api/lock'
|
||
import { deleteKeyRequest } from '@/api/key'
|
||
import { transportType } from '@/constant/transportType'
|
||
import { loginRequest } from '@/api/user'
|
||
import { setStorage, getStorage } from '@/utils/storage'
|
||
import { onLoad, onShow } from '@dcloudio/uni-app' // 注意:这里需要正确导入 UniApp 的生命周期钩子!
|
||
|
||
// #ifdef APP-PLUS
|
||
import { requestPermission } from '@/uni_modules/xhj-record'
|
||
// #endif
|
||
|
||
const $bluetooth = useBluetoothStore()
|
||
const $basic = useBasicStore()
|
||
const $lock = useLockStore()
|
||
const $user = useUserStore()
|
||
|
||
// const sLoading = ref(null)
|
||
|
||
const time = ref(0)
|
||
const onlineToken = ref('0')
|
||
const pending = ref(false)
|
||
const show = ref(false)
|
||
const typeValue = ref('')
|
||
const refresherTriggered = ref(false)
|
||
|
||
const deviceInfo = ref(null)
|
||
|
||
// 控制是否应用旋转动画
|
||
const isRotating = ref(false)
|
||
|
||
// 选择器数据源(比如一个字符串数组)
|
||
const pickerOptions = ref([])
|
||
|
||
// 当前选中项的索引(picker 内部使用)
|
||
const selectedIndex = ref(0)
|
||
|
||
// 选中后展示的文本
|
||
const selectedText = ref(pickerOptions.value[0])
|
||
|
||
onMounted(async () => {
|
||
try {
|
||
// #ifdef MP-WEIXIN
|
||
const accountInfo = uni.getAccountInfoSync()
|
||
getApp().globalData.appid = accountInfo.miniProgram.appId
|
||
getApp().globalData.envVersion = accountInfo.miniProgram.envVersion
|
||
// #endif
|
||
uni.showLoading({
|
||
title: '加载中',
|
||
mask: true
|
||
})
|
||
const token = getStorage('token')
|
||
const list = getStorage('lockList')
|
||
const userInfo = getStorage('userInfo')
|
||
|
||
if (token) {
|
||
await Promise.all([$lock.getLockList($lock.lockSearch), $user.getUserInfo()]).then(res => {
|
||
pending.value = false
|
||
uni.hideLoading()
|
||
if (res[0].code === -1 && res[1] === -1 && list && userInfo) {
|
||
uni.showToast({
|
||
title: '网络访问失败,请检查网络是否正常',
|
||
icon: 'none'
|
||
})
|
||
|
||
$lock.updateLockList(list)
|
||
$user.updateUserInfo(userInfo)
|
||
$user.updateLoginStatus(true)
|
||
}
|
||
})
|
||
} else {
|
||
// 封装 uni.login() 为 Promise
|
||
await new Promise((resolve, reject) => {
|
||
uni.login({
|
||
provider: 'weixin',
|
||
success: async loginRes => {
|
||
try {
|
||
const { code, data } = await loginRequest({
|
||
js_code: loginRes.code
|
||
})
|
||
if (code === 0) {
|
||
await setStorage('openid', data.openid)
|
||
if (data.accessToken) {
|
||
setStorage('token', data.accessToken)
|
||
const list = getStorage('lockList')
|
||
const userInfo = getStorage('userInfo')
|
||
if (!list && !userInfo) {
|
||
await $lock.getLockList($lock.lockSearch)
|
||
await $user.getUserInfo()
|
||
await $user.updateLoginStatus(true)
|
||
}
|
||
} else {
|
||
$user.updateLoginStatus(false)
|
||
}
|
||
resolve() // 登录成功,resolve Promise
|
||
} else {
|
||
throw new Error('登录请求失败')
|
||
}
|
||
} catch (err) {
|
||
console.error('登录过程出错:', err)
|
||
reject(err) // 登录过程出错,reject Promise
|
||
}
|
||
},
|
||
fail: err => {
|
||
console.error('微信登录失败:', err)
|
||
reject(err) // 微信登录失败,reject Promise
|
||
}
|
||
})
|
||
})
|
||
}
|
||
// 取第一个锁的信息作为首页的展示
|
||
const lock = list.flatMap(item => item.lockList)
|
||
console.log('lock', lock)
|
||
if (lock) {
|
||
const defaultShowLockIndex = 0
|
||
const data = {
|
||
...lock[defaultShowLockIndex],
|
||
name: lock[defaultShowLockIndex].bluetooth.bluetoothDeviceName,
|
||
deviceId: lock[defaultShowLockIndex].bluetooth.bluetoothDeviceId,
|
||
commKey: lock[defaultShowLockIndex].bluetooth.privateKey,
|
||
signKey: lock[defaultShowLockIndex].bluetooth.signKey,
|
||
publicKey: lock[defaultShowLockIndex].bluetooth.publicKey
|
||
}
|
||
await $bluetooth.updateKeyId(lock[defaultShowLockIndex].keyId.toString())
|
||
await $bluetooth.updateCurrentLockInfo(data)
|
||
pickerOptions.value = lock.map(item => item.lockAlias)
|
||
}
|
||
|
||
if (Object.keys($bluetooth.currentLockInfo).length !== 0) {
|
||
if (!($bluetooth.bluetoothStatus === 0 || $bluetooth.bluetoothStatus === -1)) {
|
||
$bluetooth.getBluetoothStatus()
|
||
return
|
||
}
|
||
|
||
let result = true
|
||
if (!$bluetooth.isInitBluetooth) {
|
||
result = await $bluetooth.initAndListenBluetooth()
|
||
}
|
||
if (!result) {
|
||
$bluetooth.checkSetting()
|
||
}
|
||
}
|
||
|
||
// 确保登录完成后再执行后续操作
|
||
deviceInfo.value = await $basic.getDeviceInfo()
|
||
await getServeTime()
|
||
} catch (err) {
|
||
console.error('初始化过程出错:', err)
|
||
uni.showToast({
|
||
title: '登录失败,请重试',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
uni.hideLoading() // 无论成功失败,最后都隐藏 loading
|
||
}
|
||
})
|
||
|
||
const jumpToPlayer = async () => {
|
||
// #ifdef APP-PLUS
|
||
// 检查权限
|
||
const result = await requestPermission()
|
||
if (result.code !== 0) {
|
||
uni.showToast({
|
||
title: '请在设置中打开应用的麦克风权限',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
// #endif
|
||
$basic.routeJump({
|
||
name: 'p2pPlayer'
|
||
})
|
||
}
|
||
|
||
const openDoorOperate = async type => {
|
||
if (!($bluetooth.bluetoothStatus === 0 || $bluetooth.bluetoothStatus === -1)) {
|
||
$bluetooth.getBluetoothStatus()
|
||
return
|
||
}
|
||
|
||
let result = true
|
||
if (!$bluetooth.isInitBluetooth) {
|
||
result = await $bluetooth.initAndListenBluetooth()
|
||
}
|
||
if (!result) {
|
||
$bluetooth.checkSetting()
|
||
}
|
||
|
||
isRotating.value = true
|
||
|
||
const timestamp = new Date().getTime()
|
||
if (
|
||
$bluetooth.currentLockInfo.faceAuthentication === 1 &&
|
||
$bluetooth.currentLockInfo.nextFaceValidateTime <= new Date().getTime() + time.value * 1000 &&
|
||
$bluetooth.currentLockInfo.nextFaceValidateTime !== 0
|
||
) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '开门前需进行实名认证,小程序暂不支持,请使用APP认证开门',
|
||
showCancel: false
|
||
})
|
||
isRotating.value = false
|
||
return
|
||
}
|
||
if (pending.value) {
|
||
isRotating.value = false
|
||
return
|
||
}
|
||
if ($bluetooth.currentLockInfo.appUnlockOnline && type !== 'close') {
|
||
const netWork = await $basic.getNetworkType()
|
||
if (!netWork) {
|
||
isRotating.value = false
|
||
return
|
||
}
|
||
}
|
||
uni.vibrateLong()
|
||
pending.value = true
|
||
|
||
if (type === 'close') {
|
||
uni.showToast({
|
||
title: `正在尝试闭锁……`,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
// if ($bluetooth.currentLockInfo.appUnlockOnline && type !== 'close') {
|
||
if ($bluetooth.currentLockInfo.appUnlockOnline) {
|
||
const result = await getNetToken()
|
||
|
||
if (!result) {
|
||
// sLoading.value.close()
|
||
pending.value = false
|
||
isRotating.value = false
|
||
return
|
||
}
|
||
}
|
||
let openMode
|
||
if (type === 'close') {
|
||
openMode = $bluetooth.currentLockInfo.appUnlockOnline ? 33 : 32
|
||
} else {
|
||
openMode = $bluetooth.currentLockInfo.appUnlockOnline ? 1 : 0
|
||
}
|
||
|
||
const { code } = await $bluetooth.openDoor({
|
||
name: $bluetooth.currentLockInfo.name,
|
||
uid: $user.userInfo.uid.toString(),
|
||
openMode,
|
||
openTime: parseInt(new Date().getTime() / 1000, 10) + time.value,
|
||
onlineToken: onlineToken.value
|
||
})
|
||
if (type === 'open') {
|
||
// #ifdef MP-WEIXIN
|
||
uni.reportEvent('open_door', {
|
||
result: code,
|
||
duration: new Date().getTime() - timestamp
|
||
})
|
||
// #endif
|
||
} else if (type === 'close') {
|
||
// #ifdef MP-WEIXIN
|
||
uni.reportEvent('close_door', {
|
||
result: code,
|
||
duration: new Date().getTime() - timestamp
|
||
})
|
||
// #endif
|
||
}
|
||
if (code === 0) {
|
||
await $bluetooth
|
||
.syncRecord({
|
||
keyId: $bluetooth.currentLockInfo.keyId.toString(),
|
||
uid: $user.userInfo.uid.toString()
|
||
})
|
||
.then(() => {
|
||
$bluetooth.closeBluetoothConnection()
|
||
})
|
||
show.value = true
|
||
typeValue.value = type
|
||
setTimeout(() => {
|
||
show.value = false
|
||
}, 3000)
|
||
if ($bluetooth.currentLockInfo.keyType === 3) {
|
||
const { code: deleteKeyCode } = await deleteKeyRequest({
|
||
keyId: $bluetooth.keyId
|
||
})
|
||
if (deleteKeyCode === 0) {
|
||
$lock.updateLockSearch({
|
||
...$lock.lockSearch,
|
||
pageNo: 1
|
||
})
|
||
$lock.getLockList($lock.lockSearch)
|
||
$basic.backAndToast('单次钥匙已在被使用后删除', 1)
|
||
}
|
||
}
|
||
} else if (code === 7) {
|
||
uni.showToast({
|
||
title: `钥匙过期`,
|
||
icon: 'none'
|
||
})
|
||
} else if (code === 13) {
|
||
uni.showToast({
|
||
title: `钥匙当前不可用`,
|
||
icon: 'none'
|
||
})
|
||
} else if (code === -1) {
|
||
uni.showToast({
|
||
title: `${type === 'close' ? '关' : '开'}锁失败,请保证在锁附近`,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
pending.value = false
|
||
isRotating.value = false
|
||
}
|
||
|
||
const closePopup = () => {
|
||
show.value = false
|
||
}
|
||
|
||
const powerTip = () => {
|
||
const time = timeFormat($bluetooth.currentLockInfo.electricQuantityDate, 'yyyy-mm-dd h:M')
|
||
uni.showModal({
|
||
title: '锁电量更新时间',
|
||
content: time,
|
||
showCancel: false
|
||
})
|
||
}
|
||
|
||
const getNetToken = async () => {
|
||
const { code, data, message } = await getLockNetTokenRequest({
|
||
lockId: $bluetooth.currentLockInfo.lockId
|
||
})
|
||
if (code === 0) {
|
||
onlineToken.value = data.token
|
||
return true
|
||
}
|
||
uni.showToast({
|
||
title: message,
|
||
icon: 'none'
|
||
})
|
||
return false
|
||
}
|
||
|
||
const getServeTime = async () => {
|
||
const { code, data } = await $bluetooth.updateServerTimestamp()
|
||
if (code === 0) {
|
||
time.value = parseInt((data.date - new Date().getTime()) / 1000, 10)
|
||
}
|
||
}
|
||
|
||
const refresher = async () => {
|
||
refresherTriggered.value = true
|
||
const { code, data, message } = await getLockDetailRequest({
|
||
lockId: $bluetooth.currentLockInfo.lockId
|
||
})
|
||
if (code === 0) {
|
||
$bluetooth.updateCurrentLockInfo({
|
||
...$bluetooth.currentLockInfo,
|
||
...data
|
||
})
|
||
uni.showToast({
|
||
title: '刷新成功',
|
||
icon: 'none'
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: message,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
refresherTriggered.value = false
|
||
}
|
||
|
||
const toSearchDevice = async () => {
|
||
$basic.routeJump({
|
||
name: 'addLockGuid'
|
||
})
|
||
}
|
||
|
||
const deleteLock = async () => {
|
||
const netWork = await $basic.getNetworkType()
|
||
if (!netWork) {
|
||
return
|
||
}
|
||
|
||
const message = '删除锁后,所有信息都会一起删除,确定删除锁吗?'
|
||
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: message,
|
||
async success(res) {
|
||
if (res.confirm) {
|
||
uni.showLoading({
|
||
title: '删除中'
|
||
})
|
||
const { code: resetDeviceCode } = await $bluetooth.resetDevice({
|
||
name: $bluetooth.currentLockInfo.name,
|
||
authUid: $user.userInfo.uid.toString(),
|
||
keyId: $bluetooth.keyId.toString()
|
||
})
|
||
if (resetDeviceCode === 0 || resetDeviceCode === -2) {
|
||
const { code, message } = await deleteLockRequest({
|
||
lockId: $bluetooth.currentLockInfo.lockId
|
||
})
|
||
if (code === 0) {
|
||
uni.hideLoading()
|
||
$lock.updateLockSearch({
|
||
...$lock.lockSearch,
|
||
pageNo: 1
|
||
})
|
||
$lock.getLockList($lock.lockSearch)
|
||
$basic.backAndToast('删除成功', 1)
|
||
} else {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: message,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} else if (resetDeviceCode === -1) {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '删除失败,请保持在锁附近',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// picker 数据变化时触发
|
||
const onPickerChange = async e => {
|
||
const list = getStorage('lockList')
|
||
// 取第一个锁的信息作为首页的展示
|
||
const lock = list.flatMap(item => item.lockList)
|
||
if (lock) {
|
||
const defaultShowLockIndex = e.detail.value
|
||
const data = {
|
||
...lock[defaultShowLockIndex],
|
||
name: lock[defaultShowLockIndex].bluetooth.bluetoothDeviceName,
|
||
deviceId: lock[defaultShowLockIndex].bluetooth.bluetoothDeviceId,
|
||
commKey: lock[defaultShowLockIndex].bluetooth.privateKey,
|
||
signKey: lock[defaultShowLockIndex].bluetooth.signKey,
|
||
publicKey: lock[defaultShowLockIndex].bluetooth.publicKey
|
||
}
|
||
await $bluetooth.updateKeyId(lock[defaultShowLockIndex].keyId.toString())
|
||
await $bluetooth.updateCurrentLockInfo(data)
|
||
pickerOptions.value = lock.map(item => item.lockAlias)
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.popup {
|
||
position: relative;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
width: 400rpx;
|
||
height: 389rpx;
|
||
text-align: center;
|
||
|
||
.popup-background {
|
||
position: absolute;
|
||
z-index: -1;
|
||
width: 400rpx;
|
||
height: 389rpx;
|
||
}
|
||
|
||
.popup-name {
|
||
z-index: 9;
|
||
display: -webkit-box;
|
||
width: 340rpx;
|
||
max-height: 80rpx;
|
||
margin-top: 180rpx;
|
||
margin-left: 30rpx;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
-webkit-line-clamp: 2;
|
||
line-height: 40rpx;
|
||
color: #676b6d;
|
||
word-break: break-all;
|
||
white-space: normal;
|
||
-webkit-box-orient: vertical;
|
||
}
|
||
|
||
.popup-time {
|
||
width: 400rpx;
|
||
margin-top: 10rpx;
|
||
}
|
||
}
|
||
|
||
.days {
|
||
width: 750rpx;
|
||
height: 60rpx;
|
||
font-size: 32rpx;
|
||
line-height: 60rpx;
|
||
color: #bc9839;
|
||
text-align: center;
|
||
background: #faecc9;
|
||
}
|
||
|
||
.top {
|
||
position: relative;
|
||
width: 686rpx;
|
||
height: 464rpx;
|
||
margin-top: 32rpx;
|
||
margin-left: 32rpx;
|
||
border-radius: 32rpx;
|
||
|
||
.top-background {
|
||
position: absolute;
|
||
z-index: -1;
|
||
width: 686rpx;
|
||
height: 464rpx;
|
||
border-radius: 32rpx;
|
||
}
|
||
|
||
.switch {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 250rpx;
|
||
height: 250rpx;
|
||
margin-top: 20rpx;
|
||
margin-left: 218rpx;
|
||
background: #ffffff;
|
||
border-radius: 50%;
|
||
box-shadow: 0 8rpx 36rpx 0 rgba(0, 0, 0, 0.12);
|
||
}
|
||
|
||
.power {
|
||
float: right;
|
||
//width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
height: 50rpx;
|
||
|
||
.power-icon {
|
||
width: 50rpx;
|
||
height: 30rpx;
|
||
}
|
||
|
||
.power-text {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.power-tips {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.bottom {
|
||
position: absolute;
|
||
bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-around;
|
||
width: 686rpx;
|
||
height: 48rpx;
|
||
font-size: 32rpx;
|
||
line-height: 48rpx;
|
||
color: #4777ee;
|
||
background-color: rgba(0, 0, 0, 0.1);
|
||
border-radius: 0 0 32rpx 32rpx;
|
||
|
||
.bottom-side {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.bottom-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
|
||
.menu {
|
||
width: 686rpx;
|
||
margin-top: 32rpx;
|
||
margin-left: 32rpx;
|
||
font-size: 40rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 32rpx;
|
||
box-shadow: 0 8rpx 36rpx 0 rgba(0, 0, 0, 0.12);
|
||
|
||
.menu-title {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx 32rpx;
|
||
}
|
||
|
||
.menu-image {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-right: 40rpx;
|
||
}
|
||
|
||
.menu-main {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
padding-top: 32rpx;
|
||
margin-left: 43rpx;
|
||
font-size: 28rpx;
|
||
text-align: center;
|
||
|
||
.menu-main-view {
|
||
width: 150rpx;
|
||
margin-bottom: 48rpx;
|
||
|
||
.menu-main-image {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.setting {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 686rpx;
|
||
padding: 24rpx 0;
|
||
margin-top: 32rpx;
|
||
margin-left: 32rpx;
|
||
font-size: 40rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 32rpx;
|
||
box-shadow: 0 8rpx 36rpx 0 rgba(0, 0, 0, 0.12);
|
||
|
||
.setting-text {
|
||
margin-left: 32rpx;
|
||
}
|
||
|
||
.setting-arrow {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-right: 32rpx;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.setting-image {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-left: 32rpx;
|
||
}
|
||
}
|
||
|
||
.not-devices-box {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: gray;
|
||
font-size: 24rpx;
|
||
width: 100%;
|
||
height: 100vh;
|
||
gap: 20rpx;
|
||
position: relative;
|
||
|
||
image {
|
||
width: 320rpx;
|
||
height: 240rpx;
|
||
}
|
||
|
||
.add-new-lock {
|
||
background-color: #4777ee;
|
||
color: white;
|
||
}
|
||
|
||
.button-add-big {
|
||
position: absolute;
|
||
width: 88rpx;
|
||
height: 88rpx;
|
||
right: 55rpx;
|
||
bottom: 55rpx;
|
||
}
|
||
}
|
||
|
||
.select-lock-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
border-radius: 15rpx;
|
||
padding: 8rpx 24rpx;
|
||
|
||
.lock-name {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 18rpx;
|
||
border-radius: 50rpx;
|
||
margin-top: 24rpx;
|
||
margin-bottom: 32rpx;
|
||
font-size: 32rpx;
|
||
background-color: #4777ee;
|
||
color: white;
|
||
padding: 12rpx 32rpx;
|
||
.icon-down {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
}
|
||
|
||
.power {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.power-icon {
|
||
width: 50rpx;
|
||
height: 30rpx;
|
||
}
|
||
|
||
.power-text {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.power-tips {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
}
|
||
}
|
||
.open-lock-btn {
|
||
display: flex;
|
||
justify-content: center;
|
||
position: relative;
|
||
height: 480rpx;
|
||
margin-top: 18rpx;
|
||
margin-bottom: 18rpx;
|
||
.open-lock-btn-image-1 {
|
||
width: 480rpx;
|
||
height: 480rpx;
|
||
position: absolute;
|
||
}
|
||
.open-lock-btn-image-2 {
|
||
width: 480rpx;
|
||
height: 480rpx;
|
||
position: absolute;
|
||
transition: transform 0.6s ease-in-out;
|
||
}
|
||
}
|
||
/* 旋转动画 class */
|
||
.rotate {
|
||
animation: rotate 2s linear infinite; /* 无限旋转动画 */
|
||
}
|
||
@keyframes rotate {
|
||
from {
|
||
transform: rotate(0deg);
|
||
}
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
.switch-text {
|
||
margin-top: 35rpx;
|
||
font-size: 32rpx;
|
||
color: #414141;
|
||
text-align: center;
|
||
}
|
||
.other-text {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 15rpx;
|
||
margin-top: 35rpx;
|
||
|
||
.bottom-side {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 32rpx;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.bottom-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
}
|
||
</style>
|