Merge branch 'fanpeng' into 'develop'

1. 完成常开模式

See merge request StarlockTeam/wx-starlock!29
This commit is contained in:
范鹏 2025-03-04 02:18:19 +00:00
commit c14af80d03
16 changed files with 822 additions and 350 deletions

View File

@ -46,3 +46,12 @@ export function lockUserListRequest(data) {
data
})
}
// 获取锁详情
export function getLockDetailRequest(data) {
return request({
url: '/lock/detail',
method: 'POST',
data
})
}

View File

@ -26,26 +26,26 @@
</view>
</template>
<script>
export default {
name: 'SwitchLoading',
props: {
size: Number
},
data() {
return {
show: false
}
},
methods: {
open() {
this.show = true
},
close() {
this.show = false
}
}
<script setup>
import { ref } from 'vue'
const show = ref(false)
const open = () => {
show.value = true
}
const close = () => {
show.value = false
}
defineProps({
size: {
type: Number,
required: true
}
})
defineExpose({ open, close })
</script>
<style>

View File

@ -512,6 +512,13 @@
"navigationBarTitleText": "录像时段",
"disableScroll": true
}
},
{
"path": "pages/passageMode/passageMode",
"style": {
"navigationBarTitleText": "常开模式",
"disableScroll": true
}
}
],
"globalStyle": {

View File

@ -19,15 +19,21 @@
import { timeFormat } from 'uview-plus'
import { useBluetoothStore } from '@/stores/bluetooth'
import { useUserStore } from '@/stores/user'
import { useBasicStore } from '@/stores/basic'
const $bluetooth = useBluetoothStore()
const $user = useUserStore()
const $basic = useBasicStore()
const pending = ref(false)
const show = ref(false)
onMounted(async () => {
const netWork = await $basic.getNetworkType()
if (!netWork) {
return
}
uni.showLoading({
title: '加载中'
})
@ -45,6 +51,8 @@
$bluetooth.closeBluetoothConnection()
if (lockStatus === 0) {
show.value = true
} else if (lockStatus === -21) {
/* empty */
} else {
uni.showToast({
title: '获取锁时间失败,请返回重试',
@ -61,9 +69,13 @@
})
const update = async () => {
if (pending.value && show.value) return
if (pending.value) return
const netWork = await $basic.getNetworkType()
if (!netWork) {
return
}
uni.showLoading({
title: '更新中'
title: '校准中'
})
pending.value = true
const { code, message } = await $bluetooth.updateServerTimestamp()
@ -84,19 +96,22 @@
indate: $bluetooth.serverTimestamp * 1000
}
})
show.value = true
uni.showToast({
title: '更新成功',
title: '校准成功',
icon: 'none'
})
} else if (lockStatus === -21) {
/* empty */
} else {
uni.hideLoading()
pending.value = false
uni.showToast({
title: '更新失败',
title: '校准失败,请保持在锁附近',
icon: 'none'
})
}
} else {
uni.hideLoading()
pending.value = false
uni.showToast({
title: message,
icon: 'none'

View File

@ -34,6 +34,9 @@
<view class="m-4 text-sm" v-if="check">
经过以上设定的时间锁会自动关闭开启或修改设置后请先开一次锁使时间生效
</view>
<view class="m-4 text-sm" v-if="check">
设定时间过短可能导致锁寿命缩短建议设定时间不低于10秒
</view>
<view
v-if="$bluetooth.currentLockSetting.lockBasicInfo.keyRight === 1"
:class="[canUpdate ? 'bg-#63b8af' : 'bg-#a3a3a3']"

View File

@ -1,143 +1,191 @@
<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>
<scroll-view
v-if="deviceInfo"
scroll-y="true"
:style="{ height: deviceInfo.screenHeight - deviceInfo.safeArea.top + 'px' }"
@refresherrefresh="refresher"
:refresher-enabled="true"
:refresher-triggered="refresherTriggered"
>
<view class="days" v-if="$bluetooth.currentLockInfo.days"
>钥匙将在{{ $bluetooth.currentLockInfo.days }}天后失效</view
>
<view class="lock-name">{{ $bluetooth.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="$lock.getPowerIcon($bluetooth.currentLockInfo.electricQuantity)"
mode="aspectFill"
></image>
<view class="power-text">{{ $bluetooth.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="sLoading"></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>{{
$lock.getRole(
$bluetooth.currentLockInfo.userType,
$bluetooth.currentLockInfo.keyRight
)
}}</view>
</view>
<view class="bottom-side">
<image
class="bottom-icon"
:src="
$bluetooth.currentLockInfo.appUnlockOnline
? '/static/images/icon_cloud_active.png'
: '/static/images/icon_cloud.png'
"
mode="aspectFill"
style="width: 40rpx; height: 40rpx"
></image>
<view
:style="{
color: $bluetooth.currentLockInfo.appUnlockOnline ? '#63b8af' : '#a3a3a3'
}"
>手机需联网</view
>
</view>
</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 class="menu">
<view class="menu-title">
<image class="menu-image" src="/static/images/icon_menu.png"></image>
<view>功能</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 class="menu-main">
<view
:style="{ color: currentLockInfo.lockSetting.appUnlockOnline ? '#63b8af' : '#a3a3a3' }"
>手机需联网</view
v-if="$bluetooth.currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="$basic.routeJump({ name: 'keyList' })"
>
<image
class="menu-main-image transform-scale-90"
src="/static/images/icon_key.png"
></image>
<view>电子钥匙</view>
</view>
<view
v-if="
$bluetooth.currentLockInfo.lockFeature.password &&
$bluetooth.currentLockInfo.keyRight === 1
"
class="menu-main-view"
@click="$basic.routeJump({ name: 'passwordList' })"
>
<image class="menu-main-image" src="/static/images/icon_password_green.png"></image>
<view>密码</view>
</view>
<view
v-if="
$bluetooth.currentLockInfo.lockFeature.icCard &&
$bluetooth.currentLockInfo.keyRight === 1
"
class="menu-main-view"
@click="$basic.routeJump({ name: 'cardList' })"
>
<image
class="menu-main-image transform-scale-110"
src="/static/images/icon_card.png"
></image>
<view></view>
</view>
<view
v-if="
$bluetooth.currentLockInfo.lockFeature.fingerprint &&
$bluetooth.currentLockInfo.keyRight === 1
"
class="menu-main-view"
@click="$basic.routeJump({ name: 'fingerprintList' })"
>
<image class="menu-main-image" src="/static/images/icon_fingerprint.png"></image>
<view>指纹</view>
</view>
<view
v-if="
$bluetooth.currentLockInfo.lockFeature.bluetoothRemoteControl &&
$bluetooth.currentLockInfo.keyRight === 1
"
class="menu-main-view transform-scale-110"
@click="$basic.routeJump({ name: 'remoteList' })"
>
<image class="menu-main-image" src="/static/images/icon_remote.png"></image>
<view>遥控</view>
</view>
<view
v-if="
$bluetooth.currentLockInfo.lockFeature.d3Face &&
$bluetooth.currentLockInfo.keyRight === 1
"
class="menu-main-view"
@click="$basic.routeJump({ name: 'faceList' })"
>
<image class="menu-main-image" src="/static/images/icon_face.png"></image>
<view>人脸</view>
</view>
<view
v-if="
$bluetooth.currentLockInfo.lockFeature.palmVein &&
$bluetooth.currentLockInfo.keyRight === 1
"
class="menu-main-view"
@click="$basic.routeJump({ name: 'palmVeinList' })"
>
<image class="menu-main-image" src="/static/images/icon_palm_vein.png"></image>
<view>掌静脉</view>
</view>
<view
v-if="$bluetooth.currentLockInfo.userType === 110301"
class="menu-main-view"
@click="$basic.routeJump({ name: 'adminList' })"
>
<image
class="menu-main-image transform-scale-140"
src="/static/images/icon_admin_black.png"
></image>
<view>授权管理员</view>
</view>
<view
class="menu-main-view transform-scale-105"
@click="$basic.routeJump({ name: 'recordList' })"
>
<image class="menu-main-image" src="/static/images/icon_record.png"></image>
<view>操作记录</view>
</view>
<view
v-if="$bluetooth.currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="$basic.routeJump({ name: 'messageReminder' })"
>
<image
class="menu-main-image transform-scale-110"
src="/static/images/icon_remind.png"
></image>
<view>消息提醒</view>
</view>
</view>
</view>
</view>
<view class="menu">
<view class="menu-title">
<image class="menu-image" src="/static/images/icon_menu.png"></image>
<view>功能</view>
<view class="setting" @click="$basic.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>
<view class="menu-main">
<view
v-if="currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'keyList' })"
>
<image
class="menu-main-image transform-scale-90"
src="/static/images/icon_key.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_password_green.png"></image>
<view>密码</view>
</view>
<view
v-if="currentLockInfo.lockFeature.icCard && currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'cardList' })"
>
<image
class="menu-main-image transform-scale-110"
src="/static/images/icon_card.png"
></image>
<view></view>
</view>
<view
v-if="currentLockInfo.lockFeature.fingerprint && currentLockInfo.keyRight === 1"
class="menu-main-view"
@click="routeJump({ name: 'fingerprintList' })"
>
<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 transform-scale-110"
@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" 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>
<view
v-if="currentLockInfo.userType === 110301"
class="menu-main-view"
@click="routeJump({ name: 'adminList' })"
>
<image
class="menu-main-image transform-scale-140"
src="/static/images/icon_admin_black.png"
></image>
<view>授权管理员</view>
</view>
<view class="menu-main-view transform-scale-105" @click="routeJump({ name: 'recordList' })">
<image class="menu-main-image" src="/static/images/icon_record.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>
</scroll-view>
<up-popup
:show="show"
@close="closePopup"
@ -149,14 +197,14 @@
<image
class="popup-background"
:src="
type === 'close'
typeValue === 'close'
? '/static/images/background_close_door.png'
: '/static/images/background_open_door.png'
"
mode="aspectFill"
/>
<view>
<view class="popup-name">{{ currentLockInfo.lockAlias }}</view>
<view class="popup-name">{{ $bluetooth.currentLockInfo.lockAlias }}</view>
<view class="popup-time">{{ timeFormat('', 'mm/dd h:M') }}</view>
</view>
</view>
@ -164,190 +212,202 @@
</view>
</template>
<script>
import { mapState, mapActions } from 'pinia'
<script setup>
import { timeFormat } from 'uview-plus'
import { onMounted, 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 { getLockNetTokenRequest } from '@/api/lock'
import { getLockDetailRequest, getLockNetTokenRequest } from '@/api/lock'
import { deleteKeyRequest } from '@/api/key'
export default {
components: {
SwitchLoading
},
data() {
return {
time: 0,
onlineToken: '0',
pending: false,
show: false,
type: ''
}
},
computed: {
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
...mapState(useUserStore, ['userInfo']),
...mapState(useLockStore, ['lockSearch'])
},
onLoad() {
this.getServeTime()
},
methods: {
timeFormat,
...mapActions(useLockStore, ['getRole', 'updateLockSearch', 'getLockList', 'getPowerIcon']),
...mapActions(useBluetoothStore, [
'openDoor',
'updateServerTimestamp',
'closeBluetoothConnection',
'syncRecord'
]),
...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
}
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, 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
}
if (this.pending) {
return
}
if (this.currentLockInfo.lockSetting.appUnlockOnline && type !== 'close') {
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 && type !== 'close') {
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
})
this.syncRecord({
keyId: this.currentLockInfo.toString(),
uid: this.userInfo.uid.toString()
}).then(() => {
this.closeBluetoothConnection()
})
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
})
}
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 === 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'
})
}
this.$refs.loading.close()
this.pending = false
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)
onMounted(async () => {
deviceInfo.value = await $basic.getDeviceInfo()
await getServeTime()
})
const openDoorOperate = async type => {
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
})
return
}
if (pending.value) {
return
}
if ($bluetooth.currentLockInfo.appUnlockOnline && type !== 'close') {
const netWork = await $basic.getNetworkType()
if (!netWork) {
return
}
}
uni.vibrateLong()
pending.value = true
sLoading.value.open()
if (type === 'close') {
uni.showToast({
title: `正在尝试闭锁……`,
icon: 'none'
})
}
if ($bluetooth.currentLockInfo.appUnlockOnline && type !== 'close') {
const result = await getNetToken()
if (!result) {
sLoading.value.close()
pending.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
})
$bluetooth
.syncRecord({
keyId: $bluetooth.currentLockInfo.keyId.toString(),
uid: $user.userInfo.uid.toString()
})
.then(() => {
$bluetooth.closeBluetoothConnection()
})
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
})
}
if (code === 0) {
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'
})
}
sLoading.value.close()
pending.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
}
</script>

View File

@ -243,6 +243,7 @@
if (data[i].openLockType === 5) {
for (let j = 0; j < data[i].keys.length; j++) {
data[i].keys[j].openLockType = data[i].openLockType
data[i].keys[j].name = data[i].keys[j].faceName
data[i].keys[j].id = data[i].keys[j].faceId
if (data[i].keys[j].faceType === 1) {
data[i].keys[j].timeText =

View File

@ -25,7 +25,7 @@
<input
class="w-450 h-60 text-right font-bold text-base"
:value="remark"
maxlength="50"
:maxlength="50"
placeholder="请输入"
placeholder-class="text-base line-height-60rpx font-bold text-right"
@input="updateName"
@ -236,8 +236,9 @@
const deleteData = async () => {
uni.showModal({
title: '提示',
content: '确定删除吗?',
title: '是否删除家人?',
content: '删除家人后,你将不会收到他到家的消息',
confirmText: '删除',
success: async res => {
if (res.confirm) {
if (pending.value) return

View File

@ -114,7 +114,7 @@
const confirm = () => {
for (let i = 0; i < emailList.value.length; i++) {
if (test.email(emailList.value[i].account) === false) {
if (test.email(emailList.value[i].account) === false && emailList.value[i].account !== '') {
uni.showToast({
title: '含不符合规范的邮箱',
icon: 'none'
@ -123,7 +123,7 @@
}
}
for (let i = 0; i < smsList.value.length; i++) {
if (test.mobile(smsList.value[i].account) === false) {
if (test.mobile(smsList.value[i].account) === false && smsList.value[i].account !== '') {
uni.showToast({
title: '含不符合规范的手机号',
icon: 'none'
@ -131,10 +131,14 @@
return
}
}
const email = emailList.value.filter(item => item.account !== '')
const sms = smsList.value.filter(item => item.account !== '')
eventChannel.emit('confirm', {
noticeWay: [
{ type: 'mail', accounts: emailList.value },
{ type: 'sms', accounts: smsList.value }
{ type: 'mail', accounts: email },
{ type: 'sms', accounts: sms }
]
})
}

View File

@ -49,9 +49,11 @@
import { updateLockSettingRequest } from '@/api/setting'
import { useBluetoothStore } from '@/stores/bluetooth'
import { useUserStore } from '@/stores/user'
import { useBasicStore } from '@/stores/basic'
const $bluetooth = useBluetoothStore()
const $user = useUserStore()
const $basic = useBasicStore()
const value = ref(0)
@ -63,6 +65,10 @@
const updateValue = async val => {
if (pending.value || value.value === val) return
const netWork = await $basic.getNetworkType()
if (!netWork) {
return
}
pending.value = true
uni.showLoading({
title: '更新中'
@ -102,6 +108,9 @@
icon: 'none'
})
}
} else if (code === -21) {
pending.value = false
uni.hideLoading()
} else {
pending.value = false
uni.hideLoading()

View File

@ -0,0 +1,297 @@
<template>
<view>
<view class="py-3 px-4 bg-white !py-2 flex items-center justify-between text-base">
<view>常开模式</view>
<switch
@click="changeSwitch"
:checked="check"
class="transform-scale-90"
:disabled="true"
color="#002ce5"
/>
</view>
<view class="py-3 px-4 bg-white text-sm mt-4rpx">
你可以设置多个常开时间段在设置的时间段内锁被打开后一直处于打开状态
</view>
<view class="font-bold text-base bg-white mt-2" v-if="check">
<view class="border-b-solid border-b-1 border-b-gray-200">
<view class="mx-3">
<view class="pt-2">常开日期</view>
<view class="mr-2 flex items-center justify-around py-2">
<view
v-for="(item, index) in list"
:key="index"
:class="[weekDays.includes(index + 1) ? 'bg-#5eb7ac text-white' : '']"
@click="changeSelect(index)"
class="rounded-50% border-solid border-3 border-gray-400 flex items-center justify-center w-70 h-70"
>{{ item }}</view
>
</view>
</view>
</view>
</view>
<view class="font-bold text-base bg-white mt-2" v-if="check">
<view class="border-b-solid border-b-1 border-b-gray-200">
<view class="mx-3 flex items-center h-100">
<view class="w-168">常开时间</view>
<view class="ml-a">
<view class="flex items-center" @click="isAllDay = isAllDay === 1 ? 0 : 1">
<view class="mr-2">全天</view>
<image class="w-40 h-40" v-if="isAllDay" src="/static/images/icon_select.png"></image>
<image v-else class="w-40 h-40" src="/static/images/icon_not_select.png"></image>
</view>
</view>
</view>
</view>
<view class="border-b-solid border-b-1 border-b-gray-200" @click="showStartTime = true">
<view class="mx-3 flex items-center h-100">
<view class="w-168">开始时间</view>
<view class="ml-a flex items-center">
<view v-if="startTimeText" class="mr-2">
<view>{{ startTimeText }}</view>
</view>
<up-icon name="arrow-right"></up-icon>
</view>
</view>
</view>
<view>
<view class="mx-3 flex items-center h-100" @click="showEndTime = true">
<view class="w-168">结束时间</view>
<view class="ml-a flex items-center">
<view v-if="endTimeText" class="mr-2">
<view>{{ endTimeText }}</view>
</view>
<up-icon name="arrow-right"></up-icon>
</view>
</view>
</view>
</view>
<view
@click="confirm"
:class="[canUpdate ? 'bg-#63b8af' : 'bg-#a3a3a3']"
class="pos-fixed bottom-[calc(env(safe-area-inset-bottom)+48rpx)] w-686 mx-4 h-88 line-height-88rpx text-center text-white rounded-3xl"
>保存
</view>
<up-datetime-picker
:hasInput="false"
:show="showStartTime"
:itemHeight="70"
:visibleItemCount="5"
v-model="defaultStartTime"
mode="time"
closeOnClickOverlay
@close="showStartTime = false"
@confirm="confirmTime('start', $event)"
@cancel="showStartTime = false"
></up-datetime-picker>
<up-datetime-picker
:hasInput="false"
:show="showEndTime"
:itemHeight="70"
:visibleItemCount="5"
v-model="defaultEndTime"
mode="time"
closeOnClickOverlay
@close="showEndTime = false"
@confirm="confirmTime('end', $event)"
@cancel="showEndTime = false"
></up-datetime-picker>
</view>
</template>
<script setup>
import { computed, onMounted, ref } from 'vue'
import { useBluetoothStore } from '@/stores/bluetooth'
import { updateLockSettingRequest } from '@/api/setting'
import { useBasicStore } from '@/stores/basic'
import { useUserStore } from '@/stores/user'
const $bluetooth = useBluetoothStore()
const $basic = useBasicStore()
const $user = useUserStore()
const showStartTime = ref(false)
const showEndTime = ref(false)
const defaultStartTime = ref('')
const defaultEndTime = ref('')
const startTimeText = ref(null)
const endTimeText = ref(null)
const check = ref(false)
const weekDays = ref([])
const isAllDay = ref(0)
const list = ['一', '二', '三', '四', '五', '六', '日']
const autoUnlock = ref(0)
const pending = ref(false)
const canUpdate = computed(() => {
return (
!check.value ||
(check.value && weekDays.value.length > 0 && startTimeText.value && endTimeText.value)
)
})
onMounted(() => {
check.value = $bluetooth.currentLockSetting.lockSettingInfo.passageMode
if ($bluetooth.currentLockSetting.lockSettingInfo.passageModeConfig.length > 0) {
const {
weekDays: weekDaysResult,
isAllDay: isAllDayResult,
startDate,
endDate
} = $bluetooth.currentLockSetting.lockSettingInfo.passageModeConfig[0]
weekDays.value = weekDaysResult
isAllDay.value = isAllDayResult
startTimeText.value = `${
Math.floor(startDate / 60) < 10
? '0' + Math.floor(startDate / 60)
: Math.floor(startDate / 60)
}:${Math.floor(startDate % 60) < 10 ? '0' + Math.floor(startDate % 60) : Math.floor(startDate % 60)}`
endTimeText.value = `${Math.floor(endDate / 60) < 10 ? '0' + Math.floor(endDate / 60) : Math.floor(endDate / 60)}:${Math.floor(endDate % 60) < 10 ? '0' + Math.floor(endDate % 60) : Math.floor(endDate % 60)}`
defaultStartTime.value = `${
Math.floor(startDate / 60) < 10
? '0' + Math.floor(startDate / 60)
: Math.floor(startDate / 60)
}:${Math.floor(startDate % 60) < 10 ? '0' + Math.floor(startDate % 60) : Math.floor(startDate % 60)}`
defaultEndTime.value = `${Math.floor(endDate / 60) < 10 ? '0' + Math.floor(endDate / 60) : Math.floor(endDate / 60)}:${Math.floor(endDate % 60) < 10 ? '0' + Math.floor(endDate % 60) : Math.floor(endDate % 60)}`
} else {
startTimeText.value = '00:00'
endTimeText.value = '00:00'
defaultStartTime.value = '00:00'
defaultEndTime.value = '00:00'
}
})
const changeSelect = index => {
if (weekDays.value.includes(index + 1)) {
weekDays.value.splice(weekDays.value.indexOf(index + 1), 1)
} else {
weekDays.value.push(index + 1)
weekDays.value.sort()
}
}
const convertWeekdaysToNumber = weekDay => {
let weekStr = '0000000'.split('')
for (let i = 0; i < 7; i++) {
const index = weekDay[i] % 7
weekStr[index] = '1'
}
return parseInt(weekStr.reverse().join(''), 2)
}
const confirm = async () => {
if (!canUpdate.value) return
const data = {
weekDays: weekDays.value,
isAllDay: isAllDay.value,
startDate:
parseInt(startTimeText.value.split(':')[0], 10) * 60 +
parseInt(startTimeText.value.split(':')[1], 10),
endDate:
parseInt(endTimeText.value.split(':')[0], 10) * 60 +
parseInt(endTimeText.value.split(':')[1], 10),
autoUnlock: autoUnlock.value
}
if (check.value && data.startDate >= data.endDate) {
uni.showToast({
title: '开始时间不能大于结束时间',
icon: 'none'
})
return
}
const netWork = await $basic.getNetworkType()
if (!netWork) {
return
}
if (pending.value) return
pending.value = true
uni.showLoading({
title: '保存中'
})
const listData = [
check.value ? 1 : 0,
Math.floor(data.startDate / 256),
data.startDate % 256,
Math.floor(data.endDate / 256),
data.endDate % 256,
data.isAllDay,
convertWeekdaysToNumber(data.weekDays),
data.autoUnlock
]
const featureBit = 50
const { code } = await $bluetooth.updateSetting({
keyId: $bluetooth.keyId.toString(),
uid: $user.userInfo.uid.toString(),
featureBit,
params: listData,
withParams: true
})
$bluetooth.closeBluetoothConnection()
if (code === 0) {
const { code, message } = await updateLockSettingRequest({
lockId: $bluetooth.currentLockInfo.lockId,
passageMode: check.value ? 1 : 0,
passageModeConfig: [data]
})
pending.value = false
uni.hideLoading()
if (code === 0) {
$bluetooth.updateCurrentLockSetting({
...$bluetooth.currentLockSetting,
lockSettingInfo: {
...$bluetooth.currentLockSetting.lockSettingInfo,
passageMode: check.value ? 1 : 0,
passageModeConfig: [data]
}
})
$basic.backAndToast('更新成功')
} else {
uni.showToast({
title: message,
icon: 'none'
})
}
} else if (code === -21) {
pending.value = false
uni.hideLoading()
} else {
pending.value = false
uni.hideLoading()
uni.showToast({
title: '更新失败,请保持在锁附近',
icon: 'none'
})
}
}
const changeSwitch = () => {
check.value = !check.value
}
const confirmTime = (type, date) => {
if (type === 'start') {
startTimeText.value = date.value
showStartTime.value = false
} else {
endTimeText.value = date.value
showEndTime.value = false
}
}
</script>
<style lang="scss">
page {
background-color: $uni-bg-color-grey;
}
</style>

View File

@ -64,6 +64,24 @@
</view>
</view>
<view class="mt-2.5"></view>
<view
v-if="
$bluetooth.currentLockSetting.lockFeature.passageMode === 1 &&
$bluetooth.currentLockSetting.lockBasicInfo.keyRight === 1
"
class="py-3 px-4 bg-white flex items-center justify-between text-base mb-4rpx"
@click="$basic.routeJump({ name: 'passageMode' })"
>
<view class="item-title">常开模式</view>
<view class="flex items-center">
<view class="mr-2 max-w-400">
{{
$bluetooth.currentLockSetting.lockSettingInfo.passageMode === 1 ? '已开启' : '已关闭'
}}
</view>
<up-icon name="arrow-right"></up-icon>
</view>
</view>
<view
v-if="
$bluetooth.currentLockSetting.lockFeature.remoteUnlock === 1 &&
@ -201,10 +219,14 @@
<view class="item-title">上传数据</view>
<view><up-icon name="arrow-right"></up-icon></view>
</view>
<!-- <view class="py-3 px-4 bg-white flex items-center justify-between text-base mt-4rpx">-->
<!-- <view class="item-title">锁升级</view>-->
<!-- <view><up-icon name="arrow-right"></up-icon></view>-->
<!-- </view>-->
<view
class="py-3 px-4 bg-white flex items-center justify-between text-base mt-4rpx"
v-if="$bluetooth.currentLockSetting.lockBasicInfo.keyRight === 1"
@click="upgrade"
>
<view class="item-title">锁升级</view>
<view><up-icon name="arrow-right"></up-icon></view>
</view>
<view
class="mt-4 rounded-3xl w-600 h-80 line-height-80rpx text-center mx-75rpx bg-#ec433c text-white text-xl font-bold"
@click="deleteLock"
@ -275,6 +297,14 @@
await asyncSetting()
})
const upgrade = () => {
uni.showModal({
title: '提示',
content: '小程序暂不支持升级功能请下载星星锁APP进行升级',
showCancel: false
})
}
const asyncSetting = async () => {
const { code, data } = await $bluetooth.getLockDataList({
type: 'setting',
@ -325,8 +355,38 @@
})
let featureBit
if (key === 'unlockReminder') {
featureBit = 47
} else if (key === 'appUnlockOnline') {
const { code, message } = await updateLockSettingRequest({
lockId: $bluetooth.currentLockInfo.lockId,
[key]: $bluetooth.currentLockSetting.lockSettingInfo[key] === 1 ? 0 : 1
})
pending.value = false
uni.hideLoading()
if (code === 0) {
$bluetooth.updateCurrentLockSetting({
...$bluetooth.currentLockSetting,
lockSettingInfo: {
...$bluetooth.currentLockSetting.lockSettingInfo,
[key]: $bluetooth.currentLockSetting.lockSettingInfo[key] === 1 ? 0 : 1
}
})
$lock.updateLockSearch({
...$lock.lockSearch,
pageNo: 1
})
$lock.getLockList($lock.lockSearch)
uni.showToast({
title: '更新成功',
icon: 'none'
})
} else {
uni.showToast({
title: message,
icon: 'none'
})
}
return
}
if (key === 'appUnlockOnline') {
featureBit = 55
} else if (key === 'remoteUnlock') {
featureBit = 28
@ -373,6 +433,9 @@
icon: 'none'
})
}
} else if (code === -21) {
pending.value = false
uni.hideLoading()
} else {
pending.value = false
uni.hideLoading()

View File

@ -112,11 +112,10 @@
const data = JSON.parse(options.info)
if (data.startDate) {
startDate.value = data.startDate
endDate.value = data.endDate === 0 ? data.startDate + 24 * 60 * 60 * 1000 : data.endDate
endDate.value = data.endDate === 0 ? data.startDate : data.endDate
info.value = data
defaultStartDate.value = data.startDate
defaultEndDate.value =
data.endDate === 0 ? data.startDate + 24 * 60 * 60 * 1000 : data.endDate
defaultEndDate.value = data.endDate === 0 ? data.startDate : data.endDate
}
}
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -376,6 +376,11 @@ const pages = [
name: 'videoSlot',
path: '/pages/videoSlot/videoSlot',
tabBar: false
},
{
name: 'passageMode',
path: '/pages/passageMode/passageMode',
tabBar: false
}
]

View File

@ -1073,7 +1073,6 @@ export const useBluetoothStore = defineStore('ble', {
for (let i = 0; i < deviceList.length; i++) {
if (deviceList[i]?.name === that.currentLockInfo.name) {
const uuid = deviceList[i]?.advertisServiceUUIDs[0]
console.log('设备UUID', uuid, uuid.slice(2, 8), uuid.slice(30, 32))
if (
uuid &&
uuid.slice(2, 8) === '758824' &&
@ -1476,7 +1475,7 @@ export const useBluetoothStore = defineStore('ble', {
console.log('写入未执行', this.bluetoothStatus)
this.getBluetoothStatus()
return {
code: -1
code: -21
}
}
@ -2920,7 +2919,7 @@ export const useBluetoothStore = defineStore('ble', {
console.log('写入未执行', this.bluetoothStatus)
this.getBluetoothStatus()
return {
code: -1
code: -21
}
}