450 lines
12 KiB
Vue
450 lines
12 KiB
Vue
<template>
|
||
<view>
|
||
<view class="days" v-if="currentLockInfo.days">钥匙将在{{ currentLockInfo.days }}天后失效</view>
|
||
<view class="lock-name">{{ currentLockInfo.lockAlias }}</view>
|
||
<view class="top">
|
||
<image class="top-background" src="/static/images/background_main.jpg" mode="aspectFill"></image>
|
||
<view style="width: 100%;height: 50rpx">
|
||
<view class="power" @click="powerTip">
|
||
<image class="power-icon" :src="getPowerIcon(currentLockInfo.electricQuantity)" mode="aspectFill"></image>
|
||
<view class="power-text">{{ currentLockInfo.electricQuantity }}%</view>
|
||
<image class="power-tips" src="/static/images/icon_tips.png" mode="aspectFill"></image>
|
||
</view>
|
||
</view>
|
||
<view class="switch" @click="openDoorOperate('open')" @longpress="openDoorOperate('close')">
|
||
<SwitchLoading :size="220" ref="loading"></SwitchLoading>
|
||
</view>
|
||
<view class="switch-text">点击开锁,长按闭锁</view>
|
||
<view class="bottom">
|
||
<view class="bottom-side">
|
||
<image class="bottom-icon" src="/static/images/icon_role.png" mode="aspectFill"></image>
|
||
<view>{{ getRole(currentLockInfo.userType, currentLockInfo.keyRight) }}</view>
|
||
</view>
|
||
<view class="bottom-side">
|
||
<image class="bottom-icon" :src=" currentLockInfo.lockSetting.appUnlockOnline ?
|
||
'/static/images/icon_cloud_active.png' : '/static/images/icon_cloud.png' "
|
||
mode="aspectFill" style="width: 40rpx;height: 40rpx;"></image>
|
||
<view :style="{color: currentLockInfo.lockSetting.appUnlockOnline ? '#63b8af' : '#a3a3a3'}">手机需联网</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="menu" v-if="currentLockInfo.keyRight === 1">
|
||
<view class="menu-title">
|
||
<image class="menu-image" src="/static/images/icon_menu.png"></image>
|
||
<view>功能</view>
|
||
</view>
|
||
<view class="menu-main">
|
||
<view v-if="currentLockInfo.keyRight === 1"
|
||
class="menu-main-view" @click="routeJump({ name: 'keyList' })">
|
||
<image class="menu-main-image" src="/static/images/tabbar_key_select.png"></image>
|
||
<view>电子钥匙</view>
|
||
</view>
|
||
<view v-if="currentLockInfo.lockFeature.password || currentLockInfo.keyRight === 1"
|
||
class="menu-main-view" @click="routeJump({ name: 'passwordList' })">
|
||
<image class="menu-main-image" src="/static/images/icon_lock_transparent.png"></image>
|
||
<view>密码</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="setting" @click="routeJump({ name: 'setting' })">
|
||
<image class="setting-image" src="/static/images/icon_setting.png"></image>
|
||
<view class="setting-text">设置</view>
|
||
<image class="setting-arrow" mode="aspectFill" src="/static/images/icon_arrow.png"></image>
|
||
</view>
|
||
<up-popup :show="show" @close="closePopup" mode="center" :closeOnClickOverlay="true" bgColor="transparent">
|
||
<view class="popup" @click="closePopup">
|
||
<image class="popup-background" :src="type === 'close' ? '/static/images/background_close_door.png' :
|
||
'/static/images/background_open_door.png'"
|
||
mode="aspectFill"></image>
|
||
<view>
|
||
<view class="popup-name">{{ currentLockInfo.lockAlias }}</view>
|
||
<view class="popup-time">{{ timeFormat('', 'mm/dd h:M') }}</view>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { useBluetoothStore } from '@/stores/bluetooth'
|
||
import { useBasicStore } from '@/stores/basic'
|
||
import { mapState, mapActions } from 'pinia'
|
||
import SwitchLoading from '@/components/SwitchLoading/SwitchLoading.vue'
|
||
import { useLockStore } from '@/stores/lock'
|
||
import { useUserStore } from '@/stores/user'
|
||
import { getLockNetTokenRequest } from '@/api/lock'
|
||
import { timeFormat } from 'uview-plus'
|
||
import { deleteKeyRequest } from '@/api/key'
|
||
|
||
export default {
|
||
data () {
|
||
return {
|
||
time: 0,
|
||
onlineToken: '0',
|
||
pending: false,
|
||
show: false,
|
||
type: ''
|
||
}
|
||
},
|
||
computed: {
|
||
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
|
||
...mapState(useUserStore, ['userInfo']),
|
||
...mapState(useLockStore, ['lockSearch']),
|
||
},
|
||
components: {
|
||
SwitchLoading
|
||
},
|
||
onLoad() {
|
||
this.getServeTime()
|
||
},
|
||
methods: {
|
||
timeFormat,
|
||
...mapActions(useLockStore, ['getRole', 'updateLockSearch', 'getLockList', 'getPowerIcon']),
|
||
...mapActions(useBluetoothStore, ['openDoor', 'updateServerTimestamp', 'closeBluetoothConnection']),
|
||
...mapActions(useBasicStore, ['routeJump', 'backAndToast', 'getNetworkType']),
|
||
closePopup() {
|
||
this.show = false
|
||
},
|
||
powerTip() {
|
||
const that = this
|
||
const time = timeFormat(that.currentLockInfo.electricQuantityDate, 'yyyy-mm-dd h:M')
|
||
console.log('更新时间', that.currentLockInfo.electricQuantityDate, time)
|
||
uni.showModal({
|
||
title: '锁电量更新时间',
|
||
content: time,
|
||
showCancel: false
|
||
})
|
||
},
|
||
async getNetToken(){
|
||
const { code, data, message } = await getLockNetTokenRequest({
|
||
lockId: this.currentLockInfo.lockId
|
||
})
|
||
if(code === 0) {
|
||
this.onlineToken = data.token
|
||
return true
|
||
} else {
|
||
uni.showToast({
|
||
title: message,
|
||
icon: 'none'
|
||
})
|
||
return false
|
||
}
|
||
},
|
||
async getServeTime() {
|
||
const { code, data } = await this.updateServerTimestamp()
|
||
if(code === 0) {
|
||
this.time = parseInt((data.date - new Date().getTime()) / 1000)
|
||
}
|
||
},
|
||
async openDoorOperate(type) {
|
||
if(this.currentLockInfo.faceAuthentication === 1 &&
|
||
((this.currentLockInfo.nextFaceValidateTime <= new Date().getTime() + this.time * 1000) &&
|
||
this.currentLockInfo.nextFaceValidateTime !== 0)) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '开门前需进行实名认证,小程序暂不支持,请使用APP认证开门',
|
||
showCancel: false
|
||
})
|
||
return
|
||
}
|
||
if(this.pending) {
|
||
return
|
||
}
|
||
if(this.currentLockInfo.lockSetting.appUnlockOnline) {
|
||
const netWork = await this.getNetworkType()
|
||
if(!netWork) {
|
||
return
|
||
}
|
||
}
|
||
uni.vibrateLong()
|
||
this.pending = true
|
||
this.$refs.loading.open()
|
||
if(type === 'close') {
|
||
uni.showToast({
|
||
title: `正在尝试闭锁……`,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
if(this.currentLockInfo.lockSetting.appUnlockOnline) {
|
||
const result = await this.getNetToken()
|
||
if(!result) {
|
||
this.$refs.loading.close()
|
||
this.pending = false
|
||
return
|
||
}
|
||
}
|
||
let openMode
|
||
if(type === 'close') {
|
||
openMode = this.currentLockInfo.lockSetting.appUnlockOnline ? 33 : 32
|
||
} else {
|
||
openMode = this.currentLockInfo.lockSetting.appUnlockOnline ? 1 : 0
|
||
}
|
||
const { code } = await this.openDoor({
|
||
name: this.currentLockInfo.name,
|
||
uid: this.userInfo.uid.toString(),
|
||
openMode: openMode,
|
||
openTime: parseInt(new Date().getTime() / 1000) + this.time,
|
||
onlineToken: this.onlineToken
|
||
})
|
||
this.closeBluetoothConnection()
|
||
if(code === 0) {
|
||
this.show = true
|
||
this.type = type
|
||
setTimeout(() => {
|
||
this.show = false
|
||
}, 3000)
|
||
if(this.currentLockInfo.keyType === 3) {
|
||
const { code: deleteKeyCode } = await deleteKeyRequest({
|
||
keyId: this.keyId
|
||
})
|
||
if(deleteKeyCode === 0) {
|
||
this.updateLockSearch({
|
||
...this.lockSearch,
|
||
pageNo: 1
|
||
})
|
||
this.getLockList(this.lockSearch)
|
||
this.backAndToast('单次钥匙已在被使用后删除', 1)
|
||
}
|
||
}
|
||
} else if(code === 13) {
|
||
uni.showToast({
|
||
title: `只能在循环时间内操作门锁`,
|
||
icon: 'none'
|
||
})
|
||
} else if(code === -1) {
|
||
uni.showToast({
|
||
title: `${type === 'close' ? '关' : '开'}锁失败,请保证在锁附近`,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
this.$refs.loading.close()
|
||
this.pending = false
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.popup {
|
||
display: flex;
|
||
position: relative;
|
||
width: 400rpx;
|
||
height: 389rpx;
|
||
text-align: center;
|
||
flex-wrap: wrap;
|
||
|
||
.popup-background {
|
||
z-index: -1;
|
||
width: 400rpx;
|
||
height: 389rpx;
|
||
position: absolute;
|
||
}
|
||
|
||
.popup-name {
|
||
margin-left: 30rpx;
|
||
z-index: 9;
|
||
margin-top: 180rpx;
|
||
color: #676b6d;
|
||
width: 340rpx;
|
||
max-height: 80rpx;
|
||
line-height: 40rpx;
|
||
|
||
word-break: break-all;
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 2;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: normal;
|
||
}
|
||
|
||
.popup-time {
|
||
margin-top: 10rpx;
|
||
width: 400rpx;
|
||
}
|
||
}
|
||
|
||
.days {
|
||
line-height: 60rpx;
|
||
background: #faecc9;
|
||
color: #bc9839;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
width: 750rpx;
|
||
height: 60rpx;
|
||
}
|
||
|
||
.lock-name {
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
padding: 32rpx 32rpx 0 32rpx;
|
||
font-weight: bold;
|
||
word-break: break-all;
|
||
}
|
||
|
||
.top {
|
||
margin-top: 32rpx;
|
||
margin-left: 32rpx;
|
||
width: 686rpx;
|
||
height: 464rpx;
|
||
border-radius: 32rpx;
|
||
position: relative;
|
||
|
||
.top-background {
|
||
z-index: -1;
|
||
position: absolute;
|
||
width: 686rpx;
|
||
height: 464rpx;
|
||
border-radius: 32rpx;
|
||
}
|
||
|
||
.switch {
|
||
margin-top: 20rpx;
|
||
margin-left: 218rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 250rpx;
|
||
height: 250rpx;
|
||
background: #FFFFFF;
|
||
border-radius: 50%;
|
||
box-shadow: 0 8rpx 36rpx 0 rgba(0,0,0,0.12);
|
||
}
|
||
|
||
.power {
|
||
float: right;
|
||
padding-top: 18rpx;
|
||
//width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
height: 50rpx;
|
||
justify-content: flex-end;
|
||
|
||
.power-icon {
|
||
width: 50rpx;
|
||
margin-right: 10rpx;
|
||
height: 30rpx;
|
||
}
|
||
|
||
.power-text {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
margin-right: 10rpx;
|
||
line-height: 50rpx;
|
||
}
|
||
|
||
.power-tips {
|
||
margin-right: 32rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
}
|
||
|
||
.switch-text {
|
||
margin-top: 10rpx;
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.bottom {
|
||
width: 686rpx;
|
||
position: absolute;
|
||
bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
background-color: rgba(0, 0, 0, 0.1);
|
||
height: 48rpx;
|
||
line-height: 48rpx;
|
||
font-size: 32rpx;
|
||
color: #63b8af;
|
||
border-radius: 0 0 32rpx 32rpx;
|
||
justify-content: space-around;
|
||
|
||
.bottom-side {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.bottom-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
|
||
.menu {
|
||
margin-top: 32rpx;
|
||
margin-left: 32rpx;
|
||
padding-bottom: 32rpx;
|
||
width: 686rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 32rpx;
|
||
box-shadow: 0 8rpx 36rpx 0 rgba(0,0,0,0.12);
|
||
font-size: 40rpx;
|
||
|
||
.menu-title {
|
||
padding: 24rpx 32rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.menu-image {
|
||
margin-right: 40rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
|
||
.menu-main {
|
||
padding-top: 32rpx;
|
||
padding-bottom: 32rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 32rpx;
|
||
flex-wrap: wrap;
|
||
text-align: center;
|
||
margin-left: 43rpx;
|
||
|
||
.menu-main-view {
|
||
width: 150rpx;
|
||
|
||
.menu-main-image {
|
||
filter: sepia(100%) saturate(10000%) hue-rotate(180deg) brightness(0.1);
|
||
margin-bottom: 10rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.setting {
|
||
padding: 24rpx 0;
|
||
margin-top: 32rpx;
|
||
margin-left: 32rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
width: 686rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 32rpx;
|
||
box-shadow: 0 8rpx 36rpx 0 rgba(0,0,0,0.12);
|
||
font-size: 40rpx;
|
||
|
||
.setting-text {
|
||
margin-left: 32rpx;
|
||
}
|
||
|
||
.setting-arrow {
|
||
margin-right: 32rpx;
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.setting-image {
|
||
margin-left: 32rpx;
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
}
|
||
</style>
|