wx-starlock/pages/lockDetail/lockDetail.vue

565 lines
16 KiB
Vue
Raw Normal View History

2024-08-22 16:37:15 +08:00
<template>
<view>
<view class="days" v-if="currentLockInfo.days">钥匙将在{{ currentLockInfo.days }}天后失效</view>
2024-09-03 18:07:47 +08:00
<view class="lock-name">{{ currentLockInfo.lockAlias }}</view>
<view class="top">
2025-02-06 11:37:41 +08:00
<image
class="top-background"
src="/static/images/background_main.jpg"
mode="aspectFill"
></image>
<view style="width: 100%; height: 50rpx">
<view class="power" @click="powerTip">
2025-02-06 11:37:41 +08:00
<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>
2024-09-02 17:18:14 +08:00
<view>{{ getRole(currentLockInfo.userType, currentLockInfo.keyRight) }}</view>
</view>
<view class="bottom-side">
2025-02-06 11:37:41 +08:00
<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>
2024-09-02 17:18:14 +08:00
<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">
2025-02-06 11:37:41 +08:00
<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>
2025-02-06 11:37:41 +08:00
<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>
2025-02-09 14:38:52 +08:00
<view
v-if="currentLockInfo.lockFeature.icCard || currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'cardList' })"
>
2025-02-07 16:28:45 +08:00
<image class="menu-main-image" src="/static/images/icon_card.png"></image>
<view></view>
</view>
2025-02-09 14:38:52 +08:00
<view
v-if="currentLockInfo.lockFeature.fingerprint || currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'fingerprintList' })"
>
2025-02-07 16:28:45 +08:00
<image class="menu-main-image" src="/static/images/icon_fingerprint.png"></image>
<view>指纹</view>
</view>
<view
v-if="
currentLockInfo.lockFeature.bluetoothRemoteControl || currentLockInfo.keyRight === 1
"
class="menu-main-view"
@click="routeJump({ name: 'remoteList' })"
>
<image class="menu-main-image" src="/static/images/icon_remote.png"></image>
<view>遥控</view>
</view>
<view
v-if="currentLockInfo.lockFeature.d3Face || currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'faceList' })"
>
<image
class="menu-main-image transform-scale-125"
src="/static/images/icon_face.png"
></image>
<view>人脸</view>
</view>
<view
v-if="currentLockInfo.lockFeature.palmVein || currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'palmVeinList' })"
>
<image class="menu-main-image" src="/static/images/icon_palm_vein.png"></image>
<view>掌静脉</view>
</view>
2025-02-10 14:13:25 +08:00
<view
v-if="currentLockInfo.userType === 110301"
class="menu-main-view"
@click="routeJump({ name: 'adminList' })"
>
2025-02-07 16:28:45 +08:00
<image class="menu-main-image" src="/static/images/icon_admin_black.png"></image>
<view>授权管理员</view>
</view>
2025-02-11 15:45:53 +08:00
<view class="menu-main-view" @click="routeJump({ name: 'recordList' })">
2025-02-07 16:28:45 +08:00
<image class="menu-main-image" src="/static/images/icon_record.png"></image>
<view>操作记录</view>
</view>
</view>
</view>
2024-08-26 20:04:22 +08:00
<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>
2025-02-06 11:37:41 +08:00
<up-popup
:show="show"
@close="closePopup"
mode="center"
:closeOnClickOverlay="true"
bgColor="transparent"
>
2024-09-05 15:46:49 +08:00
<view class="popup" @click="closePopup">
2025-02-06 11:37:41 +08:00
<image
class="popup-background"
:src="
type === 'close'
? '/static/images/background_close_door.png'
: '/static/images/background_open_door.png'
"
mode="aspectFill"
/>
2024-09-05 15:46:49 +08:00
<view>
<view class="popup-name">{{ currentLockInfo.lockAlias }}</view>
<view class="popup-time">{{ timeFormat('', 'mm/dd h:M') }}</view>
</view>
</view>
</up-popup>
2024-08-22 16:37:15 +08:00
</view>
</template>
<script>
2025-02-06 11:37:41 +08:00
import { mapState, mapActions } from 'pinia'
import { timeFormat } from 'uview-plus'
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 { getLockNetTokenRequest } from '@/api/lock'
import { deleteKeyRequest } from '@/api/key'
2025-02-06 11:37:41 +08:00
export default {
2025-02-09 14:38:52 +08:00
components: {
SwitchLoading
},
2025-02-06 11:37:41 +08:00
data() {
return {
time: 0,
onlineToken: '0',
pending: false,
show: false,
type: ''
}
2024-09-05 15:46:49 +08:00
},
2025-02-06 11:37:41 +08:00
computed: {
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
...mapState(useUserStore, ['userInfo']),
...mapState(useLockStore, ['lockSearch'])
},
2025-02-06 11:37:41 +08:00
onLoad() {
this.getServeTime()
},
2025-02-06 11:37:41 +08:00
methods: {
timeFormat,
...mapActions(useLockStore, ['getRole', 'updateLockSearch', 'getLockList', 'getPowerIcon']),
...mapActions(useBluetoothStore, [
'openDoor',
'updateServerTimestamp',
2025-02-11 15:45:53 +08:00
'closeBluetoothConnection',
'syncRecord'
2025-02-06 11:37:41 +08:00
]),
...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)
2024-09-07 18:31:03 +08:00
uni.showModal({
2025-02-06 11:37:41 +08:00
title: '锁电量更新时间',
content: time,
2024-09-07 18:31:03 +08:00
showCancel: false
})
2025-02-06 11:37:41 +08:00
},
async getNetToken() {
const { code, data, message } = await getLockNetTokenRequest({
lockId: this.currentLockInfo.lockId
})
if (code === 0) {
this.onlineToken = data.token
return true
2024-09-05 17:52:53 +08:00
}
2024-09-05 15:46:49 +08:00
uni.showToast({
2025-02-06 11:37:41 +08:00
title: message,
2024-09-05 15:46:49 +08:00
icon: 'none'
})
2025-02-06 11:37:41 +08:00
return false
},
async getServeTime() {
const { code, data } = await this.updateServerTimestamp()
if (code === 0) {
this.time = parseInt((data.date - new Date().getTime()) / 1000, 10)
}
},
async openDoorOperate(type) {
const timestamp = new Date().getTime()
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
}
2025-02-06 11:37:41 +08:00
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,
openTime: parseInt(new Date().getTime() / 1000, 10) + this.time,
onlineToken: this.onlineToken
2024-10-24 15:44:42 +08:00
})
2025-02-11 15:45:53 +08:00
this.syncRecord({
keyId: this.currentLockInfo.toString(),
uid: this.userInfo.uid.toString()
}).then(() => {
this.closeBluetoothConnection()
})
2025-02-06 11:37:41 +08:00
if (type === 'open') {
uni.reportEvent('open_door', {
result: code,
duration: new Date().getTime() - timestamp
})
} else if (type === 'close') {
uni.reportEvent('close_door', {
result: code,
duration: new Date().getTime() - timestamp
2024-09-03 10:54:41 +08:00
})
2025-02-06 11:37:41 +08:00
}
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
2024-09-03 10:54:41 +08:00
})
2025-02-06 11:37:41 +08:00
if (deleteKeyCode === 0) {
this.updateLockSearch({
...this.lockSearch,
pageNo: 1
})
this.getLockList(this.lockSearch)
this.backAndToast('单次钥匙已在被使用后删除', 1)
}
2024-09-03 10:54:41 +08:00
}
2025-02-06 11:37:41 +08:00
} else if (code === 13) {
uni.showToast({
title: `只能在循环时间内操作门锁`,
icon: 'none'
})
} else if (code === -1) {
uni.showToast({
title: `${type === 'close' ? '关' : '开'}锁失败,请保证在锁附近`,
icon: 'none'
})
2024-09-03 10:54:41 +08:00
}
2025-02-06 11:37:41 +08:00
this.$refs.loading.close()
this.pending = false
}
}
2024-08-26 20:04:22 +08:00
}
2024-08-22 16:37:15 +08:00
</script>
<style lang="scss" scoped>
2025-02-06 11:37:41 +08:00
.popup {
display: flex;
position: relative;
2024-09-05 15:46:49 +08:00
width: 400rpx;
height: 389rpx;
2025-02-06 11:37:41 +08:00
text-align: center;
flex-wrap: wrap;
2024-09-05 15:46:49 +08:00
2025-02-06 11:37:41 +08:00
.popup-background {
z-index: -1;
width: 400rpx;
height: 389rpx;
position: absolute;
}
2024-09-05 15:46:49 +08:00
2025-02-06 11:37:41 +08:00
.popup-name {
margin-left: 30rpx;
z-index: 9;
margin-top: 180rpx;
color: #676b6d;
width: 340rpx;
max-height: 80rpx;
line-height: 40rpx;
2024-09-05 15:46:49 +08:00
2025-02-06 11:37:41 +08:00
word-break: break-all;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
}
2024-09-05 15:46:49 +08:00
2025-02-06 11:37:41 +08:00
.popup-time {
margin-top: 10rpx;
width: 400rpx;
}
}
2025-02-06 11:37:41 +08:00
.days {
line-height: 60rpx;
background: #faecc9;
color: #bc9839;
text-align: center;
font-size: 32rpx;
width: 750rpx;
height: 60rpx;
}
2024-09-03 18:07:47 +08:00
2025-02-06 11:37:41 +08:00
.lock-name {
text-align: center;
font-size: 32rpx;
padding: 32rpx 32rpx 0 32rpx;
font-weight: bold;
word-break: break-all;
}
2025-02-06 11:37:41 +08:00
.top {
margin-top: 32rpx;
margin-left: 32rpx;
width: 686rpx;
height: 464rpx;
border-radius: 32rpx;
2025-02-06 11:37:41 +08:00
position: relative;
2025-02-06 11:37:41 +08:00
.top-background {
z-index: -1;
position: absolute;
width: 686rpx;
height: 464rpx;
border-radius: 32rpx;
}
2025-02-06 11:37:41 +08:00
.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);
}
2025-02-06 11:37:41 +08:00
.power {
float: right;
padding-top: 18rpx;
//width: 100%;
display: flex;
align-items: center;
height: 50rpx;
justify-content: flex-end;
2025-02-06 11:37:41 +08:00
.power-icon {
width: 50rpx;
margin-right: 10rpx;
height: 30rpx;
}
2025-02-06 11:37:41 +08:00
.power-text {
font-size: 32rpx;
font-weight: bold;
margin-right: 10rpx;
line-height: 50rpx;
}
2025-02-06 11:37:41 +08:00
.power-tips {
margin-right: 32rpx;
width: 40rpx;
height: 40rpx;
}
}
2025-02-06 11:37:41 +08:00
.switch-text {
margin-top: 10rpx;
text-align: center;
}
}
2025-02-06 11:37:41 +08:00
.bottom {
width: 686rpx;
position: absolute;
bottom: 0;
display: flex;
align-items: center;
2025-02-06 11:37:41 +08:00
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;
2024-08-22 16:37:15 +08:00
2025-02-06 11:37:41 +08:00
.bottom-side {
display: flex;
align-items: center;
}
.bottom-icon {
width: 32rpx;
height: 32rpx;
margin-right: 10rpx;
}
}
2025-02-06 11:37:41 +08:00
.menu {
margin-top: 32rpx;
margin-left: 32rpx;
width: 686rpx;
background-color: #ffffff;
border-radius: 32rpx;
box-shadow: 0 8rpx 36rpx 0 rgba(0, 0, 0, 0.12);
font-size: 40rpx;
2025-02-06 11:37:41 +08:00
.menu-title {
padding: 24rpx 32rpx;
display: flex;
align-items: center;
}
2025-02-06 11:37:41 +08:00
.menu-image {
margin-right: 40rpx;
width: 40rpx;
height: 40rpx;
}
2025-02-06 11:37:41 +08:00
.menu-main {
padding-top: 32rpx;
display: flex;
align-items: center;
2025-02-07 16:28:45 +08:00
font-size: 28rpx;
2025-02-06 11:37:41 +08:00
flex-wrap: wrap;
text-align: center;
margin-left: 43rpx;
2025-02-06 11:37:41 +08:00
.menu-main-view {
width: 150rpx;
2025-02-07 16:28:45 +08:00
margin-bottom: 48rpx;
2025-02-06 11:37:41 +08:00
.menu-main-image {
filter: sepia(100%) saturate(10000%) hue-rotate(180deg) brightness(0.1);
margin-bottom: 10rpx;
width: 40rpx;
height: 40rpx;
}
}
}
}
2025-02-06 11:37:41 +08:00
.setting {
padding: 24rpx 0;
margin-top: 32rpx;
margin-left: 32rpx;
2025-02-06 11:37:41 +08:00
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;
}
}
2024-08-22 16:37:15 +08:00
</style>