范鹏 367001f127 1. 修复名称过长显示bug
2. 添加首页列表远程开锁显示
3. 添加密码钥匙空列表判断
2024-09-04 11:02:08 +08:00

440 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<view v-if="!penging">
<view v-if="isLogin">
<scroll-view v-if="deviceInfo" scroll-y="true" :style="{ height: deviceInfo.windowHeight + 'px' }"
lower-threshold="100" @refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
:refresher-triggered="refresherTriggered">
<view class="search">
<up-search :searchIconSize="48" :inputStyle="{ fontSize: '32rpx' }" @focus="getFocus" @blur="getBlur"
:height="80" placeholder="搜索" :clearabled="false" @change="changeSearch"
v-model="lockSearch.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
</view>
<view class="lock-list" v-if="!penging">
<view v-if="lockList.length === 0 && lockSearch.searchStr === '' && !focus">
<image src="/static/images/icon_add_round.png" mode="aspectFill" class="button-add-big"
@click="toSearchDevice"></image>
<view class="text">填加锁时手机必须在锁旁边</view>
</view>
<view v-else>
<view class="group" v-for="group in lockList" :key="group.groupId">
<view class="group-name">
<view class="group-name-text">{{group.groupName}}</view>
<view class="group-name-line"></view>
</view>
<view class="lock" v-for="lock in group.lockList" :key="lock.lockId" @click="toLockDeatil(lock)">
<view class="lock-top">
<image class="lock-image-lock" src="/static/images/icon_lock.png"></image>
<view class="lock-top-right">
<view class="lock-top-right-power">
<image class="lock-top-right-power-image" src="/static/images/icon_power.png"></image>
<view class="lock-top-right-power-text">{{lock.electricQuantity}}%</view>
</view>
<view>{{getRole(lock.userType, lock.keyRight)}}</view>
</view>
</view>
<view class="lock-name">{{lock.lockAlias}}</view>
<view style="display: flex;align-items: center">
<view v-if="lock.keyStatus === 110412" class="lock-status">已过期</view>
<view v-if="lock.days" class="lock-status" style="background-color: #63b8af">{{lock.days}}</view>
<view v-if="lock.keyStatus === 110403" class="lock-status" style="background-color: #63b8af">未生效</view>
<view v-if="lock.keyStatus === 110405" class="lock-status">已冻结</view>
<view v-if="lock.lockSetting.remoteUnlock === 1" class="lock-status" style="background-color:
#63b8af">远程开锁
</view>
</view>
<view class="lock-time"
:style="{padding: lock.keyStatus === 110401 && !lock.days ? '12rpx 24rpx 0 24rpx'
:'6rpx 24rpx 0 24rpx'}">
<view v-if="lock.keyType === 1 || lock.keyType === 3" style="font-size: 32rpx">{{
getTimeLimit(lock.keyType) }}</view>
<view v-else>
<view>{{ timeFormat(lock.startDate, 'yyyy-mm-dd h:M') }}</view>
<view>{{ timeFormat(lock.endDate, 'yyyy-mm-dd h:M ') + getTimeLimit(lock.keyType) }}</view>
</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<image v-if="lockList.length !== 0" src="/static/images/icon_add_round.png" mode="aspectFill"
class="button-add" @click="toSearchDevice"></image>
</view>
<view v-else>
<view class="tips">因智能门锁与账号绑定登录为手机号登录</view>
<label for="phone">
<view class="button-login">登录</view>
</label>
</view>
</view>
<button open-type="getPhoneNumber" style="display:none" id="phone" @getphonenumber="getphonenumber"></button>
</view>
</template>
<script>
import { timeFormat } from 'uview-plus'
import { getUserInfoRequest, loginRequest } from '@/api/user'
import { useUserStore } from '@/stores/user'
import { useLockStore } from '@/stores/lock'
import { useBluetoothStore } from '@/stores/bluetooth'
import { useBasicStore } from '@/stores/basic'
import { mapState, mapActions } from 'pinia'
export default {
data() {
return {
refresherTriggered: false,
focus: false,
penging: true,
deviceInfo: null
}
},
computed: {
...mapState(useUserStore, ['userInfo', 'isLogin']),
...mapState(useLockStore, ['lockList', 'lockTotal', 'lockSearch']),
...mapState(useBluetoothStore, ['bluetoothStatus', 'isInitBluetooth']),
},
async onLoad() {
uni.showLoading({
title: '加载中',
mask: true
})
const accountInfo = uni.getAccountInfoSync()
console.log(accountInfo)
getApp().globalData.appid = accountInfo.miniProgram.appId
getApp().globalData.envVersion = accountInfo.miniProgram.envVersion
this.deviceInfo = await this.getDeviceInfo()
const token = uni.getStorageSync('token')
if(token) {
this.getLockList(this.lockSearch)
await this.getUserInfo()
} else {
await this.homeLogin()
}
this.penging = false
uni.hideLoading()
},
methods: {
timeFormat,
...mapActions(useUserStore, ['updateUserInfo', 'updateLoginStatus', 'phoneLogin', 'getUserInfo']),
...mapActions(useLockStore, ['getLockList', 'getRole', 'getTimeLimit', 'updateLockSearch']),
...mapActions(useBluetoothStore, ['getBluetoothStatus', 'initAndListenBluetooth', 'updateCurrentLockInfo',
'checkSetting', 'updateKeyId']),
...mapActions(useBasicStore, ['routeJump', 'getDeviceInfo']),
homeLogin() {
const that = this
return new Promise((resolve) => {
uni.login({
provider: 'weixin',
success: async function (loginRes) {
const { code, data } = await loginRequest({
js_code: loginRes.code
})
if(code === 0) {
uni.setStorageSync('openid', data.openid)
if(data.accessToken) {
uni.setStorageSync('token', data.accessToken)
that.getLockList(that.lockSearch)
await that.getUserInfo()
that.updateLoginStatus(true)
resolve(true)
} else {
that.updateLoginStatus(false)
resolve(false)
}
} else {
uni.showToast({
title: '登录失败,请重试',
icon: 'none'
})
resolve(false)
}
},
fail: function () {
uni.showToast({
title: '登录失败,请重试',
icon: 'none'
})
resolve(false)
}
})
})
},
async getphonenumber(data) {
if(data.detail.errMsg === 'getPhoneNumber:fail user deny') {
return
}
const result = await this.phoneLogin({
encryptedData: data.detail.encryptedData,
iv: data.detail.iv
})
if(!result) {
uni.showToast({
title: '登录失败,请重试',
icon: 'none'
})
}
},
async nextPage() {
if(this.lockList.length < this.lockTotal) {
const sreach = {
...this.lockSearch,
pageNo: this.lockSearch.pageNo + 1
}
const { code } = await this.getLockList(search)
if(code !== 0) {
this.updateLockSearch(search)
}
}
},
async refresherList() {
this.refresherTriggered = true
this.updateLockSearch({
...this.lockSearch,
pageNo: 1
})
await this.getLockList(this.lockSearch)
uni.showToast({
title: '刷新成功',
icon: 'none'
})
this.refresherTriggered = false
},
async changeSearch(data) {
this.updateLockSearch({
...this.lockSearch,
searchStr: data
})
await this.getLockList(this.lockSearch)
},
getFocus() {
this.focus = true
},
getBlur() {
this.focus = false
},
async toSearchDevice() {
if(this.bluetoothStatus !== 0) {
this.getBluetoothStatus()
return
}
let result = true
if(!this.isInitBluetooth) {
result = await this.initAndListenBluetooth()
}
if(result) {
this.routeJump({
name: 'searchDevice'
})
} else {
this.checkSetting()
}
},
async toLockDeatil(lock) {
if(this.bluetoothStatus !== 0) {
this.getBluetoothStatus()
return
}
if(lock.keyStatus === 110412) {
uni.showToast({
title: '钥匙已过期',
icon: 'none'
})
return
}
if(lock.keyStatus === 110405) {
uni.showToast({
title: '钥匙已冻结',
icon: 'none'
})
return
}
let result = true
if(!this.isInitBluetooth) {
result = await this.initAndListenBluetooth()
}
if(result) {
const data = {
...lock,
name: lock.bluetooth.bluetoothDeviceName,
deviceId: lock.bluetooth.bluetoothDeviceId,
commKey: lock.bluetooth.privateKey,
signKey: lock.bluetooth.signKey,
publicKey: lock.bluetooth.publicKey,
}
this.updateKeyId(lock.keyId.toString())
this.updateCurrentLockInfo(data)
this.routeJump({
name: 'lockDetail'
})
} else {
this.checkSetting()
}
}
}
}
</script>
<style lang="scss">
page {
background-color: $uni-bg-color-grey;
}
</style>
<style scoped lang="scss">
.search {
margin-top: 32rpx;
width: 686rpx !important;
margin-left: 32rpx;
}
.button-login {
border-radius: 46rpx;
width: 650rpx;
height: 120rpx;
line-height: 120rpx;
text-align: center;
margin-left: 50rpx;
background: #63b8af;
color: #ffffff;
font-size: 48rpx;
font-weight: bold;
}
.button-add {
width: 120rpx;
height: 120rpx;
position: fixed;
right: 50rpx;
bottom: 50rpx;
border-radius: 50%;
}
.lock-list {
padding-bottom: 32rpx;
width: 672rpx;
margin-left: 39rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.lock {
margin-top: 32rpx;
width: 320rpx;
height: 300rpx;
background: #FFFFFF;
box-shadow: 0 8rpx 36rpx 0 rgba(0,0,0,0.12);
border-radius: 32rpx;
.lock-name {
padding: 0 24rpx;
font-size: 32rpx;
font-weight: bold;
word-break: break-all;
line-height: 38rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
}
.lock-time {
padding: 6rpx 24rpx 0 24rpx;
font-size: 22rpx;
font-weight: bold;
}
.lock-top {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 24rpx 12rpx 24rpx;
font-size: 22rpx;
.lock-image-lock {
width: 64rpx;
height: 64rpx;
}
.lock-top-right-power {
display: flex;
align-items: center;
.lock-top-right-power-image {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
}
}
}
.group {
width: 672rpx;
margin-top: 32rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.group-name {
width: 672rpx;
display: flex;
align-items: center;
font-size: 32rpx;
font-weight: bold;
}
.group-name-text {
padding: 0 32rpx;
}
.group-name-line {
flex-grow: 1;
height: 3rpx;
background: #E5E5E5;
}
}
}
.button-add-big {
width: 400rpx;
height: 400rpx;
margin-top: 250rpx;
margin-left: 136rpx;
}
.text {
width: 672rpx;
font-size: 32rpx;
color: #999999;
text-align: center;
margin-top: 32rpx;
font-weight: bold;
}
.tips {
margin-top: 40vh;
padding: 32rpx 0;
text-align: center;
font-size: 28rpx;
color: #999999;
}
.lock-status {
margin-left: 24rpx;
color: #FFFFFF;
border-radius: 8rpx;
font-size: 22rpx;
font-weight: bold;
display: inline-block;
padding: 4rpx 8rpx;
background-color: #ecab1f;
text-align: center;
}
</style>