2024-09-02 17:18:14 +08:00

402 lines
11 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 class="lock-time">
<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
}
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;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
}
.lock-time {
padding: 12rpx 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;
}
</style>