Merge branch 'fanpeng' into 'master'
完成绑定设备全部功能 See merge request StarlockTeam/wx-starlock!2
21
App.vue
@ -10,6 +10,25 @@
|
|||||||
// 更新登录状态
|
// 更新登录状态
|
||||||
updateIsLogin(isLogin) {
|
updateIsLogin(isLogin) {
|
||||||
useUserStore().updateLoginStatus(isLogin)
|
useUserStore().updateLoginStatus(isLogin)
|
||||||
|
},
|
||||||
|
// 账号信息
|
||||||
|
appid: '',
|
||||||
|
// 小程序版本
|
||||||
|
envVersion: '',
|
||||||
|
// 获取环境配置
|
||||||
|
getEnvConfig() {
|
||||||
|
const envVserionStorage = uni.getStorageSync('envVersion')
|
||||||
|
if(envVserionStorage) {
|
||||||
|
return envVserionStorage
|
||||||
|
} else {
|
||||||
|
if(this.envVersion === 'develop') {
|
||||||
|
return 'DEV'
|
||||||
|
} else if(this.envVersion === 'trial') {
|
||||||
|
return 'PRE'
|
||||||
|
} else {
|
||||||
|
return 'PROD'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -22,7 +41,7 @@
|
|||||||
const checkResult = await this.checkSetting()
|
const checkResult = await this.checkSetting()
|
||||||
console.log(checkResult)
|
console.log(checkResult)
|
||||||
if(checkResult === true) {
|
if(checkResult === true) {
|
||||||
this.initAndListenBluetooth()
|
this.initAndListenBluetooth(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
|
|||||||
12
api/check.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// check 检查模块
|
||||||
|
|
||||||
|
// 获取服务器时间
|
||||||
|
export function getServerDatetime(data) {
|
||||||
|
return request({
|
||||||
|
url: '/check/getServerDatetime',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
12
api/geocode.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// geocode 地理编码模块
|
||||||
|
|
||||||
|
// 获取地址信息
|
||||||
|
export function getGeocodeAddress(data) {
|
||||||
|
return request({
|
||||||
|
url: '/geocode/getAddress',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
57
api/key.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// key 电子钥匙模块
|
||||||
|
|
||||||
|
// 获取电子钥匙列表
|
||||||
|
export function getKeyListRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/key/listUser',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置电子钥匙
|
||||||
|
export function resetKeyRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/key/reset',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建电子钥匙
|
||||||
|
export function createKeyRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/v2/key/send',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除电子钥匙
|
||||||
|
export function deleteKeyRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/key/delete',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新锁用户
|
||||||
|
export function updateLockUserNoRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/key/updateLockUserNo',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有锁用户
|
||||||
|
export function getUserNoListRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/key/getUserNoList',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
39
api/keyboardPwd.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// keyboardPwd 锁密码模块
|
||||||
|
|
||||||
|
// 获取密码列表
|
||||||
|
export function getPsaawordListRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/keyboardPwd/listSendRecords',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置密码
|
||||||
|
export function resetPsaawordListRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/keyboardPwd/reset',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建密码
|
||||||
|
export function createPsaawordRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/keyboardPwd/get',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除密码
|
||||||
|
export function deletePsaawordRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/keyboardPwd/delete',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
27
api/lock.js
@ -10,3 +10,30 @@ export function getLockListRequest(data) {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 绑定锁管理员
|
||||||
|
export function bindLockAdmin(data) {
|
||||||
|
return request({
|
||||||
|
url: '/v2/lock/bindAdmin',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取手机联网token
|
||||||
|
export function getLockNetTokenRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/lock/getLockNetToken',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除智能门锁
|
||||||
|
export function deleteLockRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/lock/delete',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
12
api/lockRecords.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// lockRecords 锁记录模块
|
||||||
|
|
||||||
|
// 电子钥匙开门上报
|
||||||
|
export function reportOpenDoorRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/lockRecords/fromLock',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
12
api/lockSetting.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// lockSetting 锁设置模块
|
||||||
|
|
||||||
|
// 更新锁设置
|
||||||
|
export function updateLockSettingRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/lockSetting/updateLockSetting',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
12
api/room.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// room 房间模块
|
||||||
|
|
||||||
|
// 更新锁电量
|
||||||
|
export function updateElectricQuantityRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/room/uploadElectricQuantity',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
46
api/user.js
@ -55,3 +55,49 @@ export function getEmailCodeRequest(data) {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
export function loginRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wechat/mini/login',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
export function phoneLoginRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wechat/mini/phone/login',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更换绑定手机号
|
||||||
|
export function rebindPhoneRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wechat/mini/rebindPhone',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证码更换密码
|
||||||
|
export function changePasswordRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wechat/mini/changePassword',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新云用户时区偏移
|
||||||
|
export function updateTimezoneOffsetRequest(data) {
|
||||||
|
return request({
|
||||||
|
url: '/cloudUser/updateSettings',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
75
components/LockDatetimePicker/LockDatetimePicker.vue
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view @click="changeShow" class="name">
|
||||||
|
<view class="name-text">{{ title }}</view>
|
||||||
|
<view class="picker">
|
||||||
|
{{ timeFormat(time, 'yyyy-mm-dd h:M') }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<up-datetime-picker itemHeight="60" :minDate="minDate" :title="placeholder" :show="show" v-model="time"
|
||||||
|
mode="datetime" @confirm="confirm" :closeOnClickOverlay="true"
|
||||||
|
@close="close"></up-datetime-picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { timeFormat } from 'uview-plus'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'LockDatetimePicker',
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
value: Number,
|
||||||
|
minDate: Number,
|
||||||
|
placeholder: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
time: 0,
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.time = this.value
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
timeFormat,
|
||||||
|
changeShow() {
|
||||||
|
this.show = !this.show
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.show = false
|
||||||
|
},
|
||||||
|
confirm(e) {
|
||||||
|
this.show = false
|
||||||
|
this.$emit('changeTime', e.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.name {
|
||||||
|
height: 100rpx;
|
||||||
|
width: 750rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
|
||||||
|
.name-text {
|
||||||
|
width: 168rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker {
|
||||||
|
margin-right: 32rpx;
|
||||||
|
text-align: right;
|
||||||
|
width: 518rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
60
components/LockInput/LockInput.vue
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="name">
|
||||||
|
<view class="name-text">{{ title }}</view>
|
||||||
|
<input :value="value" class="name-input" :placeholder="placeholder" placeholder-class="placeholder-class"
|
||||||
|
maxlength="16" @input="changeInput"></input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'LockInput',
|
||||||
|
props:{
|
||||||
|
title: String,
|
||||||
|
placeholder: String,
|
||||||
|
value: String
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeInput(e) {
|
||||||
|
this.$emit('changeInput', e.detail.value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.name {
|
||||||
|
height: 100rpx;
|
||||||
|
width: 750rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
|
.name-text {
|
||||||
|
width: 168rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-input {
|
||||||
|
margin-right: 32rpx;
|
||||||
|
text-align: right;
|
||||||
|
width: 518rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder-class {
|
||||||
|
text-align: right;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
95
components/SwitchLoading/SwitchLoading.vue
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="spinner-box" :style="{width: size + 'rpx', height: size + 'rpx'}">
|
||||||
|
<view v-if="show" class="circle-border" :style="{width: size * 0.75 + 'rpx', height: size * 0.75 + 'rpx'}">
|
||||||
|
</view>
|
||||||
|
<view v-else class="circle-border-stop" :style="{width: size * 0.75 + 'rpx', height: size * 0.75 + 'rpx'}"></view>
|
||||||
|
<view class="circle-core" :style="{width: size * 0.75 - 2 + 'rpx', height: size * 0.75 - 2 + 'rpx'}">
|
||||||
|
<image src="/static/images/icon_lock_transparent.png" mode="aspectFill" :style="{width: size * 0.35 + 'rpx',
|
||||||
|
height: size * 0.35 + 'rpx'}"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "SwitchLoading",
|
||||||
|
props:{
|
||||||
|
size: Number,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open () {
|
||||||
|
this.show = true
|
||||||
|
},
|
||||||
|
close () {
|
||||||
|
this.show = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-border {
|
||||||
|
padding: 3upx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgb(99, 184, 175);
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
rgba(99, 184, 175, 0.1) 33%,
|
||||||
|
rgba(99, 184, 175, 1) 100%
|
||||||
|
);
|
||||||
|
animation: spin 0.8s linear 0s infinite;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-border-stop {
|
||||||
|
padding: 3upx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgb(99, 184, 175);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-core {
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,25 +1,30 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
const version = '1.0.0.0'
|
const version = '1.0.0'
|
||||||
|
const buildNumber = 0
|
||||||
|
|
||||||
const DEV = {
|
const DEV = {
|
||||||
name: '开发',
|
name: '开发',
|
||||||
baseUrl: 'https://dev.lock.star-lock.cn/api',
|
baseUrl: 'https://dev.lock.star-lock.cn/api',
|
||||||
webviewBaseUrl: 'https://dev.lock.star-lock.cn',
|
webviewBaseUrl: 'https://dev.lock.star-lock.cn',
|
||||||
version: version
|
version,
|
||||||
|
buildNumber
|
||||||
}
|
}
|
||||||
const PRE = {
|
const PRE = {
|
||||||
name: '预发',
|
name: '预发',
|
||||||
baseUrl: 'https://pre.lock.star-lock.cn/api',
|
baseUrl: 'https://pre.lock.star-lock.cn/api',
|
||||||
webviewBaseUrl: 'https://pre.lock.star-lock.cn',
|
webviewBaseUrl: 'https://pre.lock.star-lock.cn',
|
||||||
version: version
|
version,
|
||||||
|
buildNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
const PROD = {
|
const PROD = {
|
||||||
name: '线上',
|
name: '线上',
|
||||||
baseUrl: '',
|
baseUrl: 'https://lock.xhjcn.ltd/api',
|
||||||
version: version
|
webviewBaseUrl: 'https://lock.xhjcn.ltd',
|
||||||
|
version,
|
||||||
|
buildNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更换环境的时候 切换导出就行
|
// 更换环境的时候 切换导出就行
|
||||||
export default PRE
|
export default { DEV, PRE, PROD }
|
||||||
|
|||||||
@ -5,49 +5,6 @@
|
|||||||
"versionName" : "1.0.0",
|
"versionName" : "1.0.0",
|
||||||
"versionCode" : "100",
|
"versionCode" : "100",
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
/* 5+App特有相关 */
|
|
||||||
"app-plus" : {
|
|
||||||
"usingComponents" : true,
|
|
||||||
"nvueStyleCompiler" : "uni-app",
|
|
||||||
"compilerVersion" : 3,
|
|
||||||
"splashscreen" : {
|
|
||||||
"alwaysShowBeforeRender" : true,
|
|
||||||
"waiting" : true,
|
|
||||||
"autoclose" : true,
|
|
||||||
"delay" : 0
|
|
||||||
},
|
|
||||||
/* 模块配置 */
|
|
||||||
"modules" : {},
|
|
||||||
/* 应用发布信息 */
|
|
||||||
"distribute" : {
|
|
||||||
/* android打包配置 */
|
|
||||||
"android" : {
|
|
||||||
"permissions" : [
|
|
||||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
|
||||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
|
||||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
|
||||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
/* ios打包配置 */
|
|
||||||
"ios" : {},
|
|
||||||
/* SDK配置 */
|
|
||||||
"sdkConfigs" : {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/* 快应用特有相关 */
|
|
||||||
"quickapp" : {},
|
|
||||||
/* 小程序特有相关 */
|
/* 小程序特有相关 */
|
||||||
"mp-weixin" : {
|
"mp-weixin" : {
|
||||||
"appid" : "wx9829a39e65550757",
|
"appid" : "wx9829a39e65550757",
|
||||||
@ -55,20 +12,17 @@
|
|||||||
"urlCheck" : true,
|
"urlCheck" : true,
|
||||||
"minified" : true
|
"minified" : true
|
||||||
},
|
},
|
||||||
|
"permission" : {
|
||||||
|
"scope.bluetooth" : {
|
||||||
|
"desc" : "蓝牙将用于控制和管理您的智能门锁"
|
||||||
|
},
|
||||||
|
"scope.userLocation" : {
|
||||||
|
"desc" : "获取您的位置信息将用于智能门锁的位置服务"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requiredPrivateInfos" : [ "getLocation" ],
|
||||||
"usingComponents" : true,
|
"usingComponents" : true,
|
||||||
"lazyCodeLoading" : "requiredComponents"
|
"lazyCodeLoading" : "requiredComponents"
|
||||||
},
|
},
|
||||||
"mp-alipay" : {
|
|
||||||
"usingComponents" : true
|
|
||||||
},
|
|
||||||
"mp-baidu" : {
|
|
||||||
"usingComponents" : true
|
|
||||||
},
|
|
||||||
"mp-toutiao" : {
|
|
||||||
"usingComponents" : true
|
|
||||||
},
|
|
||||||
"uniStatistics" : {
|
|
||||||
"enable" : false
|
|
||||||
},
|
|
||||||
"vueVersion" : "3"
|
"vueVersion" : "3"
|
||||||
}
|
}
|
||||||
|
|||||||
132
pages.json
@ -9,123 +9,139 @@
|
|||||||
},
|
},
|
||||||
"pages": [
|
"pages": [
|
||||||
{
|
{
|
||||||
"path": "pages/home/home",
|
"path": "pages/home/home"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/selectAddress/selectAddress",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "星星锁",
|
"navigationBarTitleText": "锁地址",
|
||||||
"navigationBarTextStyle": "white",
|
"disableScroll": true
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/mine/mine",
|
"path": "pages/mine/mine"
|
||||||
"style": {
|
|
||||||
"navigationBarTitleText": "星星锁",
|
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "pages/index/index"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/userInfo/userInfo",
|
"path": "pages/userInfo/userInfo",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "个人信息",
|
"navigationBarTitleText": "个人信息"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/updateName/updateName",
|
"path": "pages/updateName/updateName",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "修改昵称",
|
"navigationBarTitleText": "修改昵称"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/updatePassword/updatePassword",
|
"path": "pages/updatePassword/updatePassword",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "重置密码",
|
"navigationBarTitleText": "重置密码"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/updateEmail/updateEmail",
|
"path": "pages/updateEmail/updateEmail",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "修改邮箱",
|
"navigationBarTitleText": "修改邮箱"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/verifyEmail/verifyEmail",
|
"path": "pages/verifyEmail/verifyEmail",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "验证邮箱",
|
"navigationBarTitleText": "验证邮箱"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/safeQuestion/safeQuestion",
|
"path": "pages/safeQuestion/safeQuestion",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "安全问题",
|
"navigationBarTitleText": "安全问题"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/updateSafeQuestion/updateSafeQuestion",
|
"path": "pages/updateSafeQuestion/updateSafeQuestion",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "修改安全问题",
|
"navigationBarTitleText": "修改安全问题"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/webview/webview",
|
"path": "pages/webview/webview",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "介绍",
|
"navigationBarTitleText": "介绍"
|
||||||
"navigationBarTextStyle": "white",
|
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
|
||||||
"navigationStyle": "default"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/lockDetail/lockDetail",
|
"path": "pages/lockDetail/lockDetail",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "星星锁",
|
"navigationBarTitleText": "星星锁"
|
||||||
"navigationBarTextStyle": "white",
|
}
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
},
|
||||||
"navigationStyle": "default"
|
{
|
||||||
|
"path": "pages/bindLock/bindLock",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "添加锁"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/searchDevice/searchDevice",
|
"path": "pages/searchDevice/searchDevice",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "搜索",
|
"disableScroll": true,
|
||||||
"navigationBarTextStyle": "white",
|
"navigationBarTitleText": "附近设备"
|
||||||
"navigationBarBackgroundColor": "#63b8af",
|
}
|
||||||
"navigationStyle": "default"
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/setting/setting",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "设置"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/keyList/keyList",
|
||||||
|
"style": {
|
||||||
|
"disableScroll": true,
|
||||||
|
"navigationBarTitleText": "电子钥匙"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/createKey/createKey",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "发送钥匙"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/passwordList/passwordList",
|
||||||
|
"style": {
|
||||||
|
"disableScroll": true,
|
||||||
|
"navigationBarTitleText": "密码"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/createPassword/createPassword",
|
||||||
|
"style": {
|
||||||
|
"disableScroll": true,
|
||||||
|
"navigationBarTitleText": "获取密码"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/passwordDetail/passwordDetail",
|
||||||
|
"style": {
|
||||||
|
"disableScroll": true,
|
||||||
|
"navigationBarTitleText": "密码详情"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/keyDetail/keyDetail",
|
||||||
|
"style": {
|
||||||
|
"disableScroll": true,
|
||||||
|
"navigationBarTitleText": "钥匙详情"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
"navigationBarTextStyle": "black",
|
"navigationBarTextStyle": "white",
|
||||||
"navigationBarTitleText": "星星锁",
|
"navigationBarTitleText": "星星锁",
|
||||||
"navigationBarBackgroundColor": "#F3F3F3",
|
"navigationBarBackgroundColor": "#63b8af",
|
||||||
"backgroundColor": "#F3F3F3",
|
"backgroundColor": "#F3F3F3",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "default"
|
||||||
},
|
},
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
"color": "#a3a3a3",
|
"color": "#a3a3a3",
|
||||||
|
|||||||
177
pages/bindLock/bindLock.vue
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="text">如需修改名字请重新命名,点击确定添加锁</view>
|
||||||
|
<input class="input" :value="name" maxlength="32" placeholder="请输入名称" placeholder-class="input-placeholder"
|
||||||
|
@input="uopdateName"
|
||||||
|
></input>
|
||||||
|
<view class="button" @click="bindLock">确定</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { bindLockAdmin } from '@/api/lock'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
|
||||||
|
...mapState(useUserStore, ['userInfo']),
|
||||||
|
...mapState(useLockStore, ['lockSearch']),
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.name = this.currentLockInfo.name
|
||||||
|
console.log(this.currentLockInfo)
|
||||||
|
console.log(this.name)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBluetoothStore, ['addLockUser']),
|
||||||
|
...mapActions(useLockStore, ['getLockList', 'updateLockSearch']),
|
||||||
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
|
uopdateName(data) {
|
||||||
|
this.name = data.detail.value
|
||||||
|
},
|
||||||
|
async bindLock() {
|
||||||
|
if(this.name === '') {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入名称',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.showLoading({
|
||||||
|
title: '添加中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const timestamp = parseInt(new Date().getTime() / 1000)
|
||||||
|
const password = (Math.floor(Math.random() * 900000) + 100000).toString()
|
||||||
|
const { code: addUserCode } = await this.addLockUser({
|
||||||
|
name: this.currentLockInfo.name,
|
||||||
|
keyId: this.keyId,
|
||||||
|
authUid: this.userInfo.uid.toString(),
|
||||||
|
uid: this.userInfo.uid.toString(),
|
||||||
|
openMode: 1,
|
||||||
|
keyType: 0,
|
||||||
|
startDate: timestamp,
|
||||||
|
expireDate: 0xffffffff,
|
||||||
|
useCountLimit: 0xffff,
|
||||||
|
isRound: 0,
|
||||||
|
weekRound: 0,
|
||||||
|
startHour: 0,
|
||||||
|
startMin: 0,
|
||||||
|
endHour: 0,
|
||||||
|
endMin: 0,
|
||||||
|
role: 0xff,
|
||||||
|
password
|
||||||
|
})
|
||||||
|
if(addUserCode !== 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
this.backAndToast('添加失败,请重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = {
|
||||||
|
lockAlias: this.name,
|
||||||
|
lockInfo: {
|
||||||
|
...this.currentLockInfo.lockConfig,
|
||||||
|
adminPwd: password
|
||||||
|
},
|
||||||
|
bluetooth: {
|
||||||
|
bluetoothDeviceName: this.currentLockInfo.name,
|
||||||
|
bluetoothDeviceId: this.currentLockInfo.deviceId,
|
||||||
|
publicKey: this.currentLockInfo.publicKey,
|
||||||
|
privateKey: this.currentLockInfo.commKey,
|
||||||
|
signKey: this.currentLockInfo.signKey,
|
||||||
|
},
|
||||||
|
lockUserNo: this.currentLockInfo.lockUserNo,
|
||||||
|
pwdTimestamp: this.currentLockInfo.pwdTimestamp,
|
||||||
|
featureValue: this.currentLockInfo.featureValue,
|
||||||
|
featureSettingValue: this.currentLockInfo.featureSettingValue,
|
||||||
|
featureSettingParams: this.currentLockInfo.featureSettingParams
|
||||||
|
}
|
||||||
|
if(this.currentLockInfo.position) {
|
||||||
|
params.position = {
|
||||||
|
latitude: this.currentLockInfo.position.latitude,
|
||||||
|
longitude: this.currentLockInfo.position.longitude,
|
||||||
|
province: this.currentLockInfo.position.province,
|
||||||
|
city: this.currentLockInfo.position.city,
|
||||||
|
district: this.currentLockInfo.position.district,
|
||||||
|
country: this.currentLockInfo.position.country,
|
||||||
|
township: this.currentLockInfo.position.township,
|
||||||
|
address: this.currentLockInfo.position.address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { code, message } = await bindLockAdmin(params)
|
||||||
|
console.log('添加锁返回', code, message)
|
||||||
|
if(code === 0) {
|
||||||
|
this.updateLockSearch({
|
||||||
|
...this.lockSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
this.getLockList(this.lockSearch)
|
||||||
|
uni.hideLoading()
|
||||||
|
this.backAndToast('添加成功')
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.text {
|
||||||
|
color: #2b2a28;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
font-size: 34rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
border-radius: 16rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-left: 35rpx;
|
||||||
|
margin-top: 24rpx;
|
||||||
|
height: 108rpx;
|
||||||
|
width: 616rpx;
|
||||||
|
padding-left: 32rpx;
|
||||||
|
padding-right: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-placeholder {
|
||||||
|
height: 108rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 108rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin-top: 160rpx;
|
||||||
|
margin-left: 35rpx;
|
||||||
|
width: 680rpx;
|
||||||
|
height: 96rpx;
|
||||||
|
background: #63b8af;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
line-height: 96rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
237
pages/createKey/createKey.vue
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="tabs">
|
||||||
|
<up-tabs :list="tabs" lineWidth="40rpx" lineHeight="5rpx" :current="currnetIndex" lineColor="#63b8af"
|
||||||
|
@click="clickTab" :inactiveStyle="{color:'#a3a3a3', fontSize: '32rpx', fontWeight: 'bold'}"
|
||||||
|
:activeStyle="{color:'#63b8af', fontSize: '32rpx', fontWeight: 'bold'}">
|
||||||
|
</up-tabs>
|
||||||
|
</view>
|
||||||
|
<swiper :style="{height: deviceInfo.screenHeight - deviceInfo.safeArea.top - 44 + 'px'}" v-if="deviceInfo"
|
||||||
|
:list="tabs" :autoplay="false"
|
||||||
|
:circular="true" :current="currnetIndex" @change="changeSwiper">
|
||||||
|
<swiper-item>
|
||||||
|
<LockInput :value="permanentAccount" title="接收者账号" placeholder="请输入手机号或邮箱"
|
||||||
|
@changeInput="changePermanentAccountInput"></LockInput>
|
||||||
|
<LockInput :value="permanentName" title="钥匙名称" placeholder="请输入钥匙名称"
|
||||||
|
@changeInput="changePermanentNmaeInput"></LockInput>
|
||||||
|
<view class="text">接收者可使用此小程序开关锁</view>
|
||||||
|
<view class="button" @click="createKey('permanent')">发送钥匙</view>
|
||||||
|
</swiper-item>
|
||||||
|
<swiper-item :style="{height: deviceInfo.windowHeight - 44 + 'px'}">
|
||||||
|
<LockInput :value="temporaryAccount" title="接收者账号" placeholder="请输入手机号或邮箱"
|
||||||
|
@changeInput="changeTemporaryAccountInput"></LockInput>
|
||||||
|
<LockInput :value="temporaryName" title="钥匙名称" placeholder="请输入钥匙名称"
|
||||||
|
@changeInput="changeTemporaryNameInput"></LockInput>
|
||||||
|
<view style="margin-top: 20rpx">
|
||||||
|
<LockDatetimePicker title="生效时间" :value="temporaryValidTime" :minDate="minDate"
|
||||||
|
placeholder="请选择失效时间" @changeTime="changeTemporaryValidTime"></LockDatetimePicker>
|
||||||
|
<LockDatetimePicker title="失效时间" :value="temporaryInvalidTime" :minDate="minDate"
|
||||||
|
placeholder="请选择失效时间" @changeTime="changeTemporaryInvalidTime"></LockDatetimePicker>
|
||||||
|
</view>
|
||||||
|
<view class="text">接收者在有效期内可以不限次数使用</view>
|
||||||
|
<view class="button" @click="createKey('temporary')">发送钥匙</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import LockInput from '@/components/LockInput/LockInput.vue'
|
||||||
|
import LockDatetimePicker from '@/components/LockDatetimePicker/LockDatetimePicker.vue'
|
||||||
|
import { createPsaawordRequest } from '@/api/keyboardPwd'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { test } from 'uview-plus'
|
||||||
|
import { createKeyRequest } from '@/api/key'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tabs: [{
|
||||||
|
name: '永久'
|
||||||
|
}, {
|
||||||
|
name: '限时'
|
||||||
|
}],
|
||||||
|
permanentName: '',
|
||||||
|
permanentAccount: '',
|
||||||
|
temporaryName: '',
|
||||||
|
temporaryAccount: '',
|
||||||
|
temporaryValidTime: Number(new Date()),
|
||||||
|
temporaryInvalidTime: Number(new Date()),
|
||||||
|
minDate: Number(new Date()),
|
||||||
|
currnetIndex: 0,
|
||||||
|
deviceInfo: null,
|
||||||
|
pending: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
LockInput,
|
||||||
|
LockDatetimePicker
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo']),
|
||||||
|
...mapState(useLockStore, ['keySearch']),
|
||||||
|
},
|
||||||
|
async onLoad () {
|
||||||
|
this.deviceInfo = await this.getDeviceInfo()
|
||||||
|
this.temporaryInvalidTime = this.setTime()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBasicStore, ['getDeviceInfo', 'backAndToast']),
|
||||||
|
...mapActions(useLockStore, ['getKeyList', 'updateKeySearch']),
|
||||||
|
setTime () {
|
||||||
|
const now = new Date()
|
||||||
|
now.setMinutes(0, 0, 0)
|
||||||
|
now.setDate(now.getDate() + 3)
|
||||||
|
|
||||||
|
return now.getTime()
|
||||||
|
},
|
||||||
|
async createKey (type, createUser = false) {
|
||||||
|
|
||||||
|
if ((type === 'temporary' && !(test.email(this.temporaryAccount) || test.mobile(this.temporaryAccount))) ||
|
||||||
|
(type === 'permanent' && !(test.email(this.permanentAccount) || test.mobile(this.permanentAccount)))) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入格式正确的手机号或邮箱',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type === 'temporary' && this.temporaryName === '') || (type === 'permanent' && this.permanentName === '')) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '名称不能为空',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type === 'temporary' && this.temporaryValidTime >= this.temporaryInvalidTime) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '失效时间必须大于生效时间',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.pending) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.pending = true
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
faceAuthentication: '2',
|
||||||
|
isRemoteUnlock: '2',
|
||||||
|
lockId: this.currentLockInfo.lockId,
|
||||||
|
keyRight: '0',
|
||||||
|
remarks: '',
|
||||||
|
countryCode: '86',
|
||||||
|
createUser: '0'
|
||||||
|
}
|
||||||
|
if(createUser) {
|
||||||
|
params.createUser = '1'
|
||||||
|
params.usernameType = test.mobile(this.temporaryAccount) ? '1' : '2'
|
||||||
|
}
|
||||||
|
if (type === 'temporary') {
|
||||||
|
params.keyNameForAdmin = this.temporaryName
|
||||||
|
params.endDate = this.temporaryInvalidTime.toString()
|
||||||
|
params.keyType = '2'
|
||||||
|
params.receiverUsername = this.temporaryAccount
|
||||||
|
params.startDate = this.temporaryValidTime.toString()
|
||||||
|
} else {
|
||||||
|
params.keyNameForAdmin = this.permanentName
|
||||||
|
params.startDate = new Date().getTime().toString()
|
||||||
|
params.endDate = '0'
|
||||||
|
params.keyType = '1'
|
||||||
|
params.receiverUsername = this.permanentAccount
|
||||||
|
}
|
||||||
|
const { code, message } = await createKeyRequest(params)
|
||||||
|
if (code === 0) {
|
||||||
|
this.updateKeySearch({
|
||||||
|
...this.keySearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
this.getKeyList(this.keySearch)
|
||||||
|
this.backAndToast('钥匙已发送')
|
||||||
|
} else if(code === 425) {
|
||||||
|
this.pending = false
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: `是否发送电子钥匙给未注册账号\n${ params.receiverUsername }`,
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
await this.createKey(type, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.pending = false
|
||||||
|
},
|
||||||
|
changePermanentAccountInput (e) {
|
||||||
|
this.permanentAccount = e
|
||||||
|
},
|
||||||
|
changePermanentNmaeInput (e) {
|
||||||
|
this.permanentName = e
|
||||||
|
},
|
||||||
|
changeTemporaryNameInput (e) {
|
||||||
|
this.temporaryName = e
|
||||||
|
},
|
||||||
|
changeTemporaryAccountInput (e) {
|
||||||
|
this.temporaryAccount = e
|
||||||
|
},
|
||||||
|
changeTemporaryValidTime (e) {
|
||||||
|
this.temporaryValidTime = e
|
||||||
|
},
|
||||||
|
changeTemporaryInvalidTime (e) {
|
||||||
|
this.temporaryInvalidTime = e
|
||||||
|
},
|
||||||
|
clickTab (data) {
|
||||||
|
this.currnetIndex = data.index
|
||||||
|
},
|
||||||
|
changeSwiper (e) {
|
||||||
|
this.currnetIndex = e.detail.current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-top: 40rpx;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
color: #262626;
|
||||||
|
font-size: 26rpx;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
border-radius: 64rpx;
|
||||||
|
width: 686rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #63b8af;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
200
pages/createPassword/createPassword.vue
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="tabs">
|
||||||
|
<up-tabs :list="tabs" lineWidth="40rpx" lineHeight="5rpx" :current="currnetIndex" lineColor="#63b8af"
|
||||||
|
@click="clickTab" :inactiveStyle="{color:'#a3a3a3', fontSize: '32rpx', fontWeight: 'bold'}"
|
||||||
|
:activeStyle="{color:'#63b8af', fontSize: '32rpx', fontWeight: 'bold'}">
|
||||||
|
</up-tabs>
|
||||||
|
</view>
|
||||||
|
<swiper :style="{height: deviceInfo.screenHeight - deviceInfo.safeArea.top - 44 + 'px'}" v-if="deviceInfo"
|
||||||
|
:list="tabs" :autoplay="false"
|
||||||
|
:circular="true" :current="currnetIndex" @change="changeSwiper">
|
||||||
|
<swiper-item>
|
||||||
|
<LockInput :value="permanentName" title="名称" placeholder="给密码命名"
|
||||||
|
@changeInput="changePermanentInput"></LockInput>
|
||||||
|
<view class="text">{{ text }}</view>
|
||||||
|
<view class="button" @click="createPassword('permanent')">获取密码</view>
|
||||||
|
</swiper-item>
|
||||||
|
<swiper-item :style="{height: deviceInfo.windowHeight - 44 + 'px'}">
|
||||||
|
<LockInput :value="temporaryName" title="名称" placeholder="给密码命名"
|
||||||
|
@changeInput="changeTemporaryInput"></LockInput>
|
||||||
|
<view style="margin-top: 20rpx">
|
||||||
|
<LockDatetimePicker title="失效时间" :value="temporaryTime" :minDate="minDate"
|
||||||
|
placeholder="请选择失效时间" @changeTime="changeTemporaryTime"></LockDatetimePicker>
|
||||||
|
</view>
|
||||||
|
<view class="text">{{ text }}</view>
|
||||||
|
<view class="button" @click="createPassword('temporary')">获取密码</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import LockInput from '@/components/LockInput/LockInput.vue'
|
||||||
|
import LockDatetimePicker from '@/components/LockDatetimePicker/LockDatetimePicker.vue'
|
||||||
|
import { createPsaawordRequest } from '@/api/keyboardPwd'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tabs: [{
|
||||||
|
name: '永久'
|
||||||
|
}, {
|
||||||
|
name: '限时'
|
||||||
|
}],
|
||||||
|
permanentName: '',
|
||||||
|
temporaryName: '',
|
||||||
|
temporaryTime: Number(new Date()),
|
||||||
|
minDate: Number(new Date()),
|
||||||
|
currnetIndex: 0,
|
||||||
|
deviceInfo: null,
|
||||||
|
pending: false,
|
||||||
|
text: '密码生成后,请在当日23:59前使用一次进行激活,否则过点后未激活则失效。密码激活后,有效期内不限次数使用。'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
LockInput,
|
||||||
|
LockDatetimePicker
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo']),
|
||||||
|
...mapState(useLockStore, ['passwordSearch']),
|
||||||
|
},
|
||||||
|
async onLoad() {
|
||||||
|
this.deviceInfo = await this.getDeviceInfo()
|
||||||
|
this.temporaryTime = this.setTime()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBasicStore, ['getDeviceInfo', 'backAndToast']),
|
||||||
|
...mapActions(useLockStore, ['getPasswordList', 'updatePasswordSearch']),
|
||||||
|
setTime() {
|
||||||
|
const now = new Date()
|
||||||
|
now.setMinutes(0, 0, 0)
|
||||||
|
now.setDate(now.getDate() + 1)
|
||||||
|
|
||||||
|
return now.getTime()
|
||||||
|
},
|
||||||
|
async createPassword(type) {
|
||||||
|
const that = this
|
||||||
|
if((type === 'temporary' && this.temporaryName === '') || (type === 'permanent' && this.permanentName === '')) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '名称不能为空',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.pending) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.pending = true
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
lockId: this.currentLockInfo.lockId,
|
||||||
|
isCoerced: 2,
|
||||||
|
pwdRight: 0
|
||||||
|
}
|
||||||
|
if(type === 'temporary') {
|
||||||
|
params.keyboardPwdName = this.temporaryName
|
||||||
|
params.keyboardPwdType = 3
|
||||||
|
params.startDate = new Date().getTime()
|
||||||
|
params.endDate = this.temporaryTime
|
||||||
|
params.hoursStart = 0
|
||||||
|
params.hoursEnd = 0
|
||||||
|
} else {
|
||||||
|
params.startDate = 0
|
||||||
|
params.endDate = 0
|
||||||
|
params.keyboardPwdName = this.permanentName
|
||||||
|
params.keyboardPwdType = 2
|
||||||
|
params.hoursStart = 0
|
||||||
|
params.hoursEnd = 0
|
||||||
|
}
|
||||||
|
const { code, data, message } = await createPsaawordRequest(params)
|
||||||
|
if(code === 0) {
|
||||||
|
this.updatePasswordSearch({
|
||||||
|
...this.passwordSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
this.getPasswordList(this.passwordSearch)
|
||||||
|
uni.showModal({
|
||||||
|
title: '密码生成成功',
|
||||||
|
content: `密码:${data.keyboardPwd}`,
|
||||||
|
cancelText: '复制',
|
||||||
|
success: (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
uni.navigateBack()
|
||||||
|
} else {
|
||||||
|
uni.setClipboardData({
|
||||||
|
data: data.keyboardPwd,
|
||||||
|
success: () => {
|
||||||
|
that.backAndToast('复制成功')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.pending = false
|
||||||
|
},
|
||||||
|
changePermanentInput(e) {
|
||||||
|
this.permanentName = e
|
||||||
|
},
|
||||||
|
changeTemporaryInput(e) {
|
||||||
|
this.temporaryName = e
|
||||||
|
},
|
||||||
|
changeTemporaryTime(e) {
|
||||||
|
this.temporaryTime = e
|
||||||
|
},
|
||||||
|
clickTab(data) {
|
||||||
|
this.currnetIndex = data.index
|
||||||
|
},
|
||||||
|
changeSwiper(e) {
|
||||||
|
this.currnetIndex = e.detail.current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-top: 40rpx;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
color: #262626;
|
||||||
|
font-size: 26rpx;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
border-radius: 64rpx;
|
||||||
|
width: 686rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #63b8af;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -2,17 +2,18 @@
|
|||||||
<view>
|
<view>
|
||||||
<view v-if="!penging">
|
<view v-if="!penging">
|
||||||
<view v-if="isLogin">
|
<view v-if="isLogin">
|
||||||
<scroll-view scroll-y="true" :style="{ height: 'calc(100vh)' }" lower-threshold="100"
|
<scroll-view v-if="deviceInfo" scroll-y="true" :style="{ height: deviceInfo.windowHeight + 'px' }"
|
||||||
@refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
|
lower-threshold="100" @refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
|
||||||
:refresher-triggered="refresherTriggered">
|
:refresher-triggered="refresherTriggered">
|
||||||
<view class="search">
|
<view class="search">
|
||||||
<up-search :searchIconSize="48" :inputStyle="{ fontSize: '32rpx' }" @focus="getFocus" @blur="getBlur"
|
<up-search :searchIconSize="48" :inputStyle="{ fontSize: '32rpx' }" @focus="getFocus" @blur="getBlur"
|
||||||
:height="80" placeholder="搜索" :clearabled="false" @change="changeSearch"
|
:height="80" placeholder="搜索" :clearabled="false" @change="changeSearch"
|
||||||
v-model="search.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
|
v-model="lockSearch.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
|
||||||
</view>
|
</view>
|
||||||
<view class="lock-list" v-if="!penging">
|
<view class="lock-list" v-if="!penging">
|
||||||
<view v-if="lockList.length === 0 && search.searchStr === '' && !focus">
|
<view v-if="lockList.length === 0 && lockSearch.searchStr === '' && !focus">
|
||||||
<image src="/static/images/icon_add.png" mode="aspectFill" class="button-add-big" @click="toSearchDevice"></image>
|
<image src="/static/images/icon_add_round.png" mode="aspectFill" class="button-add-big"
|
||||||
|
@click="toSearchDevice"></image>
|
||||||
<view class="text">填加锁时,手机必须在锁旁边</view>
|
<view class="text">填加锁时,手机必须在锁旁边</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-else>
|
<view v-else>
|
||||||
@ -32,9 +33,9 @@
|
|||||||
<view>{{getRole(lock.userType)}}</view>
|
<view>{{getRole(lock.userType)}}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="lock-name">{{lock.lockName}}</view>
|
<view class="lock-name">{{lock.lockAlias}}</view>
|
||||||
<view class="lock-time">
|
<view class="lock-time">
|
||||||
<view v-if="lock.keyType !== 1" style="font-size: 32rpx">{{ getTimeLimit(lock.keyType) }}</view>
|
<view v-if="lock.keyType === 1" style="font-size: 32rpx">{{ getTimeLimit(lock.keyType) }}</view>
|
||||||
<view v-else>
|
<view v-else>
|
||||||
<view>{{ timeFormat(lock.startDate, 'yyyy-mm-dd h:M') }}</view>
|
<view>{{ timeFormat(lock.startDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
<view>{{ timeFormat(lock.endDate, 'yyyy-mm-dd h:M ') + getTimeLimit(lock.keyType) }}</view>
|
<view>{{ timeFormat(lock.endDate, 'yyyy-mm-dd h:M ') + getTimeLimit(lock.keyType) }}</view>
|
||||||
@ -45,19 +46,23 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<image v-if="lockList.length !== 0" src="/static/images/icon_add.png" mode="aspectFill"
|
<image v-if="lockList.length !== 0" src="/static/images/icon_add_round.png" mode="aspectFill"
|
||||||
class="button-add" @click="toSearchDevice"></image>
|
class="button-add" @click="toSearchDevice"></image>
|
||||||
</view>
|
</view>
|
||||||
<view v-else>
|
<view v-else>
|
||||||
<view class="button-login" @click="login">登录</view>
|
<view class="tips">因智能门锁与账号绑定,登录为手机号登录</view>
|
||||||
|
<label for="phone">
|
||||||
|
<view class="button-login">登录</view>
|
||||||
|
</label>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<button open-type="getPhoneNumber" style="display:none" id="phone" @getphonenumber="getphonenumber"></button>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { timeFormat } from 'uview-plus'
|
import { timeFormat } from 'uview-plus'
|
||||||
import { getUserInfoRequest } from '@/api/user'
|
import { getUserInfoRequest, loginRequest } from '@/api/user'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { useLockStore } from '@/stores/lock'
|
import { useLockStore } from '@/stores/lock'
|
||||||
import { useBluetoothStore } from '@/stores/bluetooth'
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
@ -67,68 +72,130 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
search: {
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 50,
|
|
||||||
searchStr: ''
|
|
||||||
},
|
|
||||||
refresherTriggered: false,
|
refresherTriggered: false,
|
||||||
focus: false,
|
focus: false,
|
||||||
penging: true
|
penging: true,
|
||||||
|
deviceInfo: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useUserStore, ['userInfo', 'isLogin']),
|
...mapState(useUserStore, ['userInfo', 'isLogin']),
|
||||||
...mapState(useLockStore, ['lockList', 'lockTotal']),
|
...mapState(useLockStore, ['lockList', 'lockTotal', 'lockSearch']),
|
||||||
...mapState(useBluetoothStore, ['bluetoothStatus', 'isInitBluetooth']),
|
...mapState(useBluetoothStore, ['bluetoothStatus', 'isInitBluetooth']),
|
||||||
},
|
},
|
||||||
async onLoad() {
|
async onLoad() {
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
title: '加载中'
|
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')
|
const token = uni.getStorageSync('token')
|
||||||
if(token) {
|
if(token) {
|
||||||
this.updateLoginStatus(true)
|
this.getLockList(this.lockSearch)
|
||||||
const code = await this.getUserInfo()
|
await this.getUserInfo()
|
||||||
if(code === 0) {
|
} else {
|
||||||
await this.getLockList(this.search)
|
await this.homeLogin()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.penging = false
|
this.penging = false
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
timeFormat,
|
timeFormat,
|
||||||
...mapActions(useUserStore, ['updateUserInfo', 'updateLoginStatus', 'login']),
|
...mapActions(useUserStore, ['updateUserInfo', 'updateLoginStatus', 'phoneLogin', 'getUserInfo']),
|
||||||
...mapActions(useLockStore, ['getLockList', 'getRole', 'getTimeLimit']),
|
...mapActions(useLockStore, ['getLockList', 'getRole', 'getTimeLimit', 'updateLockSearch']),
|
||||||
...mapActions(useBluetoothStore, ['getBluetoothStatus', 'initAndListenBluetooth', 'updateCurrentLockInfo', 'checkSetting']),
|
...mapActions(useBluetoothStore, ['getBluetoothStatus', 'initAndListenBluetooth', 'updateCurrentLockInfo',
|
||||||
...mapActions(useBasicStore, ['routeJump']),
|
'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() {
|
async nextPage() {
|
||||||
if(this.lockList.length < this.lockTotal) {
|
if(this.lockList.length < this.lockTotal) {
|
||||||
this.search.pageNo++
|
const sreach = {
|
||||||
const { code } = await this.getLockList(this.search)
|
...this.lockSearch,
|
||||||
|
pageNo: this.lockSearch.pageNo + 1
|
||||||
|
}
|
||||||
|
const { code } = await this.getLockList(search)
|
||||||
if(code !== 0) {
|
if(code !== 0) {
|
||||||
this.search.pageNo--
|
this.updateLockSearch(search)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async refresherList() {
|
async refresherList() {
|
||||||
this.refresherTriggered = true
|
this.refresherTriggered = true
|
||||||
this.search.pageNo = 1
|
this.updateLockSearch({
|
||||||
await this.getLockList(this.search)
|
...this.lockSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
await this.getLockList(this.lockSearch)
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
this.refresherTriggered = false
|
this.refresherTriggered = false
|
||||||
},
|
},
|
||||||
async changeSearch(data) {
|
async changeSearch(data) {
|
||||||
this.search.searchStr = data
|
this.updateLockSearch({
|
||||||
await this.getLockList(this.search)
|
...this.lockSearch,
|
||||||
},
|
searchStr: data
|
||||||
async getUserInfo() {
|
})
|
||||||
const { code, data } = await getUserInfoRequest()
|
await this.getLockList(this.lockSearch)
|
||||||
if(code === 0) {
|
|
||||||
this.updateUserInfo(data)
|
|
||||||
console.log(this.userInfo)
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
},
|
},
|
||||||
getFocus() {
|
getFocus() {
|
||||||
this.focus = true
|
this.focus = true
|
||||||
@ -163,7 +230,16 @@
|
|||||||
result = await this.initAndListenBluetooth()
|
result = await this.initAndListenBluetooth()
|
||||||
}
|
}
|
||||||
if(result) {
|
if(result) {
|
||||||
this.updateCurrentLockInfo(lock)
|
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({
|
this.routeJump({
|
||||||
name: 'lockDetail'
|
name: 'lockDetail'
|
||||||
})
|
})
|
||||||
@ -189,7 +265,6 @@ page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button-login {
|
.button-login {
|
||||||
margin-top: 40vh;
|
|
||||||
border-radius: 46rpx;
|
border-radius: 46rpx;
|
||||||
width: 650rpx;
|
width: 650rpx;
|
||||||
height: 120rpx;
|
height: 120rpx;
|
||||||
@ -314,4 +389,12 @@ page {
|
|||||||
margin-top: 32rpx;
|
margin-top: 32rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
margin-top: 40vh;
|
||||||
|
padding: 32rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,205 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="content">
|
|
||||||
<view v-if="!showConnect">
|
|
||||||
<button class="button" v-if="showAdd" @click="getList">添加设备</button>
|
|
||||||
<button class="button" v-else @click="stopGetList">停止搜索</button>
|
|
||||||
<view class="device-list" v-for="(item, index) in deviceList" :key="item.deviceId" @click="connect(item)">{{item.name}}</view>
|
|
||||||
</view>
|
|
||||||
<view v-else>
|
|
||||||
<button class="button" @click="bindUser">添加用户</button>
|
|
||||||
<button class="button" @click="openDoorOperate">开门</button>
|
|
||||||
<button class="button" @click="closeDoorOperate">关门</button>
|
|
||||||
<button class="button" @click="reset">恢复出厂设置</button>
|
|
||||||
<button class="button" @click="getLockStatusResult">获取锁状态</button>
|
|
||||||
<button class="button" @click="resetPassword">重置锁密码</button>
|
|
||||||
<button class="button" @click="setPassword">设置密码</button>
|
|
||||||
<button class="button" @click="deletePassword">删除密码</button>
|
|
||||||
<view>名称:{{currentLockInfo.name}}</view>
|
|
||||||
<view>设备Id:{{currentLockInfo.deviceId}}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useBluetoothStore } from '@/stores/bluetooth'
|
|
||||||
import { mapState, mapActions } from 'pinia'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showAdd: true,
|
|
||||||
showConnect: false,
|
|
||||||
keyId: '0',
|
|
||||||
authUid: '294',
|
|
||||||
onlineToken: '0'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapState(useBluetoothStore, ['deviceList', 'currentLockInfo'])
|
|
||||||
},
|
|
||||||
onLoad () {},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useBluetoothStore, ['getBluetoothDevices', 'stopGetBluetoothDevices', 'updateCurrentLockInfo',
|
|
||||||
'connectBluetoothDevice', 'getPublicKey', 'getCommKey', 'getLockStatus', 'addLockUser', 'timestampToArray',
|
|
||||||
'openDoor', 'resetDevice', 'resetLockPassword', 'setLockPassword']),
|
|
||||||
async deletePassword() {
|
|
||||||
const timestamp = parseInt(new Date().getTime() / 1000)
|
|
||||||
const data = await this.setLockPassword({
|
|
||||||
keyId: this.keyId,
|
|
||||||
uid: this.authUid,
|
|
||||||
pwdNo: 2,
|
|
||||||
operate: 2,
|
|
||||||
isAdmin: 1,
|
|
||||||
pwd: '000000',
|
|
||||||
userCountLimit: 0,
|
|
||||||
startTime: timestamp,
|
|
||||||
endTime: timestamp
|
|
||||||
})
|
|
||||||
console.log('设置密码返回', data)
|
|
||||||
},
|
|
||||||
async setPassword() {
|
|
||||||
const timestamp = parseInt(new Date().getTime() / 1000)
|
|
||||||
const endTimestamp = timestamp + 3600 * 24 * 365
|
|
||||||
const data = await this.setLockPassword({
|
|
||||||
keyId: this.keyId,
|
|
||||||
uid: this.authUid,
|
|
||||||
pwdNo: 1,
|
|
||||||
operate: 0,
|
|
||||||
isAdmin: 1,
|
|
||||||
pwd: '000000',
|
|
||||||
userCountLimit: 0xffff,
|
|
||||||
startTime: timestamp,
|
|
||||||
endTime: endTimestamp
|
|
||||||
})
|
|
||||||
console.log('设置密码返回', data)
|
|
||||||
},
|
|
||||||
async resetPassword() {
|
|
||||||
const { code } = await this.resetLockPassword({
|
|
||||||
uid: this.authUid,
|
|
||||||
keyId: this.keyId
|
|
||||||
})
|
|
||||||
console.log('重置密码返回', code)
|
|
||||||
},
|
|
||||||
async openDoorOperate() {
|
|
||||||
const { code } = await this.openDoor({
|
|
||||||
name: this.currentLockInfo.name,
|
|
||||||
uid: this.authUid,
|
|
||||||
openMode: 0,
|
|
||||||
openTime: parseInt(new Date().getTime() / 1000),
|
|
||||||
onlineToken: this.onlineToken
|
|
||||||
})
|
|
||||||
console.log('开门返回', code)
|
|
||||||
},
|
|
||||||
async closeDoorOperate() {
|
|
||||||
const { code } = await this.openDoor({
|
|
||||||
name: this.currentLockInfo.name,
|
|
||||||
uid: this.authUid,
|
|
||||||
openMode: 32,
|
|
||||||
openTime: parseInt(new Date().getTime() / 1000),
|
|
||||||
onlineToken: this.onlineToken
|
|
||||||
})
|
|
||||||
console.log('关门返回', code)
|
|
||||||
},
|
|
||||||
async reset() {
|
|
||||||
const { code } = await this.resetDevice({
|
|
||||||
name: this.currentLockInfo.name,
|
|
||||||
authUid: this.authUid,
|
|
||||||
keyId: this.keyId
|
|
||||||
})
|
|
||||||
console.log('恢复出厂设置返回', code)
|
|
||||||
},
|
|
||||||
getList() {
|
|
||||||
this.getBluetoothDevices()
|
|
||||||
this.showAdd = false
|
|
||||||
},
|
|
||||||
stopGetList() {
|
|
||||||
this.stopGetBluetoothDevices()
|
|
||||||
this.showAdd = true
|
|
||||||
},
|
|
||||||
async connect(item) {
|
|
||||||
this.updateCurrentLockInfo({
|
|
||||||
name: item.name,
|
|
||||||
deviceId: item.deviceId
|
|
||||||
})
|
|
||||||
const result = await this.connectBluetoothDevice()
|
|
||||||
if(result) {
|
|
||||||
this.showConnect = true
|
|
||||||
this.stopGetBluetoothDevices()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async bindUser() {
|
|
||||||
const { code } = await this.getPublicKey(this.currentLockInfo.name)
|
|
||||||
console.log('获取公钥返回', code)
|
|
||||||
if(code !== 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const { code: getCommKeyCode } = await this.getCommKey(this.currentLockInfo.name, this.keyId, this.authUid,
|
|
||||||
parseInt(new Date().getTime() / 1000))
|
|
||||||
console.log('获取私钥返回', getCommKeyCode)
|
|
||||||
if(getCommKeyCode !== 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const timestamp = parseInt(new Date().getTime() / 1000)
|
|
||||||
const { code: addUserCode } = await this.addLockUser({
|
|
||||||
name: this.currentLockInfo.name,
|
|
||||||
keyId: this.keyId,
|
|
||||||
authUid: this.authUid,
|
|
||||||
uid: this.authUid,
|
|
||||||
publicKey: this.currentLockInfo.publicKey,
|
|
||||||
commKey: this.currentLockInfo.commKey,
|
|
||||||
openMode: 1,
|
|
||||||
keyType: 1,
|
|
||||||
startDate: timestamp,
|
|
||||||
expireDate: 0xffffffff,
|
|
||||||
useCountLimit: 0xffff,
|
|
||||||
isRound: 0,
|
|
||||||
weekRound: 0,
|
|
||||||
startHour: 0,
|
|
||||||
startMin: 0,
|
|
||||||
endHour: 0,
|
|
||||||
endMin: 0,
|
|
||||||
role: 0xff,
|
|
||||||
password: (Math.floor(Math.random() * 900000) + 100000).toString()
|
|
||||||
})
|
|
||||||
console.log('添加用户返回', addUserCode)
|
|
||||||
},
|
|
||||||
getLockStatusResult() {
|
|
||||||
const timnestamp = parseInt(new Date().getTime() / 1000)
|
|
||||||
this.getLockStatus({
|
|
||||||
name: this.currentLockInfo.name,
|
|
||||||
uid: this.authUid,
|
|
||||||
nowTime: timnestamp,
|
|
||||||
localTime: timnestamp
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.content {
|
|
||||||
padding-top: 160rpx;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
margin-top: 40rpx;
|
|
||||||
width: 400rpx;
|
|
||||||
height: 108rpx;
|
|
||||||
line-height: 108rpx;
|
|
||||||
background: #3F536E;
|
|
||||||
color: #ffffff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-list {
|
|
||||||
margin-top: 10rpx;
|
|
||||||
height: 100rpx;
|
|
||||||
width: 500rpx;
|
|
||||||
line-height: 100rpx;
|
|
||||||
text-align: center;
|
|
||||||
border: #dd524d solid 2rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
120
pages/keyDetail/keyDetail.vue
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="item-title">名称</view>
|
||||||
|
<view class="item-content">{{ currentKeyInfo.nickname }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 2rpx">
|
||||||
|
<view class="item-title">有效期</view>
|
||||||
|
<view v-if="currentKeyInfo.keyType === 1">永久</view>
|
||||||
|
<view v-else>
|
||||||
|
<view class="item-content">{{ timeFormat(currentKeyInfo.startDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
|
<view class="item-content">{{ timeFormat(currentKeyInfo.endDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 20rpx">
|
||||||
|
<view class="item-title">接收者</view>
|
||||||
|
<view class="item-content">{{ currentKeyInfo.username }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 2rpx">
|
||||||
|
<view class="item-title">发送人</view>
|
||||||
|
<view class="item-content">{{ currentKeyInfo.senderUsername }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 2rpx">
|
||||||
|
<view class="item-title">发送时间</view>
|
||||||
|
<view class="item-content">{{ timeFormat(currentKeyInfo.sendDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="button" @click="deleteKey">删除钥匙</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { timeFormat } from 'uview-plus'
|
||||||
|
import { deleteKeyRequest } from '@/api/key'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useLockStore, ['currentKeyInfo', 'keySearch']),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
timeFormat,
|
||||||
|
...mapActions(useLockStore, ['updateKeySearch', 'getKeyList']),
|
||||||
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
|
async deleteKey () {
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该钥匙',
|
||||||
|
async success(res) {
|
||||||
|
if(res.confirm) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '删除中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const { code: requestCode, message } = await deleteKeyRequest({
|
||||||
|
keyId: that.currentKeyInfo.keyId
|
||||||
|
})
|
||||||
|
if(requestCode === 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
that.updateKeySearch({
|
||||||
|
...that.keySearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
await that.getKeyList(that.keySearch)
|
||||||
|
that.backAndToast('删除成功')
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.item {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin: 32rpx;
|
||||||
|
width: 686rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #df282d;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
313
pages/keyList/keyList.vue
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<scroll-view v-if="deviceInfo" scroll-y="true" :style="{height: deviceInfo.screenHeight - deviceInfo.safeArea.top + 'px'}" lower-threshold="100"
|
||||||
|
@refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
|
||||||
|
:refresher-triggered="refresherTriggered">
|
||||||
|
<view class="search">
|
||||||
|
<up-search shape="square" :searchIconSize="48" :inputStyle="{ fontSize: '32rpx' }" :height="80" placeholder="搜索"
|
||||||
|
:clearabled="false" @change="changeSearch"
|
||||||
|
v-model="keySearch.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
|
||||||
|
</view>
|
||||||
|
<view style="padding: 32rpx 0 calc(env(safe-area-inset-bottom) + 250rpx) 0">
|
||||||
|
<view v-if="keyList.length === 0 && requestFinished">
|
||||||
|
<image class="empty-list" src="/static/images/background_empty_list.png" mode="aspectFill"></image>
|
||||||
|
<view class="empty-list-text">暂无数据</view>
|
||||||
|
</view>
|
||||||
|
<view v-else>
|
||||||
|
<up-swipe-action>
|
||||||
|
<up-swipe-action-item ref="swipeItem" :options="options" v-for="(key, index) in keyList"
|
||||||
|
:key="key.keyboardPwdId" :threshold="50" @click="deleteKey(key)">
|
||||||
|
<view class="key" @click="toKeyDetail(key)">
|
||||||
|
<image class="key-left" :src="key.headUrl" mode="aspectFill"></image>
|
||||||
|
<view class="key-right">
|
||||||
|
<view style="display: flex; align-items: center">
|
||||||
|
<view class="key-right-top">{{ key.keyName }}</view>
|
||||||
|
<view class="key-status" :style="{ color: (key.keyStatus === 110401) ? '#63b8af' : '#df282d' }">
|
||||||
|
{{ getKeyStatus(key.keyStatus) }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="key-right-bottom">{{ key.timeText }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="line"></view>
|
||||||
|
</up-swipe-action-item>
|
||||||
|
</up-swipe-action>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view class="button">
|
||||||
|
<view class="button-reset" @click="resetKey">重置钥匙</view>
|
||||||
|
<view class="button-create" @click="toCreateKey">发送钥匙</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { deletePsaawordRequest, resetPsaawordListRequest } from '@/api/keyboardPwd'
|
||||||
|
import { deleteKeyRequest, resetKeyRequest } from '@/api/key'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
deviceInfo: null,
|
||||||
|
refresherTriggered: false,
|
||||||
|
requestFinished: false,
|
||||||
|
options: [{
|
||||||
|
text: '删除',
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#f56c6c'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useUserStore, ['userInfo']),
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
|
||||||
|
...mapState(useLockStore, ['keyTotal', 'keyList', 'keySearch']),
|
||||||
|
},
|
||||||
|
async onLoad() {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
this.deviceInfo = await this.getDeviceInfo()
|
||||||
|
this.updateKeySearch({
|
||||||
|
...this.keySearch,
|
||||||
|
lockId: this.currentLockInfo.lockId
|
||||||
|
})
|
||||||
|
const { code, meesage } = await this.getKeyList(this.keySearch)
|
||||||
|
this.requestFinished = true
|
||||||
|
uni.hideLoading()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBasicStore, ['routeJump', 'getDeviceInfo']),
|
||||||
|
...mapActions(useLockStore, ['getKeyList', 'updateCurrentKeyInfo', 'updateKeySearch', 'getKeyStatus']),
|
||||||
|
toKeyDetail(key) {
|
||||||
|
this.updateCurrentKeyInfo(key)
|
||||||
|
this.routeJump({
|
||||||
|
name: 'keyDetail'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async deleteKey(data) {
|
||||||
|
const key = data
|
||||||
|
const that = this
|
||||||
|
let index = this.keyList.findIndex(item => item.keyId === key.keyId)
|
||||||
|
that.$refs.swipeItem[index].closeHandler()
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该钥匙',
|
||||||
|
async success(res) {
|
||||||
|
if(res.confirm) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '删除中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const { code: requestCode, message } = await deleteKeyRequest({
|
||||||
|
keyId: key.keyId
|
||||||
|
})
|
||||||
|
if(requestCode === 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
that.updateKeySearch({
|
||||||
|
...that.keySearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
await that.getKeyList(that.keySearch)
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async resetKey() {
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要重置钥匙,该锁的所有钥匙都将被删除',
|
||||||
|
async success(res) {
|
||||||
|
if(res.confirm) {
|
||||||
|
const { code: requestCode, message } = await resetKeyRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId,
|
||||||
|
})
|
||||||
|
console.log('重置钥匙返回', requestCode, message)
|
||||||
|
if(requestCode === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '重置钥匙成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
that.updateKeySearch({
|
||||||
|
...that.keySearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
await that.getKeyList(that.keySearch)
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toCreateKey() {
|
||||||
|
this.routeJump({
|
||||||
|
name: 'createKey'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async refresherList() {
|
||||||
|
this.refresherTriggered = true
|
||||||
|
this.updateKeySearch({
|
||||||
|
...this.keySearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
const { code, meesage } = await this.getKeyList(this.keySearch)
|
||||||
|
if(code === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.refresherTriggered = false
|
||||||
|
},
|
||||||
|
async nextPage() {
|
||||||
|
if(this.keyTotal <= this.keySearch.pageNo * this.keySearch.pageSize) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const pageNo = this.keySearch.pageNo + 1
|
||||||
|
const params = {
|
||||||
|
...this.keySearch,
|
||||||
|
pageNo
|
||||||
|
}
|
||||||
|
const { code, meesage } = await this.getKeyList(params)
|
||||||
|
if(code === 0) {
|
||||||
|
this.updateKeySearch({
|
||||||
|
...this.keySearch,
|
||||||
|
pageNo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async changeSearch(data) {
|
||||||
|
this.updateKeySearch({
|
||||||
|
...this.keySearch,
|
||||||
|
searchStr: data
|
||||||
|
})
|
||||||
|
const { code, meesage } = await this.getKeyList(this.keySearch)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search {
|
||||||
|
margin-top: 32rpx;
|
||||||
|
width: 686rpx !important;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: fixed;
|
||||||
|
bottom: calc(env(safe-area-inset-bottom) + 48rpx);
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
.button-reset {
|
||||||
|
margin-left: 50rpx;
|
||||||
|
width: 300rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #df282d;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-create {
|
||||||
|
margin-left: 50rpx;
|
||||||
|
width: 300rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #63b8af;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.key {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
height: 120rpx;
|
||||||
|
width: 750rpx;
|
||||||
|
|
||||||
|
.key-left {
|
||||||
|
margin-left: 32rpx;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-right {
|
||||||
|
margin-left: 32rpx;
|
||||||
|
margin-right: 32rpx;
|
||||||
|
width: 574rpx;
|
||||||
|
|
||||||
|
.key-right-top {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-right-bottom {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-status {
|
||||||
|
margin-left: auto;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #63b8af;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
width: 100%;
|
||||||
|
height: 2rpx;
|
||||||
|
background: #EBEBEB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-list {
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
margin: 300rpx auto 20rpx 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-list-text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,17 +1,332 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<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="/static/images/icon_power.png" 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) }}</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.userType === 110301">
|
||||||
|
<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.userType === 110301"
|
||||||
|
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.userType === 110301"
|
||||||
|
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>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<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'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {}
|
return {
|
||||||
|
time: 0,
|
||||||
|
onlineToken: '0',
|
||||||
|
pending: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo']),
|
||||||
|
...mapState(useUserStore, ['userInfo'])
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
SwitchLoading
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: this.currentLockInfo.lockAlias
|
||||||
|
})
|
||||||
|
this.getServeTime()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useLockStore, ['getRole']),
|
||||||
|
...mapActions(useBluetoothStore, ['openDoor', 'updateServerTimestamp']),
|
||||||
|
...mapActions(useBasicStore, ['routeJump']),
|
||||||
|
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.pending) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.vibrateLong()
|
||||||
|
this.pending = true
|
||||||
|
this.$refs.loading.open()
|
||||||
|
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
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `${type === 'close' ? '关' : '开'}锁成功`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: `${type === 'close' ? '关' : '开'}锁失败,请保证在锁附近`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$refs.loading.close()
|
||||||
|
this.pending = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
|
.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: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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>
|
</style>
|
||||||
|
|||||||
@ -31,35 +31,132 @@
|
|||||||
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="button-logout" @click="logout">退出</view>
|
<view class="env" v-if="envVersion !== 'release' && env">
|
||||||
|
<view class="env-text">{{env.name}}环境 版本号:{{env.version}}+{{env.buildNumber}}</view>
|
||||||
|
<view class="env-button" @click="show=true">切换环境</view>
|
||||||
|
</view>
|
||||||
|
<label for="changePhone">
|
||||||
|
<view class="switch-account">切换账号</view>
|
||||||
|
</label>
|
||||||
</view>
|
</view>
|
||||||
<view v-else>
|
<view v-else>
|
||||||
<view class="button-login" @click="login">登录</view>
|
<view class="tips">因智能门锁与账号绑定,登录为手机号登录</view>
|
||||||
|
<label for="phone">
|
||||||
|
<view class="button-login">登录</view>
|
||||||
|
</label>
|
||||||
|
<view class="env" v-if="envVersion !== 'release' && env">
|
||||||
|
<view class="env-text">{{env.name}}环境 版本号:{{env.version}}+{{env.buildNumber}}</view>
|
||||||
|
<view class="env-button" @click="show=true">切换环境</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<button open-type="contact" id="contact"></button>
|
<button open-type="contact" style="display:none" id="contact"></button>
|
||||||
|
<button open-type="getPhoneNumber" style="display:none" id="phone" @getphonenumber="getphonenumber"></button>
|
||||||
|
<button open-type="getPhoneNumber" style="display:none" id="changePhone" @getphonenumber="changePhone"></button>
|
||||||
|
<up-action-sheet :actions="envList" :closeOnClickOverlay="true" title="切换环境" cancelText="取消" :closeOnClickAction="true"
|
||||||
|
:show="show" :safeAreaInsetBottom="true" @close="show=false" @select="selectEnv"></up-action-sheet>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useBasicStore } from '@/stores/basic'
|
import { useBasicStore } from '@/stores/basic'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
import { mapState, mapActions } from 'pinia'
|
import { mapState, mapActions } from 'pinia'
|
||||||
|
import { phoneLoginRequest } from '@/api/user'
|
||||||
|
import env from '@/config/env'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
buttonInfo: null
|
buttonInfo: null,
|
||||||
|
env: null,
|
||||||
|
envVersion: '',
|
||||||
|
envList: [],
|
||||||
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useUserStore, ['isLogin'])
|
...mapState(useUserStore, ['isLogin']),
|
||||||
|
...mapState(useLockStore, ['lockSearch'])
|
||||||
},
|
},
|
||||||
async onLoad() {
|
async onLoad() {
|
||||||
this.buttonInfo = await this.getButtonInfo()
|
this.buttonInfo = await this.getButtonInfo()
|
||||||
|
this.env = env[getApp().globalData.getEnvConfig()]
|
||||||
|
this.envVersion = getApp().globalData.envVersion
|
||||||
|
for (let key in env) {
|
||||||
|
this.envList.push({
|
||||||
|
...env[key],
|
||||||
|
key: key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
console.log(this.envList)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useBasicStore, ['getButtonInfo', 'routeJump']),
|
...mapActions(useBasicStore, ['getButtonInfo', 'routeJump']),
|
||||||
...mapActions(useUserStore, ['updateLoginStatus', 'login']),
|
...mapActions(useLockStore, ['getLockList', 'updateLockSearch']),
|
||||||
|
...mapActions(useUserStore, ['updateLoginStatus', 'phoneLogin', 'updateUserInfo', 'getUserInfo',
|
||||||
|
'checkSession']),
|
||||||
|
selectEnv(env) {
|
||||||
|
uni.setStorageSync('envVersion', env.key)
|
||||||
|
uni.removeStorageSync('token')
|
||||||
|
uni.removeStorageSync('openid')
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/home/home'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async changePhone(res) {
|
||||||
|
if(res.detail.errMsg === 'getPhoneNumber:fail user deny') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const result = await this.checkSession()
|
||||||
|
if(!result) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '登录失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const openid = uni.getStorageSync('openid')
|
||||||
|
const { code, data, message } = await phoneLoginRequest({
|
||||||
|
encryptedData: res.detail.encryptedData,
|
||||||
|
iv: res.detail.iv,
|
||||||
|
rebind: true,
|
||||||
|
openid
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
uni.setStorageSync('token', data.accessToken)
|
||||||
|
this.updateLockSearch({
|
||||||
|
...this.lockSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
this.getUserInfo()
|
||||||
|
this.getLockList(this.lockSearch)
|
||||||
|
uni.showToast({
|
||||||
|
title: '账号切换成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
toUsereInfo() {
|
toUsereInfo() {
|
||||||
this.routeJump({
|
this.routeJump({
|
||||||
name: 'userInfo'
|
name: 'userInfo'
|
||||||
@ -72,21 +169,8 @@
|
|||||||
type
|
type
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
|
||||||
logout() {
|
|
||||||
const that = this
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '确定退出登录吗?',
|
|
||||||
success: (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
uni.removeStorageSync('token')
|
|
||||||
that.updateLoginStatus(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -136,23 +220,48 @@ page {
|
|||||||
background: #EBEBEB;
|
background: #EBEBEB;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-logout {
|
.switch-account {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 46rpx;
|
border-radius: 46rpx;
|
||||||
bottom: 60rpx;
|
bottom: 60rpx;
|
||||||
width: 710rpx;
|
width: 600rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
line-height: 80rpx;
|
line-height: 80rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-left: 20rpx;
|
margin-left: 75rpx;
|
||||||
background: #ec433c;
|
background: #63b8af;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 40rpx;
|
font-size: 40rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.env {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 180rpx;
|
||||||
|
width: 600rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 75rpx;
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
.env-text {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.env-button {
|
||||||
|
border-radius: 46rpx;
|
||||||
|
background: #f0ad4e;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 600rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.button-login {
|
.button-login {
|
||||||
margin-top: 40vh;
|
|
||||||
border-radius: 46rpx;
|
border-radius: 46rpx;
|
||||||
width: 650rpx;
|
width: 650rpx;
|
||||||
height: 120rpx;
|
height: 120rpx;
|
||||||
@ -164,4 +273,12 @@ page {
|
|||||||
font-size: 48rpx;
|
font-size: 48rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
margin-top: 35vh;
|
||||||
|
padding: 32rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
148
pages/passwordDetail/passwordDetail.vue
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="item-title">密码</view>
|
||||||
|
<view class="item-content">{{ currentPasswordInfo.keyboardPwd }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 2rpx">
|
||||||
|
<view class="item-title">名称</view>
|
||||||
|
<view class="item-content">{{ currentPasswordInfo.keyboardPwdName }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 2rpx">
|
||||||
|
<view class="item-title">有效期</view>
|
||||||
|
<view v-if="currentPasswordInfo.keyboardPwdType === 2">永久</view>
|
||||||
|
<view v-else>
|
||||||
|
<view class="item-content">{{ timeFormat(currentPasswordInfo.startDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
|
<view class="item-content">{{ timeFormat(currentPasswordInfo.endDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 20rpx">
|
||||||
|
<view class="item-title">发送人</view>
|
||||||
|
<view class="item-content">{{ currentPasswordInfo.senderUsername }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-top: 2rpx">
|
||||||
|
<view class="item-title">发送时间</view>
|
||||||
|
<view class="item-content">{{ timeFormat(currentPasswordInfo.sendDate, 'yyyy-mm-dd h:M') }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="tips">密码生成后,请在当日23:59前使用一次进行激活,否则过0点后未激活则失效。</view>
|
||||||
|
<view class="button" @click="deletePassword">删除密码</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { timeFormat } from 'uview-plus'
|
||||||
|
import { deletePsaawordRequest } from '@/api/keyboardPwd'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useLockStore, ['currentPasswordInfo', 'passwordSearch']),
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
|
||||||
|
...mapState(useUserStore, ['userInfo'])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
timeFormat,
|
||||||
|
...mapActions(useBluetoothStore, ['setLockPassword']),
|
||||||
|
...mapActions(useLockStore, ['updatePasswordSearch', 'getPasswordList']),
|
||||||
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
|
async deletePassword () {
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该密码',
|
||||||
|
async success(res) {
|
||||||
|
if(res.confirm) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '删除中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const timestamp = parseInt(new Date().getTime() / 1000)
|
||||||
|
const { code } = await that.setLockPassword({
|
||||||
|
keyId: that.keyId.toString(),
|
||||||
|
uid: that.userInfo.uid.toString(),
|
||||||
|
pwdNo: that.currentPasswordInfo.pwdUserNo,
|
||||||
|
operate: 3,
|
||||||
|
isAdmin: that.currentPasswordInfo.pwdRight,
|
||||||
|
pwd: that.currentPasswordInfo.keyboardPwd,
|
||||||
|
userCountLimit: 0xFFFF,
|
||||||
|
startTime: timestamp,
|
||||||
|
endTime: timestamp
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
const { code: requestCode, message } = await deletePsaawordRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId,
|
||||||
|
keyboardPwdId: that.currentPasswordInfo.keyboardPwdId,
|
||||||
|
deleteType: 1
|
||||||
|
})
|
||||||
|
if(requestCode === 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
that.updatePasswordSearch({
|
||||||
|
...that.passwordSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
that.getPasswordList(that.passwordSearch)
|
||||||
|
that.backAndToast('删除成功')
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除失败,请保持在锁附近',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.item {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin: 32rpx;
|
||||||
|
width: 686rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #df282d;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
334
pages/passwordList/passwordList.vue
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<scroll-view v-if="deviceInfo" scroll-y="true" :style="{height: deviceInfo.screenHeight - deviceInfo.safeArea.top + 'px'}" lower-threshold="100"
|
||||||
|
@refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
|
||||||
|
:refresher-triggered="refresherTriggered">
|
||||||
|
<view class="search">
|
||||||
|
<up-search shape="square" :searchIconSize="48" :inputStyle="{ fontSize: '32rpx' }" :height="80" placeholder="搜索"
|
||||||
|
:clearabled="false" @change="changeSearch"
|
||||||
|
v-model="passwordSearch.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
|
||||||
|
</view>
|
||||||
|
<view style="padding: 32rpx 0 calc(env(safe-area-inset-bottom) + 250rpx) 0">
|
||||||
|
<view v-if="passwordList.length === 0 && requestFinished">
|
||||||
|
<image class="empty-list" src="/static/images/background_empty_list.png" mode="aspectFill"></image>
|
||||||
|
<view class="empty-list-text">暂无数据</view>
|
||||||
|
</view>
|
||||||
|
<view v-else>
|
||||||
|
<up-swipe-action>
|
||||||
|
<up-swipe-action-item ref="swipeItem" :options="options" v-for="(password, index) in passwordList"
|
||||||
|
:key="password.keyboardPwdId" :threshold="50" @click="deletePassword(password)">
|
||||||
|
<view class="password" @click="toPasswordDetail(password)">
|
||||||
|
<image class="password-left" src="/static/images/icon_lock_transparent.png" mode="aspectFill"></image>
|
||||||
|
<view class="password-right">
|
||||||
|
<view class="password-right-top">{{ password.keyboardPwdName }}</view>
|
||||||
|
<view class="password-right-bottom">{{ password.timeText }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="line"></view>
|
||||||
|
</up-swipe-action-item>
|
||||||
|
</up-swipe-action>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view class="button">
|
||||||
|
<view class="button-reset" @click="resetPassword">重置密码</view>
|
||||||
|
<view class="button-create" @click="toCreatePassword">获取密码</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { deletePsaawordRequest, resetPsaawordListRequest } from '@/api/keyboardPwd'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
deviceInfo: null,
|
||||||
|
refresherTriggered: false,
|
||||||
|
requestFinished: false,
|
||||||
|
options: [{
|
||||||
|
text: '删除',
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#f56c6c'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useUserStore, ['userInfo']),
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo', 'keyId']),
|
||||||
|
...mapState(useLockStore, ['passwordTotal', 'passwordList', 'passwordSearch']),
|
||||||
|
},
|
||||||
|
async onLoad() {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
this.deviceInfo = await this.getDeviceInfo()
|
||||||
|
this.updatePasswordSearch({
|
||||||
|
...this.passwordSearch,
|
||||||
|
lockId: this.currentLockInfo.lockId,
|
||||||
|
lockStatus: this.currentLockInfo.lockStatus
|
||||||
|
})
|
||||||
|
const { code, meesage } = await this.getPasswordList(this.passwordSearch)
|
||||||
|
this.requestFinished = true
|
||||||
|
uni.hideLoading()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBasicStore, ['routeJump', 'getDeviceInfo']),
|
||||||
|
...mapActions(useLockStore, ['getPasswordList', 'updateCurrentPasswordInfo', 'updatePasswordSearch']),
|
||||||
|
...mapActions(useBluetoothStore, ['resetLockPassword', 'setLockPassword']),
|
||||||
|
toPasswordDetail(password) {
|
||||||
|
this.updateCurrentPasswordInfo(password)
|
||||||
|
this.routeJump({
|
||||||
|
name: 'passwordDetail'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async deletePassword(data) {
|
||||||
|
const password = data
|
||||||
|
const that = this
|
||||||
|
let index = this.passwordList.findIndex(item => item.keyboardPwdId === password.keyboardPwdId)
|
||||||
|
that.$refs.swipeItem[index].closeHandler()
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该密码',
|
||||||
|
async success(res) {
|
||||||
|
if(res.confirm) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '删除中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const timestamp = parseInt(new Date().getTime() / 1000)
|
||||||
|
const { code } = await that.setLockPassword({
|
||||||
|
keyId: that.keyId.toString(),
|
||||||
|
uid: that.userInfo.uid.toString(),
|
||||||
|
pwdNo: password.pwdUserNo,
|
||||||
|
operate: 3,
|
||||||
|
isAdmin: password.pwdRight,
|
||||||
|
pwd: password.keyboardPwd,
|
||||||
|
userCountLimit: 0xFFFF,
|
||||||
|
startTime: timestamp,
|
||||||
|
endTime: timestamp
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
const { code: requestCode, message } = await deletePsaawordRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId,
|
||||||
|
keyboardPwdId: password.keyboardPwdId,
|
||||||
|
deleteType: 1
|
||||||
|
})
|
||||||
|
if(requestCode === 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
that.updatePasswordSearch({
|
||||||
|
...that.passwordSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
await that.getPasswordList(that.passwordSearch)
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除失败,请保持在锁附近',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async resetPassword() {
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要重置密码,该锁的所有密码都将被删除',
|
||||||
|
async success(res) {
|
||||||
|
if(res.confirm) {
|
||||||
|
const { code } = await that.resetLockPassword({
|
||||||
|
uid: that.userInfo.uid.toString(),
|
||||||
|
keyId: that.currentLockInfo.keyId.toString()
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
const { code: requestCode, message } = await resetPsaawordListRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId,
|
||||||
|
passwordKey: that.currentLockInfo.bluetooth.passwordKey
|
||||||
|
})
|
||||||
|
console.log('重置密码返回', requestCode, message)
|
||||||
|
if(requestCode === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '重置密码成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
that.updatePasswordSearch({
|
||||||
|
...that.passwordSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
that.getPasswordList(that.passwordSearch)
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: '重置密码失败,请保持在锁附近',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toCreatePassword() {
|
||||||
|
this.routeJump({
|
||||||
|
name: 'createPassword'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async refresherList() {
|
||||||
|
this.refresherTriggered = true
|
||||||
|
this.updatePasswordSearch({
|
||||||
|
...this.passwordSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
const { code, meesage } = await this.getPasswordList(this.passwordSearch)
|
||||||
|
if(code === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.refresherTriggered = false
|
||||||
|
},
|
||||||
|
async nextPage() {
|
||||||
|
if(this.passwordTotal <= this.passwordSearch.pageNo * this.passwordSearch.pageSize) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const pageNo = this.passwordSearch.pageNo + 1
|
||||||
|
const params = {
|
||||||
|
...this.passwordSearch,
|
||||||
|
pageNo
|
||||||
|
}
|
||||||
|
const { code, meesage } = await this.getPasswordList(params)
|
||||||
|
if(code === 0) {
|
||||||
|
that.updatePasswordSearch({
|
||||||
|
...that.passwordSearch,
|
||||||
|
pageNo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async changeSearch(data) {
|
||||||
|
this.updatePasswordSearch({
|
||||||
|
...this.passwordSearch,
|
||||||
|
searchStr: data
|
||||||
|
})
|
||||||
|
const { code, meesage } = await this.getPasswordList(this.passwordSearch)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search {
|
||||||
|
margin-top: 32rpx;
|
||||||
|
width: 686rpx !important;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: fixed;
|
||||||
|
bottom: calc(env(safe-area-inset-bottom) + 48rpx);
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
.button-reset {
|
||||||
|
margin-left: 50rpx;
|
||||||
|
width: 300rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #df282d;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-create {
|
||||||
|
margin-left: 50rpx;
|
||||||
|
width: 300rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #63b8af;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.password {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
height: 120rpx;
|
||||||
|
width: 750rpx;
|
||||||
|
|
||||||
|
.password-left {
|
||||||
|
margin-left: 32rpx;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-right {
|
||||||
|
margin-right: 32rpx;
|
||||||
|
|
||||||
|
.password-right-top {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-right-bottom {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
width: 100%;
|
||||||
|
height: 2rpx;
|
||||||
|
background: #EBEBEB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-list {
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
margin: 300rpx auto 20rpx 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-list-text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,17 +1,162 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
|
<scroll-view v-if="deviceInfo" class="scroll-view" scroll-y="true" :style="{ height: deviceInfo.screenHeight - deviceInfo.statusBarHeight + 'px' }">
|
||||||
|
<view style="padding-bottom: calc(env(safe-area-inset-bottom) + 300rpx)">
|
||||||
|
<view class="device" v-for="device in deviceList" @click="connect(device)">
|
||||||
|
<view class="device" style="justify-content:flex-start;">
|
||||||
|
<image class="device-lock" src="/static/images/icon_door_lock.png"></image>
|
||||||
|
<view class="device-name">{{device.name}}</view>
|
||||||
|
</view>
|
||||||
|
<image class="device-add" src="/static/images/icon_add.png"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view class="loading">
|
||||||
|
<up-loading-icon size="80rpx" text="搜索中" :vertical="true" textSize="32rpx"></up-loading-icon>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState, mapActions } from 'pinia'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {}
|
return {
|
||||||
|
deviceInfo: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useBluetoothStore, ['deviceList', 'currentLockInfo', 'serverTimestamp', 'keyId']),
|
||||||
|
...mapState(useUserStore, ['userInfo'])
|
||||||
|
},
|
||||||
|
async onLoad() {
|
||||||
|
this.deviceInfo = await this.getDeviceInfo()
|
||||||
|
this.getBluetoothDevices()
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
this.stopGetBluetoothDevices()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBluetoothStore, ['getBluetoothDevices', 'stopGetBluetoothDevices', 'updateCurrentLockInfo',
|
||||||
|
'getPublicKey', 'getCommKey', 'connectBluetoothDevice', 'updateServerTimestamp', 'getLockStatus']),
|
||||||
|
...mapActions(useBasicStore, ['getDeviceInfo', 'routeJump']),
|
||||||
|
async connect(device) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '连接中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const { code: serverTimestampCode, message } = await this.updateServerTimestamp()
|
||||||
|
if(serverTimestampCode !== 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
uni.hideLoading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
name: device.name,
|
||||||
|
deviceId: device.deviceId
|
||||||
|
})
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
this.stopGetBluetoothDevices()
|
||||||
|
if(result) {
|
||||||
|
const { code: getPublicKeyCode } = await this.getPublicKey(this.currentLockInfo.name)
|
||||||
|
console.log('获取公钥返回', getPublicKeyCode, [...this.currentLockInfo.publicKey])
|
||||||
|
if(getPublicKeyCode !== 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '连接失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { code: getCommKeyCode } = await this.getCommKey(this.currentLockInfo.name, this.keyId,
|
||||||
|
this.userInfo.uid.toString(), this.serverTimestamp)
|
||||||
|
console.log('获取私钥返回', getCommKeyCode)
|
||||||
|
if(getCommKeyCode !== 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '连接失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const date = new Date()
|
||||||
|
const timestamp = parseInt(date.getTime() / 1000) - date.getTimezoneOffset() * 60
|
||||||
|
const { code } = await this.getLockStatus({
|
||||||
|
name: this.currentLockInfo.name,
|
||||||
|
uid: this.userInfo.uid,
|
||||||
|
nowTime: this.serverTimestamp,
|
||||||
|
localTime: timestamp
|
||||||
|
})
|
||||||
|
if (code !== 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '连接失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'selectAddress'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.getBluetoothDevices()
|
||||||
|
uni.showToast({
|
||||||
|
title: '连接失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.loading {
|
||||||
|
position: fixed;
|
||||||
|
bottom: calc(env(safe-area-inset-bottom) + 50rpx) ;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.device {
|
||||||
|
background: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
.device-lock {
|
||||||
|
margin-left: 24rpx;
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-name {
|
||||||
|
margin-left: 24rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-add {
|
||||||
|
float: right;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
256
pages/selectAddress/selectAddress.vue
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="title">地理位置</view>
|
||||||
|
<view v-if="show">
|
||||||
|
<map class="map" :longitude="longitude" :latitude="latitude" :scale="16" :markers="markers"
|
||||||
|
:enable-zoom="false" :enable-scroll="false"></map>
|
||||||
|
</view>
|
||||||
|
<view v-else class="map"></view>
|
||||||
|
<view class="explain">检查以确保以下地址是正确的</view>
|
||||||
|
<view class="view-address" :style="{height: calculateStringTotalWidth(address) > 44 ? '120rpx' : '80rpx'}">
|
||||||
|
<view class="address">{{ address }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="bottom">
|
||||||
|
<view class="skip" @click="skipAddress">跳过</view>
|
||||||
|
<view class="confirm" @click="toBindLock">下一步</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { test } from 'uview-plus'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { mapState, mapActions } from 'pinia'
|
||||||
|
import { getGeocodeAddress } from '@/api/geocode'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
latitude: null,
|
||||||
|
longitude: null,
|
||||||
|
show: false,
|
||||||
|
markers: [],
|
||||||
|
address: '',
|
||||||
|
first: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useBluetoothStore, ['currentLockInfo'])
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.getLocation()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
if(this.first) {
|
||||||
|
this.first = false
|
||||||
|
} else {
|
||||||
|
if(!this.show) {
|
||||||
|
this.getLocation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBasicStore, ['routeJump', 'calculateStringTotalWidth']),
|
||||||
|
...mapActions(useBluetoothStore, ['updateCurrentLockInfo']),
|
||||||
|
toBindLock() {
|
||||||
|
const that = this
|
||||||
|
if(this.address === '') {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '暂未获取到地理位置信息,请重试',
|
||||||
|
confirmText: '重试',
|
||||||
|
success: (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
that.getLocation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'bindLock'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
skipAddress() {
|
||||||
|
const that = this
|
||||||
|
if(this.address !== '') {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '已获取当前地理位置,确定跳过吗',
|
||||||
|
confirmText: '跳过',
|
||||||
|
cancelText: '取消',
|
||||||
|
success: (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
const lockInfo = that.currentLockInfo
|
||||||
|
delete lockInfo.position
|
||||||
|
that.updateCurrentLockInfo(lockInfo)
|
||||||
|
this.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'bindLock'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'bindLock'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async getLocation() {
|
||||||
|
const that = this
|
||||||
|
uni.getLocation({
|
||||||
|
isHighAccuracy: true,
|
||||||
|
type: 'gcj02',
|
||||||
|
async success (res) {
|
||||||
|
that.latitude = res.latitude
|
||||||
|
that.longitude = res.longitude
|
||||||
|
that.markers = [{
|
||||||
|
id: 1,
|
||||||
|
latitude: res.latitude,
|
||||||
|
longitude: res.longitude,
|
||||||
|
iconPath: '/static/images/icon_address.png',
|
||||||
|
width: '48rpx',
|
||||||
|
height: '48rpx'
|
||||||
|
}]
|
||||||
|
that.show = true
|
||||||
|
const { code, data: result } = await getGeocodeAddress({
|
||||||
|
latitude: that.latitude,
|
||||||
|
longitude: that.longitude
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
that.address = result.addr
|
||||||
|
const position = {
|
||||||
|
...result,
|
||||||
|
latitude: that.latitude,
|
||||||
|
longitude: that.longitude
|
||||||
|
}
|
||||||
|
console.log('获取地理位置信息', that.currentLockInfo)
|
||||||
|
that.updateCurrentLockInfo({
|
||||||
|
...that.currentLockInfo,
|
||||||
|
position
|
||||||
|
})
|
||||||
|
console.log('获取地理位置信息', that.currentLockInfo)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail (res) {
|
||||||
|
if(res.errMsg === 'getLocation:fail auth deny') {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '拒绝授权将无法使用定位功能',
|
||||||
|
confirmText: '去授权',
|
||||||
|
cancelText: '跳过',
|
||||||
|
success (res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.openSetting()
|
||||||
|
} else {
|
||||||
|
that.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'bindLock'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '获取地理位置信息失败',
|
||||||
|
confirmText: '重试',
|
||||||
|
cancelText: '跳过',
|
||||||
|
success (res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
that.getLocation()
|
||||||
|
} else {
|
||||||
|
that.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'bindLock'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.map {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 650rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
font-size: 80rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explain {
|
||||||
|
padding: 20rpx 30rpx 0 30rpx;
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-address {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 690rpx;
|
||||||
|
color: #c4c4c4;
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin: 0 30rpx;
|
||||||
|
border-bottom: #63b8af 3rpx solid;
|
||||||
|
|
||||||
|
.address {
|
||||||
|
width: 690rpx;
|
||||||
|
text-align: left;
|
||||||
|
word-break: break-all;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
width: 600rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 75rpx;
|
||||||
|
position: fixed;
|
||||||
|
bottom: calc(30rpx + env(safe-area-inset-bottom));
|
||||||
|
|
||||||
|
.skip {
|
||||||
|
width: 225rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
border-radius: 64rpx;
|
||||||
|
border: 3rpx solid #63b8af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm {
|
||||||
|
border-radius: 64rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
background-color: #63b8af;
|
||||||
|
width: 225rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
218
pages/setting/setting.vue
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="view">
|
||||||
|
<view class="view-button">
|
||||||
|
<view>名称</view>
|
||||||
|
<view class="view-button" style="padding: 0">
|
||||||
|
<view class="info">{{currentLockInfo.lockAlias}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="view-button">
|
||||||
|
<view>锁编号</view>
|
||||||
|
<view class="view-button" style="padding: 0">
|
||||||
|
<view class="info">{{currentLockInfo.name}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="view-line"></view>
|
||||||
|
<view class="view-button">
|
||||||
|
<view>MAC/ID</view>
|
||||||
|
<view class="view-button" style="padding: 0">
|
||||||
|
<view class="info">{{currentLockInfo.mac}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="view-line"></view>
|
||||||
|
<view class="view-button">
|
||||||
|
<view>电量</view>
|
||||||
|
<view class="view-button" style="padding: 0">
|
||||||
|
<view class="info">{{currentLockInfo.electricQuantity}}%</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="view" v-if="currentLockInfo.userType === 110301">
|
||||||
|
<view class="view-button">
|
||||||
|
<view>开锁时是否需联网</view>
|
||||||
|
<view class="view-button" style="padding: 0">
|
||||||
|
<up-switch v-model="unlockApp" :size="40" activeColor="#63b8af" :asyncChange="true"
|
||||||
|
@change="changeUnlockApp" :activeValue="1" :inactiveValue="0"></up-switch>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="button-logout" @click="deleteLock">删除</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
|
import { deleteLockRequest } from '@/api/lock'
|
||||||
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
import { updateLockSettingRequest } from '@/api/lockSetting'
|
||||||
|
import { deleteKeyRequest } from '@/api/key'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
unlockApp: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(useUserStore, ['userInfo']),
|
||||||
|
...mapState(useBluetoothStore, ['keyId', 'currentLockInfo']),
|
||||||
|
...mapState(useLockStore, ['lockSearch'])
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.unlockApp = this.currentLockInfo.lockSetting.appUnlockOnline
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useBluetoothStore, ['resetDevice', 'updateCurrentLockInfo']),
|
||||||
|
...mapActions(useLockStore, ['getLockList', 'updateLockSearch']),
|
||||||
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
|
async changeUnlockApp(value) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '更新中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
const { code, message } = await updateLockSettingRequest({
|
||||||
|
lockId: this.currentLockInfo.lockId,
|
||||||
|
appUnlockOnline: value
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
this.unlockApp = value
|
||||||
|
const data = this.currentLockInfo
|
||||||
|
data.lockSetting.appUnlockOnline = value
|
||||||
|
this.updateCurrentLockInfo(data)
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '更新成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteLock() {
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定删除该门锁吗?',
|
||||||
|
success: async function (res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '删除中',
|
||||||
|
mask: true
|
||||||
|
})
|
||||||
|
if(that.currentLockInfo.userType === 110301) {
|
||||||
|
const { code: resetDeviceCode } = await that.resetDevice({
|
||||||
|
name: that.currentLockInfo.name,
|
||||||
|
authUid: that.userInfo.uid.toString(),
|
||||||
|
keyId: that.keyId.toString()
|
||||||
|
})
|
||||||
|
if(resetDeviceCode === 0) {
|
||||||
|
const { code, message } = await deleteLockRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
that.updateLockSearch({
|
||||||
|
...that.lockSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
that.getLockList(that.lockSearch)
|
||||||
|
that.backAndToast('删除成功', 2)
|
||||||
|
uni.navigateBack()
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: 'message',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const { code } = await deleteKeyRequest({
|
||||||
|
keyId: that.keyId
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
uni.hideLoading()
|
||||||
|
that.updateLockSearch({
|
||||||
|
...that.lockSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
that.getLockList(that.lockSearch)
|
||||||
|
that.backAndToast('删除成功', 2)
|
||||||
|
uni.navigateBack()
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: 'message',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: $uni-bg-color-grey;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.button-logout {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 46rpx;
|
||||||
|
bottom: calc(env(safe-area-inset-bottom) + 30rpx);
|
||||||
|
width: 600rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 75rpx;
|
||||||
|
background: #ec433c;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view {
|
||||||
|
margin-top: 32rpx;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
width: 710rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-button {
|
||||||
|
padding: 0 40rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: #292826;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-line {
|
||||||
|
width: 100%;
|
||||||
|
height: 3rpx;
|
||||||
|
background: #EBEBEB;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -42,7 +42,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useUserStore, ['updateUserInfo']),
|
...mapActions(useUserStore, ['updateUserInfo']),
|
||||||
...mapActions(useBasicStore, ['routeJump']),
|
...mapActions(useBasicStore, ['routeJump', 'backAndToast']),
|
||||||
updateInputEmail(data) {
|
updateInputEmail(data) {
|
||||||
this.email = data.detail.value
|
this.email = data.detail.value
|
||||||
},
|
},
|
||||||
@ -100,14 +100,7 @@ export default {
|
|||||||
...this.userInfo,
|
...this.userInfo,
|
||||||
email: this.email
|
email: this.email
|
||||||
})
|
})
|
||||||
uni.navigateBack({
|
this.backAndToast('邮箱绑定成功')
|
||||||
complete () {
|
|
||||||
uni.showToast({
|
|
||||||
title: '邮箱更新成功',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: message,
|
title: message,
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
import { mapActions, mapState } from 'pinia'
|
import { mapActions, mapState } from 'pinia'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { updateUserInfoRequest } from '@/api/user'
|
import { updateUserInfoRequest } from '@/api/user'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@ -26,6 +27,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useUserStore, ['updateUserInfo']),
|
...mapActions(useUserStore, ['updateUserInfo']),
|
||||||
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
updateInput(data) {
|
updateInput(data) {
|
||||||
this.nickname = data.detail.value
|
this.nickname = data.detail.value
|
||||||
console.log(data)
|
console.log(data)
|
||||||
@ -50,14 +52,7 @@ export default {
|
|||||||
...this.userInfo,
|
...this.userInfo,
|
||||||
nickname: this.nickname
|
nickname: this.nickname
|
||||||
})
|
})
|
||||||
uni.navigateBack({
|
this.backAndToast('昵称更新成功')
|
||||||
complete() {
|
|
||||||
uni.showToast({
|
|
||||||
title: '昵称更新成功',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '昵称更新失败',
|
title: '昵称更新失败',
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<input class="input" :password="true" style="margin-top: 48rpx;" :value="oldPassword" maxlength="20"
|
<input class="input" :password="true" :value="password" maxlength="20" placeholder="请输入新密码"
|
||||||
placeholder="请输入原密码" placeholder-class="input-placeholder" :focus="true" @input="updateOldPassword"></input>
|
|
||||||
<input class="input" :password="true" :value="newPassword" maxlength="20" placeholder="请输入新密码"
|
|
||||||
placeholder-class="input-placeholder" @input="updateNewPassword"></input>
|
placeholder-class="input-placeholder" @input="updateNewPassword"></input>
|
||||||
<input class="input" :password="true" :value="confirmPassword" maxlength="20" placeholder="请确认密码"
|
<view class="view-top">
|
||||||
placeholder-class="input-placeholder" @input="updateConfirmPassword"></input>
|
<input type="number" class="input-verify" :value="verificationCode" maxlength="6" placeholder="请输入验证码"
|
||||||
|
placeholder-class="input-placeholder" @input="updateInputCode"></input>
|
||||||
|
<view class="button-verify" @click="getPhoneCode">{{text}}</view>
|
||||||
|
</view>
|
||||||
<view class="text-tips">密码必须是8-20位,至少包括数字/字母/符号中的2种</view>
|
<view class="text-tips">密码必须是8-20位,至少包括数字/字母/符号中的2种</view>
|
||||||
<view class="button" @click="updatePassword">保存</view>
|
<view class="button" @click="updatePassword">保存</view>
|
||||||
</view>
|
</view>
|
||||||
@ -14,15 +15,17 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapActions, mapState } from 'pinia'
|
import { mapActions, mapState } from 'pinia'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { updatePasswordRequest } from '@/api/user'
|
import { changePasswordRequest, getEmailCodeRequest, updatePasswordRequest } from '@/api/user'
|
||||||
|
import { test } from 'uview-plus'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
oldPassword: '',
|
text: '获取验证码',
|
||||||
newPassword: '',
|
password: '',
|
||||||
confirmPassword: '',
|
pending: false,
|
||||||
pending: false
|
verificationCode: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -30,34 +33,61 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useUserStore, ['updateUserInfo']),
|
...mapActions(useUserStore, ['updateUserInfo']),
|
||||||
updateOldPassword (data) {
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
this.oldPassword = data.detail.value
|
|
||||||
},
|
|
||||||
updateNewPassword (data) {
|
updateNewPassword (data) {
|
||||||
this.newPassword = data.detail.value
|
this.password = data.detail.value
|
||||||
},
|
},
|
||||||
updateConfirmPassword (data) {
|
updateInputCode (data) {
|
||||||
this.confirmPassword = data.detail.value
|
this.verificationCode = data.detail.value
|
||||||
|
},
|
||||||
|
async getPhoneCode () {
|
||||||
|
if (this.text !== '获取验证码') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { code, message } = await getEmailCodeRequest({
|
||||||
|
channel: '1',
|
||||||
|
codeType: 9
|
||||||
|
})
|
||||||
|
if (code === 0) {
|
||||||
|
this.updateTime()
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTime () {
|
||||||
|
let time = 120
|
||||||
|
this.text = `${time} s`
|
||||||
|
const now = new Date().getTime()
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
const second = parseInt((new Date().getTime() - now) / 1000)
|
||||||
|
this.text = `${time - second} s`
|
||||||
|
if (time <= second) {
|
||||||
|
clearInterval(timer)
|
||||||
|
this.text = '获取验证码'
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
},
|
},
|
||||||
async updatePassword () {
|
async updatePassword () {
|
||||||
if (this.oldPassword === '' || this.newPassword === '' || this.confirmPassword === '') {
|
if (this.password === '') {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '密码不能为空',
|
title: '密码不能为空',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.newPassword.length < 8 || this.newPassword.length > 20 || this.confirmPassword.length < 8 ||
|
if (this.password.length < 8 || this.password.length > 20) {
|
||||||
this.confirmPassword.length > 20 || this.oldPassword.length < 8 || this.oldPassword.length > 20) {
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '密码长度必须是8-20位',
|
title: '密码长度必须是8-20位',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.newPassword !== this.confirmPassword) {
|
if (!(this.verificationCode.length === 6 && test.digits(this.verificationCode))) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '两次密码输入不一致',
|
title: '验证码为6位纯数字',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -66,24 +96,13 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.pending = true
|
this.pending = true
|
||||||
const { code, message } = await updatePasswordRequest({
|
const { code, message } = await changePasswordRequest({
|
||||||
oldPassword: this.oldPassword,
|
verificationCode: this.verificationCode,
|
||||||
newPassword: this.newPassword,
|
password: this.password,
|
||||||
date: new Date().getTime()
|
channel: '1'
|
||||||
})
|
})
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
this.updateUserInfo({
|
this.backAndToast('密码重置成功')
|
||||||
...this.userInfo,
|
|
||||||
nickname: this.nickname
|
|
||||||
})
|
|
||||||
uni.navigateBack({
|
|
||||||
complete () {
|
|
||||||
uni.showToast({
|
|
||||||
title: '密码重置成功',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: message,
|
title: message,
|
||||||
@ -107,7 +126,7 @@ page {
|
|||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
margin-left: 35rpx;
|
margin-left: 35rpx;
|
||||||
margin-top: 24rpx;
|
margin-top: 48rpx;
|
||||||
height: 108rpx;
|
height: 108rpx;
|
||||||
width: 616rpx;
|
width: 616rpx;
|
||||||
padding-left: 32rpx;
|
padding-left: 32rpx;
|
||||||
@ -140,4 +159,34 @@ page {
|
|||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #9B9B9B;
|
color: #9B9B9B;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.view-top {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-verify {
|
||||||
|
border-radius: 16rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-left: 35rpx;
|
||||||
|
margin-top: 48rpx;
|
||||||
|
height: 108rpx;
|
||||||
|
width: 316rpx;
|
||||||
|
padding-left: 32rpx;
|
||||||
|
padding-right: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-verify {
|
||||||
|
margin-top: 48rpx;
|
||||||
|
height: 108rpx;
|
||||||
|
width: 265rpx;
|
||||||
|
line-height: 108rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin-left: 35rpx;
|
||||||
|
|
||||||
|
background: #63b8af;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
import { getQuestionAnswerRequest, getQuestionListRequest, updateQuestionAnswerRequest } from '@/api/safeAnswer'
|
import { getQuestionAnswerRequest, getQuestionListRequest, updateQuestionAnswerRequest } from '@/api/safeAnswer'
|
||||||
import { mapActions, mapState } from 'pinia'
|
import { mapActions, mapState } from 'pinia'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@ -75,6 +76,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useUserStore, ['updateUserInfo']),
|
...mapActions(useUserStore, ['updateUserInfo']),
|
||||||
|
...mapActions(useBasicStore, ['backAndToast']),
|
||||||
async updateAnswer() {
|
async updateAnswer() {
|
||||||
console.log('答案', this.answer)
|
console.log('答案', this.answer)
|
||||||
for(let i = 0; i < this.answer.length; i++) {
|
for(let i = 0; i < this.answer.length; i++) {
|
||||||
@ -107,14 +109,7 @@ export default {
|
|||||||
...this.userInfo,
|
...this.userInfo,
|
||||||
haveSafeAnswer: 1
|
haveSafeAnswer: 1
|
||||||
})
|
})
|
||||||
uni.navigateBack({
|
this.backAndToast('设置成功')
|
||||||
complete() {
|
|
||||||
uni.showToast({
|
|
||||||
title: '安全问题设置成功',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: message,
|
title: message,
|
||||||
|
|||||||
@ -19,14 +19,16 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="view-line"></view>
|
<view class="view-line"></view>
|
||||||
<view class="view-button">
|
<label for="phone">
|
||||||
<view>手机号</view>
|
<view class="view-button">
|
||||||
<view class="view-button" style="padding: 0">
|
<view>手机号</view>
|
||||||
<view v-if="userInfo.mobile !== ''" class="info">{{userInfo.mobile}}</view>
|
<view class="view-button" style="padding: 0">
|
||||||
<view v-else class="red-dot"></view>
|
<view v-if="userInfo.mobile !== ''" class="info">{{userInfo.mobile}}</view>
|
||||||
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
<view v-else class="red-dot"></view>
|
||||||
|
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</label>
|
||||||
<view class="view-line"></view>
|
<view class="view-line"></view>
|
||||||
<view class="view-button" @click="toUpdateEmail">
|
<view class="view-button" @click="toUpdateEmail">
|
||||||
<view>邮箱</view>
|
<view>邮箱</view>
|
||||||
@ -58,6 +60,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<button open-type="chooseAvatar" style="display:none" id="avatar" @chooseavatar="chooseAvatar"></button>
|
<button open-type="chooseAvatar" style="display:none" id="avatar" @chooseavatar="chooseAvatar"></button>
|
||||||
|
<button open-type="getPhoneNumber" style="display:none" id="phone" @getphonenumber="rebindPhone"></button>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -66,7 +69,7 @@ import { mapActions, mapState } from 'pinia'
|
|||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { useBasicStore } from '@/stores/basic'
|
import { useBasicStore } from '@/stores/basic'
|
||||||
import { getUploadParamsRequest } from '@/api/file'
|
import { getUploadParamsRequest } from '@/api/file'
|
||||||
import { updateUserInfoRequest } from '@/api/user'
|
import { rebindPhoneRequest, updateUserInfoRequest } from '@/api/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@ -79,11 +82,44 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useBasicStore, ['routeJump']),
|
...mapActions(useBasicStore, ['routeJump']),
|
||||||
...mapActions(useUserStore, ['updateUserInfo']),
|
...mapActions(useUserStore, ['updateUserInfo', 'checkSession', 'getUserInfo']),
|
||||||
|
async rebindPhone(detail) {
|
||||||
|
if(detail.detail.errMsg === 'getPhoneNumber:fail user deny') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(this.pending) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.pending = true
|
||||||
|
const result = await this.checkSession()
|
||||||
|
if(result) {
|
||||||
|
const { code, data, message } = await rebindPhoneRequest({
|
||||||
|
encryptedData: detail.detail.encryptedData,
|
||||||
|
iv: detail.detail.iv
|
||||||
|
})
|
||||||
|
if(code === 0) {
|
||||||
|
this.getUserInfo()
|
||||||
|
// this.updateUserInfo({
|
||||||
|
// ...this.userInfo,
|
||||||
|
// mobile: data.mobile
|
||||||
|
// })
|
||||||
|
uni.showToast({
|
||||||
|
title: '更换成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.rebindPhone()
|
||||||
|
}
|
||||||
|
this.pending = false
|
||||||
|
},
|
||||||
chooseAvatar(e) {
|
chooseAvatar(e) {
|
||||||
console.log(e)
|
|
||||||
const that = this
|
const that = this
|
||||||
|
|
||||||
if(that.pending) {
|
if(that.pending) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
|
<view class="tips">为了你的账号安全,修改账号前请先使用验证码验证</view>
|
||||||
<view class="view-top">
|
<view class="view-top">
|
||||||
<input type="number" class="input" :value="verificationCode" maxlength="20" placeholder="请输入验证码"
|
<input type="number" class="input" :value="verificationCode" maxlength="20" placeholder="请输入验证码"
|
||||||
placeholder-class="input-placeholder" @input="updateInput"></input>
|
placeholder-class="input-placeholder" @input="updateInput"></input>
|
||||||
@ -87,37 +88,6 @@ export default {
|
|||||||
},
|
},
|
||||||
updateInput(data) {
|
updateInput(data) {
|
||||||
this.verificationCode = data.detail.value
|
this.verificationCode = data.detail.value
|
||||||
},
|
|
||||||
async updateName() {
|
|
||||||
if(this.nickname === '') {
|
|
||||||
uni.showToast({
|
|
||||||
title: '昵称不能为空',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const { code } = await updateUserInfoRequest({
|
|
||||||
nickname: this.nickname
|
|
||||||
})
|
|
||||||
if(code === 0) {
|
|
||||||
this.updateUserInfo({
|
|
||||||
...this.userInfo,
|
|
||||||
nickname: this.nickname
|
|
||||||
})
|
|
||||||
uni.navigateBack({
|
|
||||||
complete() {
|
|
||||||
uni.showToast({
|
|
||||||
title: '昵称更新成功',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '昵称更新失败',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,6 +100,12 @@ page {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.tips {
|
||||||
|
padding: 24rpx 32rpx 0 32rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
.button-verify {
|
.button-verify {
|
||||||
margin-top: 48rpx;
|
margin-top: 48rpx;
|
||||||
height: 108rpx;
|
height: 108rpx;
|
||||||
|
|||||||
BIN
static/images/background_empty_list.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
static/images/background_main.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 880 B |
BIN
static/images/icon_add_round.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
static/images/icon_address.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
static/images/icon_cloud.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
static/images/icon_cloud_active.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
static/images/icon_door_lock.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
static/images/icon_lock_transparent.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/icon_menu.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
static/images/icon_role.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
static/images/icon_setting.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
static/images/icon_tips.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
@ -61,6 +61,51 @@ const pages = [
|
|||||||
name: 'searchDevice',
|
name: 'searchDevice',
|
||||||
path: '/pages/searchDevice/searchDevice',
|
path: '/pages/searchDevice/searchDevice',
|
||||||
tabBar: false
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'selectAddress',
|
||||||
|
path: '/pages/selectAddress/selectAddress',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'bindLock',
|
||||||
|
path: '/pages/bindLock/bindLock',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'setting',
|
||||||
|
path: '/pages/setting/setting',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'keyList',
|
||||||
|
path: '/pages/keyList/keyList',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'createKey',
|
||||||
|
path: '/pages/createKey/createKey',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'passwordList',
|
||||||
|
path: '/pages/passwordList/passwordList',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'createPassword',
|
||||||
|
path: '/pages/createPassword/createPassword',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'passwordDetail',
|
||||||
|
path: '/pages/passwordDetail/passwordDetail',
|
||||||
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'keyDetail',
|
||||||
|
path: '/pages/keyDetail/keyDetail',
|
||||||
|
tabBar: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -120,5 +165,37 @@ export const useBasicStore = defineStore('basic', {
|
|||||||
return
|
return
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 计算字符串长度
|
||||||
|
calculateStringTotalWidth(str) {
|
||||||
|
let totalWidth = 0
|
||||||
|
// 遍历字符串中的每一个字符
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
const char = str[i]
|
||||||
|
// 判断当前字符是全角字符还是半角字符
|
||||||
|
if (/[\uFF01-\uFF60\uFFE0-\uFFE6\u4E00-\u9FFF\u3000-\u303F]/.test(char)) {
|
||||||
|
// 全角字符宽度为 2
|
||||||
|
totalWidth += 2
|
||||||
|
} else {
|
||||||
|
// 半角字符宽度为 1
|
||||||
|
totalWidth += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalWidth
|
||||||
|
},
|
||||||
|
// 回退页面并弹出toast提示
|
||||||
|
backAndToast(message, delta = 1) {
|
||||||
|
const that = this
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: delta,
|
||||||
|
complete: function () {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,11 +5,20 @@ import { defineStore } from 'pinia'
|
|||||||
import crc from 'crc'
|
import crc from 'crc'
|
||||||
import { sm4 } from 'sm-crypto'
|
import { sm4 } from 'sm-crypto'
|
||||||
import { md5 } from 'js-md5'
|
import { md5 } from 'js-md5'
|
||||||
|
import { getServerDatetime } from '@/api/check'
|
||||||
|
import { getUserNoListRequest, updateLockUserNoRequest } from '@/api/key'
|
||||||
|
import { updateElectricQuantityRequest } from '@/api/room'
|
||||||
|
import { reportOpenDoorRequest } from '@/api/lockRecords'
|
||||||
|
import { updateTimezoneOffsetRequest } from '@/api/user'
|
||||||
|
|
||||||
// 定时器
|
// 定时器
|
||||||
let timer
|
let timer
|
||||||
// 特性值回调
|
// 特性值回调
|
||||||
let characteristicValueCallback = null
|
let characteristicValueCallback = null
|
||||||
|
// 搜索次数
|
||||||
|
let searchNumber = 10
|
||||||
|
// 搜索提示标志
|
||||||
|
let searchTipFlag = true
|
||||||
|
|
||||||
// 命令ID
|
// 命令ID
|
||||||
const cmdIds = {
|
const cmdIds = {
|
||||||
@ -58,14 +67,40 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
// 消息序号
|
// 消息序号
|
||||||
messageCount: 1,
|
messageCount: 1,
|
||||||
// 是否初始化蓝牙
|
// 是否初始化蓝牙
|
||||||
isInitBluetooth: false
|
isInitBluetooth: false,
|
||||||
|
// 服务器时间
|
||||||
|
serverTimestamp: 0,
|
||||||
|
// 设备keyID
|
||||||
|
keyId: '0'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
// 更新keyId
|
||||||
|
updateKeyId(keyId) {
|
||||||
|
this.keyId = keyId
|
||||||
|
},
|
||||||
|
// 二进制转字符串
|
||||||
|
uint8ArrayToString(uint8Array) {
|
||||||
|
let str = ''
|
||||||
|
for (let i = 0; i < uint8Array.length; i++) {
|
||||||
|
if (uint8Array[i] !== 0) {
|
||||||
|
str += String.fromCharCode(uint8Array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
},
|
||||||
|
// 更新服务端时间戳
|
||||||
|
async updateServerTimestamp() {
|
||||||
|
const { code, data, message } = await getServerDatetime({})
|
||||||
|
if(code === 0) {
|
||||||
|
this.serverTimestamp = parseInt(data.date / 1000)
|
||||||
|
}
|
||||||
|
return { code, data, message }
|
||||||
|
},
|
||||||
// 初始化并监听
|
// 初始化并监听
|
||||||
async initAndListenBluetooth() {
|
async initAndListenBluetooth(tipFlag) {
|
||||||
// 初始化蓝牙
|
// 初始化蓝牙
|
||||||
const initResult = await this.initBluetooth()
|
const initResult = await this.initBluetooth(tipFlag)
|
||||||
if (initResult) {
|
if (initResult) {
|
||||||
// 更新蓝牙初始化状态
|
// 更新蓝牙初始化状态
|
||||||
this.updateInitBluetooth(true)
|
this.updateInitBluetooth(true)
|
||||||
@ -86,7 +121,7 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
this.isInitBluetooth = value
|
this.isInitBluetooth = value
|
||||||
},
|
},
|
||||||
// 初始化蓝牙模块
|
// 初始化蓝牙模块
|
||||||
initBluetooth() {
|
initBluetooth(tipFlag = true) {
|
||||||
const that = this
|
const that = this
|
||||||
// 初始化蓝牙模块
|
// 初始化蓝牙模块
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
@ -119,6 +154,23 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
resolve(true)
|
resolve(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if(err.errno === 3 && tipFlag) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '蓝牙功能需要附近设备权限,请前往设置开启微信的附近设备权限后再试',
|
||||||
|
showCancel: false,
|
||||||
|
confirmText: '确定',
|
||||||
|
success(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.openAppAuthorizeSetting({
|
||||||
|
success (res) {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
resolve(false)
|
resolve(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -168,7 +220,7 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
if(binaryData[14] === 0) {
|
if(binaryData[14] === 0) {
|
||||||
that.updateCurrentLockInfo({
|
that.updateCurrentLockInfo({
|
||||||
...that.currentLockInfo,
|
...that.currentLockInfo,
|
||||||
publicKey: binaryData.slice(15, 31)
|
publicKey: [...binaryData.slice(15, 31)]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
characteristicValueCallback({
|
characteristicValueCallback({
|
||||||
@ -191,7 +243,8 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
that.updateCurrentLockInfo({
|
that.updateCurrentLockInfo({
|
||||||
...that.currentLockInfo,
|
...that.currentLockInfo,
|
||||||
commKey: decrypted.slice(3, 19),
|
commKey: decrypted.slice(3, 19),
|
||||||
signKey: decrypted.slice(19, 35)
|
signKey: decrypted.slice(19, 35),
|
||||||
|
pwdTimestamp: this.arrayToTimestamp(decrypted.slice(35, 39)) * 1000
|
||||||
})
|
})
|
||||||
console.log('commKey', Array.from(that.currentLockInfo.commKey))
|
console.log('commKey', Array.from(that.currentLockInfo.commKey))
|
||||||
console.log('signKey', Array.from(that.currentLockInfo.signKey))
|
console.log('signKey', Array.from(that.currentLockInfo.signKey))
|
||||||
@ -211,28 +264,28 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
case cmdIds.getLockStatus:
|
case cmdIds.getLockStatus:
|
||||||
if (decrypted[2] === 0) {
|
if (decrypted[2] === 0) {
|
||||||
const lockConfig = {
|
const lockConfig = {
|
||||||
vendor: decrypted.slice(3, 23),
|
vendor: that.uint8ArrayToString(decrypted.slice(3, 23)),
|
||||||
product: decrypted[23],
|
product: decrypted[23],
|
||||||
model: decrypted.slice(24, 44),
|
model: that.uint8ArrayToString(decrypted.slice(24, 44)),
|
||||||
fwVersion: decrypted.slice(44, 64),
|
fwVersion: that.uint8ArrayToString(decrypted.slice(44, 64)),
|
||||||
hwVersion: decrypted.slice(64, 84),
|
hwVersion: that.uint8ArrayToString(decrypted.slice(64, 84)),
|
||||||
serialNum0: decrypted.slice(84, 100),
|
serialNum0: that.uint8ArrayToString(decrypted.slice(84, 100)),
|
||||||
serialNum1: decrypted.slice(100, 116),
|
serialNum1: that.uint8ArrayToString(decrypted.slice(100, 116)),
|
||||||
btDeviceName: decrypted.slice(116, 132),
|
btDeviceName: that.uint8ArrayToString(decrypted.slice(116, 132)),
|
||||||
battRemCap: decrypted[132],
|
electricQuantity: decrypted[132],
|
||||||
battRemCapStandby: decrypted[133],
|
electricQuantityStandby: decrypted[133],
|
||||||
restoreCounter: decrypted.slice(134, 136),
|
restoreCount: decrypted[134] * 256 + decrypted[135],
|
||||||
restoreDate: decrypted.slice(136, 140),
|
restoreDate: this.arrayToTimestamp(decrypted.slice(136, 140)),
|
||||||
icPartNo: decrypted.slice(140, 150),
|
icPartNo: that.uint8ArrayToString(decrypted.slice(140, 150)),
|
||||||
inDate: decrypted.slice(150, 154),
|
indate: this.arrayToTimestamp(decrypted.slice(150, 154)),
|
||||||
mac: decrypted.slice(154, 174),
|
mac: that.uint8ArrayToString(decrypted.slice(154, 174)),
|
||||||
featurevalueLength: decrypted[174],
|
timezoneOffset: new Date().getTimezoneOffset() * 60
|
||||||
featureValue: decrypted.slice(175, 175 + decrypted[174]),
|
|
||||||
featureEnValLength: decrypted[175 + decrypted[174]],
|
|
||||||
featureEnVal: decrypted.slice(176 + decrypted[174], 176 + decrypted[174] + decrypted[175 + decrypted[174]]),
|
|
||||||
}
|
}
|
||||||
that.updateCurrentLockInfo({
|
that.updateCurrentLockInfo({
|
||||||
...that.currentLockInfo,
|
...that.currentLockInfo,
|
||||||
|
featureValue: that.uint8ArrayToString(decrypted.slice(175, 175 + decrypted[174])),
|
||||||
|
featureSettingValue: that.uint8ArrayToString(decrypted.slice(176 + decrypted[174], 176 + decrypted[174] + decrypted[175 + decrypted[174]])),
|
||||||
|
featureSettingParams: Array.from(decrypted.slice(176 + decrypted[174] + decrypted[175 + decrypted[174]])),
|
||||||
lockConfig
|
lockConfig
|
||||||
})
|
})
|
||||||
console.log('获取锁状态成功', that.currentLockInfo.lockConfig)
|
console.log('获取锁状态成功', that.currentLockInfo.lockConfig)
|
||||||
@ -246,6 +299,13 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
...that.currentLockInfo,
|
...that.currentLockInfo,
|
||||||
token: decrypted.slice(42,46)
|
token: decrypted.slice(42,46)
|
||||||
})
|
})
|
||||||
|
if(decrypted[46] === 0) {
|
||||||
|
that.updateCurrentLockInfo({
|
||||||
|
...that.currentLockInfo,
|
||||||
|
lockUserNo: decrypted[47] * 256 + decrypted[48]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
console.log('添加用户结果', decrypted[46], that.currentLockInfo.token)
|
||||||
characteristicValueCallback({
|
characteristicValueCallback({
|
||||||
code: decrypted[46]
|
code: decrypted[46]
|
||||||
})
|
})
|
||||||
@ -282,11 +342,47 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case cmdIds.openDoor:
|
||||||
|
that.updateCurrentLockInfo({
|
||||||
|
...that.currentLockInfo,
|
||||||
|
token: decrypted.slice(2,6)
|
||||||
|
})
|
||||||
|
console.log('开门', decrypted[6], that.currentLockInfo.token)
|
||||||
|
characteristicValueCallback({
|
||||||
|
code: decrypted[6]
|
||||||
|
})
|
||||||
|
if(decrypted[6] === 0) {
|
||||||
|
updateElectricQuantityRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId,
|
||||||
|
electricQuantity: decrypted[7],
|
||||||
|
electricQuantityStandby: decrypted[9]
|
||||||
|
}).then(res => {
|
||||||
|
if(res.code === 0) {
|
||||||
|
that.updateCurrentLockInfo({
|
||||||
|
...that.currentLockInfo,
|
||||||
|
electricQuantityDate: res.data.electricQuantityDate
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
reportOpenDoorRequest({
|
||||||
|
lockId: that.currentLockInfo.lockId,
|
||||||
|
keyId: that.keyId,
|
||||||
|
}).then(res => {
|
||||||
|
console.log('上报开门结果', res)
|
||||||
|
})
|
||||||
|
updateTimezoneOffsetRequest({
|
||||||
|
timezoneOffset: new Date().getTimezoneOffset() * 60
|
||||||
|
}).then(res => {
|
||||||
|
console.log('上报时区结果', res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
that.updateCurrentLockInfo({
|
that.updateCurrentLockInfo({
|
||||||
...that.currentLockInfo,
|
...that.currentLockInfo,
|
||||||
token: decrypted.slice(2,6)
|
token: decrypted.slice(2,6)
|
||||||
})
|
})
|
||||||
|
console.log('默认结果', decrypted[6], that.currentLockInfo.token)
|
||||||
characteristicValueCallback({
|
characteristicValueCallback({
|
||||||
code: decrypted[6]
|
code: decrypted[6]
|
||||||
})
|
})
|
||||||
@ -335,6 +431,7 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
this.getBluetoothStatus()
|
this.getBluetoothStatus()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.deviceList = []
|
||||||
uni.startBluetoothDevicesDiscovery({
|
uni.startBluetoothDevicesDiscovery({
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -343,6 +440,23 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
fail: async function (res) {
|
fail: async function (res) {
|
||||||
console.log('开始搜索失败', res)
|
console.log('开始搜索失败', res)
|
||||||
|
if(res.errno === 1509008) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '安卓手机蓝牙功能需要定位权限,请前往设置开启微信的定位权限后再试',
|
||||||
|
showCancel: false,
|
||||||
|
success(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.openAppAuthorizeSetting({
|
||||||
|
success (res) {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
if(res.errCode === 10000) {
|
if(res.errCode === 10000) {
|
||||||
// 重新初始化蓝牙适配器
|
// 重新初始化蓝牙适配器
|
||||||
await that.initBluetooth()
|
await that.initBluetooth()
|
||||||
@ -362,7 +476,26 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
uni.getBluetoothDevices({
|
uni.getBluetoothDevices({
|
||||||
success(res) {
|
success(res) {
|
||||||
|
searchNumber--
|
||||||
|
if(searchNumber === 0 && searchTipFlag) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '长时间未搜索到任何设备,请确认微信的附近设备权限开启后再试',
|
||||||
|
showCancel: false,
|
||||||
|
success() {
|
||||||
|
uni.openAppAuthorizeSetting({
|
||||||
|
success (res) {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const deviceList = res.devices
|
const deviceList = res.devices
|
||||||
|
if(deviceList.length !== 0) {
|
||||||
|
searchTipFlag = false
|
||||||
|
}
|
||||||
that.deviceList = []
|
that.deviceList = []
|
||||||
for(let i = 0; i < deviceList.length; i++) {
|
for(let i = 0; i < deviceList.length; i++) {
|
||||||
if(deviceList[i]?.advertisServiceUUIDs) {
|
if(deviceList[i]?.advertisServiceUUIDs) {
|
||||||
@ -386,6 +519,8 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
// 停止搜索蓝牙设备
|
// 停止搜索蓝牙设备
|
||||||
stopGetBluetoothDevices() {
|
stopGetBluetoothDevices() {
|
||||||
|
searchNumber = 10
|
||||||
|
searchTipFlag = true
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
uni.stopBluetoothDevicesDiscovery()
|
uni.stopBluetoothDevicesDiscovery()
|
||||||
},
|
},
|
||||||
@ -396,7 +531,15 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
title: '提示',
|
title: '提示',
|
||||||
content: '蓝牙尚未打开,请先打开蓝牙',
|
content: '蓝牙尚未打开,请先打开蓝牙',
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
confirmText: '确定',
|
success(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
wx.openSystemBluetoothSetting({
|
||||||
|
success (res) {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else if(this.bluetoothStatus === 2 || this.bluetoothStatus === 3) {
|
} else if(this.bluetoothStatus === 2 || this.bluetoothStatus === 3) {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
@ -466,7 +609,7 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
success (res) {
|
success (res) {
|
||||||
let serviceId
|
let serviceId
|
||||||
for(let i = 0; i < res.services.length; i++) {
|
for(let i = 0; i < res.services.length; i++) {
|
||||||
if(res.services[i].isPrimary) {
|
if(res.services[i].uuid.indexOf('FFF0') !== -1) {
|
||||||
serviceId = res.services[i].uuid
|
serviceId = res.services[i].uuid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,6 +663,10 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
fail(res) {
|
fail(res) {
|
||||||
|
if(res.errno === 1509007) {
|
||||||
|
resolve(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '连接失败,请靠近设备并保持设备处于唤醒状态',
|
title: '连接失败,请靠近设备并保持设备处于唤醒状态',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
@ -564,23 +711,127 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 查找设备并连接
|
||||||
|
async searchAndConnectDevice() {
|
||||||
|
const that = this
|
||||||
|
let timer1
|
||||||
|
let timer2
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.startBluetoothDevicesDiscovery({
|
||||||
|
success: function (res) {
|
||||||
|
timer2 = setTimeout(() => {
|
||||||
|
uni.stopBluetoothDevicesDiscovery()
|
||||||
|
clearInterval(timer1)
|
||||||
|
resolve(false)
|
||||||
|
}, 10500)
|
||||||
|
timer1 = setInterval(() => {
|
||||||
|
uni.getBluetoothDevices({
|
||||||
|
success(res) {
|
||||||
|
const deviceList = res.devices
|
||||||
|
for(let i = 0; i < deviceList.length; i++) {
|
||||||
|
if(deviceList[i]?.name === that.currentLockInfo.name) {
|
||||||
|
const uuid = deviceList[i]?.advertisServiceUUIDs[0]
|
||||||
|
if(uuid && uuid.slice(2,8)==='758824' && uuid.slice(30,32)==='01') {
|
||||||
|
uni.stopBluetoothDevicesDiscovery()
|
||||||
|
clearTimeout(timer2)
|
||||||
|
clearInterval(timer1)
|
||||||
|
resolve(deviceList[i].deviceId)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: async function (res) {
|
||||||
|
console.log('获取设备列表失败', res)
|
||||||
|
if(res.errCode === 10000) {
|
||||||
|
// 重新初始化蓝牙适配器
|
||||||
|
await that.initBluetooth()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
fail: async function (res) {
|
||||||
|
console.log('开始搜索失败', res)
|
||||||
|
if(res.errCode === 10000) {
|
||||||
|
// 重新初始化蓝牙适配器
|
||||||
|
await that.initBluetooth()
|
||||||
|
that.searchAndConnectDevice()
|
||||||
|
} else {
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 检查是否已添加为用户
|
||||||
|
async checkLockUser(flag = false) {
|
||||||
|
console.log('检查是否已添加为用户', this.currentLockInfo.lockUserNo)
|
||||||
|
if(this.currentLockInfo.lockUserNo === 0 || flag) {
|
||||||
|
const timestamp = parseInt(new Date().getTime() / 1000)
|
||||||
|
const password = (Math.floor(Math.random() * 900000) + 100000).toString()
|
||||||
|
console.log('用户未添加,开始添加用户')
|
||||||
|
const { code: addUserCode } = await this.addLockUser({
|
||||||
|
name: this.currentLockInfo.name,
|
||||||
|
keyId: this.keyId,
|
||||||
|
authUid: this.currentLockInfo.senderUserId.toString(),
|
||||||
|
uid: this.currentLockInfo.uid.toString(),
|
||||||
|
openMode: 1,
|
||||||
|
keyType: 0,
|
||||||
|
startDate: this.currentLockInfo.startDate === 0 ? timestamp : this.currentLockInfo.startDate,
|
||||||
|
expireDate: this.currentLockInfo.endDate === 0 ? 0xffffffff : this.currentLockInfo.endDate,
|
||||||
|
useCountLimit: this.currentLockInfo.keyType === 3 ? 1 : 0xffff,
|
||||||
|
isRound: 0,
|
||||||
|
weekRound: 0,
|
||||||
|
startHour: 0,
|
||||||
|
startMin: 0,
|
||||||
|
endHour: 0,
|
||||||
|
endMin: 0,
|
||||||
|
role: 0,
|
||||||
|
password
|
||||||
|
})
|
||||||
|
console.log('添加用户蓝牙结果', addUserCode)
|
||||||
|
if(addUserCode === 0) {
|
||||||
|
const { code } = await updateLockUserNoRequest({
|
||||||
|
keyId: this.keyId,
|
||||||
|
lockUserNo: this.currentLockInfo.lockUserNo
|
||||||
|
})
|
||||||
|
console.log('添加用户请求结果', code)
|
||||||
|
return true
|
||||||
|
} else if(addUserCode === 0x0c) {
|
||||||
|
console.log('用户达上限,开始清理用户')
|
||||||
|
const { code: requestCode, data: requestData } = await getUserNoListRequest({
|
||||||
|
lockId: this.currentLockInfo.lockId
|
||||||
|
})
|
||||||
|
console.log('获取用户列表请求结果', requestCode, requestData)
|
||||||
|
if(requestCode !== 0) return false
|
||||||
|
const userNoList = requestData.userNos
|
||||||
|
const { code: cleanCode } = await this.cleanLockUser({
|
||||||
|
name: this.currentLockInfo.name,
|
||||||
|
keyId: this.keyId,
|
||||||
|
authUid: this.currentLockInfo.senderUserId.toString(),
|
||||||
|
uid: this.currentLockInfo.uid.toString(),
|
||||||
|
userNoList: userNoList
|
||||||
|
})
|
||||||
|
console.log('清理用户蓝牙结果', cleanCode)
|
||||||
|
if(cleanCode === 0) {
|
||||||
|
return await this.checkLockUser()
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if(addUserCode === 0x0f) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
// 写入特征值
|
// 写入特征值
|
||||||
async writeBLECharacteristicValue(binaryData) {
|
async writeBLECharacteristicValue(binaryData) {
|
||||||
const that = this
|
const that = this
|
||||||
|
|
||||||
// 确认蓝牙状态正常
|
|
||||||
if(this.bluetoothStatus !== 0) {
|
|
||||||
console.log('写入未执行', this.bluetoothStatus)
|
|
||||||
this.getBluetoothStatus()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认设备连接正常
|
|
||||||
if(!that.currentLockInfo.connected) {
|
|
||||||
const result = await that.connectBluetoothDevice()
|
|
||||||
if(!result) return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('设备ID:', that.currentLockInfo.deviceId)
|
console.log('设备ID:', that.currentLockInfo.deviceId)
|
||||||
console.log('设备名称:', that.currentLockInfo.name)
|
console.log('设备名称:', that.currentLockInfo.name)
|
||||||
console.log('设备主服务:', that.currentLockInfo.serviceId)
|
console.log('设备主服务:', that.currentLockInfo.serviceId)
|
||||||
@ -668,6 +919,37 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
// 获取公钥
|
// 获取公钥
|
||||||
async getPublicKey(name) {
|
async getPublicKey(name) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const headArray = this.createPackageHeader(0, 42)
|
const headArray = this.createPackageHeader(0, 42)
|
||||||
const conentArray = new Uint8Array(42)
|
const conentArray = new Uint8Array(42)
|
||||||
|
|
||||||
@ -685,6 +967,37 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
// 获取私钥
|
// 获取私钥
|
||||||
async getCommKey(name, keyId, authUid, nowTime) {
|
async getCommKey(name, keyId, authUid, nowTime) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const length = 2 + 40 + 40 + 20 + 4 + 1 + 16
|
const length = 2 + 40 + 40 + 20 + 4 + 1 + 16
|
||||||
const headArray = this.createPackageHeader(2, length)
|
const headArray = this.createPackageHeader(2, length)
|
||||||
const conentArray = new Uint8Array(length)
|
const conentArray = new Uint8Array(length)
|
||||||
@ -736,6 +1049,37 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
// 获取锁状态
|
// 获取锁状态
|
||||||
async getLockStatus(data) {
|
async getLockStatus(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { name, uid, nowTime, localTime } = data
|
const { name, uid, nowTime, localTime } = data
|
||||||
const length = 2 + 40 + 20 + 4 + 4
|
const length = 2 + 40 + 20 + 4 + 4
|
||||||
const headArray = this.createPackageHeader(3, length)
|
const headArray = this.createPackageHeader(3, length)
|
||||||
@ -769,10 +1113,46 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
array[3] = (timestamp & 0xff)
|
array[3] = (timestamp & 0xff)
|
||||||
return array
|
return array
|
||||||
},
|
},
|
||||||
|
// 二进制转时间戳
|
||||||
|
arrayToTimestamp(array) {
|
||||||
|
const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]
|
||||||
|
return timestamp >>> 0
|
||||||
|
},
|
||||||
// 添加用户
|
// 添加用户
|
||||||
async addLockUser(data) {
|
async addLockUser(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { name, authUid, uid, keyId, openMode, keyType, startDate, expireDate, useCountLimit, isRound, weekRound,
|
const { name, authUid, uid, keyId, openMode, keyType, startDate, expireDate, useCountLimit, isRound, weekRound,
|
||||||
startHour, startMin, endHour, endMin, role, password, publicKey, commKey } = data
|
startHour, startMin, endHour, endMin, role, password } = data
|
||||||
const length = 2 + 40 + 20 + 40 + 20 + 1 + 1 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 20 + 4 + 1 + 16
|
const length = 2 + 40 + 20 + 40 + 20 + 1 + 1 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 20 + 4 + 1 + 16
|
||||||
const headArray = this.createPackageHeader(3, length)
|
const headArray = this.createPackageHeader(3, length)
|
||||||
const conentArray = new Uint8Array(length)
|
const conentArray = new Uint8Array(length)
|
||||||
@ -825,24 +1205,33 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
|
|
||||||
conentArray.set(md5Array, 166)
|
conentArray.set(md5Array, 166)
|
||||||
|
|
||||||
const cebArray = sm4.encrypt(conentArray, commKey, { mode: 'ecb', output: 'array' })
|
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
||||||
|
|
||||||
const packageArray = this.createPackageEnd(headArray, cebArray)
|
const packageArray = this.createPackageEnd(headArray, cebArray)
|
||||||
await this.writeBLECharacteristicValue(packageArray)
|
await this.writeBLECharacteristicValue(packageArray, false)
|
||||||
return this.getWriteResult(this.addLockUser, data)
|
return this.getWriteResult(this.addLockUser, data)
|
||||||
},
|
},
|
||||||
// 获取写入结果
|
// 获取写入结果
|
||||||
getWriteResult(request, params) {
|
getWriteResult(request, params) {
|
||||||
|
const that = this
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const timer = setTimeout(() => {
|
const getWriteResultTimer = setTimeout(() => {
|
||||||
resolve({ code: -1 })
|
resolve({ code: -1 })
|
||||||
}, 10000)
|
}, 20000)
|
||||||
characteristicValueCallback = async (data) => {
|
characteristicValueCallback = async (data) => {
|
||||||
// code 6 token过期,重新获取
|
// code 6 token过期,重新获取
|
||||||
if(data.code === 6) {
|
if(data.code === 6) {
|
||||||
resolve(await request(params))
|
resolve(await request(params))
|
||||||
|
} else if(data.code === 4) {
|
||||||
|
const checkResult = await that.checkLockUser(true)
|
||||||
|
if(checkResult) {
|
||||||
|
resolve(await request(params))
|
||||||
|
} else {
|
||||||
|
clearTimeout(getWriteResultTimer)
|
||||||
|
resolve(data)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
clearTimeout(timer)
|
clearTimeout(getWriteResultTimer)
|
||||||
resolve(data)
|
resolve(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -850,6 +1239,45 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
// 开门
|
// 开门
|
||||||
async openDoor(data) {
|
async openDoor(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已添加为用户
|
||||||
|
const checkResult = await this.checkLockUser()
|
||||||
|
if (!checkResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { name, uid, openMode, openTime, onlineToken } = data
|
const { name, uid, openMode, openTime, onlineToken } = data
|
||||||
const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
|
const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
|
||||||
const headArray = this.createPackageHeader(3, length)
|
const headArray = this.createPackageHeader(3, length)
|
||||||
@ -870,11 +1298,14 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
|
|
||||||
conentArray.set(this.timestampToArray(openTime), 63)
|
conentArray.set(this.timestampToArray(openTime), 63)
|
||||||
|
|
||||||
conentArray.set(this.currentLockInfo.token, 67)
|
console.log('开门时token', this.currentLockInfo.token)
|
||||||
|
|
||||||
|
conentArray.set(this.currentLockInfo.token || this.timestampToArray(openTime), 67)
|
||||||
|
|
||||||
conentArray[71] = 16
|
conentArray[71] = 16
|
||||||
|
|
||||||
const md5Array = this.md5Encrypte(name + uid, this.currentLockInfo.token, this.currentLockInfo.signKey)
|
|
||||||
|
const md5Array = this.md5Encrypte(name + uid, this.currentLockInfo.token || this.timestampToArray(openTime), this.currentLockInfo.signKey)
|
||||||
|
|
||||||
conentArray.set(md5Array, 72)
|
conentArray.set(md5Array, 72)
|
||||||
|
|
||||||
@ -885,13 +1316,132 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
||||||
|
|
||||||
const packageArray = this.createPackageEnd(headArray, cebArray)
|
const packageArray = this.createPackageEnd(headArray, cebArray)
|
||||||
|
this.writeBLECharacteristicValue(packageArray)
|
||||||
await this.writeBLECharacteristicValue(packageArray)
|
|
||||||
|
|
||||||
return this.getWriteResult(this.openDoor, data)
|
return this.getWriteResult(this.openDoor, data)
|
||||||
},
|
},
|
||||||
|
// 清理用户
|
||||||
|
async cleanLockUser(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, authUid, keyId, uid, userNoList } = data
|
||||||
|
const length = 2 + 40 + 20 + 40 + 20 + 2 + userNoList.length + 4 + 1 + 16
|
||||||
|
|
||||||
|
const headArray = this.createPackageHeader(3, length)
|
||||||
|
const conentArray = new Uint8Array(length)
|
||||||
|
|
||||||
|
conentArray[0] = cmdIds.cleanUser / 256
|
||||||
|
conentArray[1] = cmdIds.cleanUser % 256
|
||||||
|
|
||||||
|
for (let i = 0; i < name.length; i++) {
|
||||||
|
conentArray[i + 2] = name.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < authUid.length; i++) {
|
||||||
|
conentArray[i + 42] = authUid.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < keyId.length; i++) {
|
||||||
|
conentArray[i + 62] = keyId.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < uid.length; i++) {
|
||||||
|
conentArray[i + 102] = uid.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
conentArray[122] = userNoList.length / 256
|
||||||
|
conentArray[123] = userNoList.length % 256
|
||||||
|
|
||||||
|
for (let i = 0; i < userNoList.length; i++) {
|
||||||
|
conentArray[i + 124] = userNoList[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
conentArray.set(this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), 124 + userNoList.length)
|
||||||
|
|
||||||
|
conentArray[128 + userNoList.length] = 16
|
||||||
|
|
||||||
|
const md5Array = this.md5Encrypte(authUid + keyId, this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), this.currentLockInfo.publicKey)
|
||||||
|
|
||||||
|
conentArray.set(md5Array, 129 + userNoList.length)
|
||||||
|
|
||||||
|
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
||||||
|
|
||||||
|
const packageArray = this.createPackageEnd(headArray, cebArray)
|
||||||
|
|
||||||
|
await this.writeBLECharacteristicValue(packageArray)
|
||||||
|
|
||||||
|
return this.getWriteResult(this.cleanLockUser, data)
|
||||||
|
},
|
||||||
// 恢复出厂设置
|
// 恢复出厂设置
|
||||||
async resetDevice(data) {
|
async resetDevice(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已添加为用户
|
||||||
|
const checkResult = await this.checkLockUser()
|
||||||
|
if (!checkResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { name, authUid, keyId } = data
|
const { name, authUid, keyId } = data
|
||||||
const length = 2 + 40 + 20 + 4 + 1 + 16
|
const length = 2 + 40 + 20 + 4 + 1 + 16
|
||||||
const headArray = this.createPackageHeader(3, length)
|
const headArray = this.createPackageHeader(3, length)
|
||||||
@ -907,10 +1457,10 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
for(let i = 0; i < authUid.length; i++) {
|
for(let i = 0; i < authUid.length; i++) {
|
||||||
conentArray[i + 42] = authUid.charCodeAt(i)
|
conentArray[i + 42] = authUid.charCodeAt(i)
|
||||||
}
|
}
|
||||||
conentArray.set(this.currentLockInfo.token, 62)
|
conentArray.set(this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), 62)
|
||||||
conentArray[66] = 16
|
conentArray[66] = 16
|
||||||
|
|
||||||
const md5Array = this.md5Encrypte(name, this.currentLockInfo.token, this.currentLockInfo.publicKey)
|
const md5Array = this.md5Encrypte(name, this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), this.currentLockInfo.publicKey)
|
||||||
conentArray.set(md5Array, 67)
|
conentArray.set(md5Array, 67)
|
||||||
|
|
||||||
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
||||||
@ -923,6 +1473,45 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
},
|
},
|
||||||
// 重置开锁密码
|
// 重置开锁密码
|
||||||
async resetLockPassword(data) {
|
async resetLockPassword(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已添加为用户
|
||||||
|
const checkResult = await this.checkLockUser()
|
||||||
|
if (!checkResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { keyId, uid } = data
|
const { keyId, uid } = data
|
||||||
const length = 2 + 1 + 1 + 40 + 20 + 4 + 1 + 16
|
const length = 2 + 1 + 1 + 40 + 20 + 4 + 1 + 16
|
||||||
const headArray = this.createPackageHeader(3, length)
|
const headArray = this.createPackageHeader(3, length)
|
||||||
@ -944,11 +1533,11 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
conentArray[i + 44] = uid.charCodeAt(i)
|
conentArray[i + 44] = uid.charCodeAt(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
conentArray.set(this.currentLockInfo.token, 64)
|
conentArray.set(this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), 64)
|
||||||
|
|
||||||
conentArray[68] = 16
|
conentArray[68] = 16
|
||||||
|
|
||||||
const md5Array = this.md5Encrypte(keyId + uid, this.currentLockInfo.token, this.currentLockInfo.signKey)
|
const md5Array = this.md5Encrypte(keyId + uid, this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), this.currentLockInfo.signKey)
|
||||||
|
|
||||||
conentArray.set(md5Array, 69)
|
conentArray.set(md5Array, 69)
|
||||||
|
|
||||||
@ -960,13 +1549,47 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
|
|
||||||
return this.getWriteResult(this.resetLockPassword, data)
|
return this.getWriteResult(this.resetLockPassword, data)
|
||||||
},
|
},
|
||||||
// 清理用户
|
|
||||||
async cleanUser(data) {
|
|
||||||
const { name, authUid, keyId, uid, userNoLength, userNoList } = data
|
|
||||||
// const length = 2 + 40 + 20 + 40 + 20 + 2 + userNoLength * 4 + 1 + 16
|
|
||||||
},
|
|
||||||
// 设置密码
|
// 设置密码
|
||||||
async setLockPassword(data) {
|
async setLockPassword(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if(this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if(!this.currentLockInfo.connected) {
|
||||||
|
const srerchResult = await this.searchAndConnectDevice()
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: srerchResult
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
if(!srerchResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if(!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已添加为用户
|
||||||
|
const checkResult = await this.checkLockUser()
|
||||||
|
if (!checkResult) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { keyId, uid, pwdNo, operate, isAdmin, pwd, userCountLimit, startTime, endTime} = data
|
const { keyId, uid, pwdNo, operate, isAdmin, pwd, userCountLimit, startTime, endTime} = data
|
||||||
const length = 2 + 1 + 1 + 40 + 20 + 2 + 1 + 1 + 20 + 2 + 4 + 4 + 4 + 1 + 16
|
const length = 2 + 1 + 1 + 40 + 20 + 2 + 1 + 1 + 20 + 2 + 4 + 4 + 4 + 1 + 16
|
||||||
const headArray = this.createPackageHeader(3, length)
|
const headArray = this.createPackageHeader(3, length)
|
||||||
@ -1001,14 +1624,14 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
conentArray[88] = userCountLimit / 256
|
conentArray[88] = userCountLimit / 256
|
||||||
conentArray[89] = userCountLimit % 256
|
conentArray[89] = userCountLimit % 256
|
||||||
|
|
||||||
conentArray.set(this.currentLockInfo.token, 90)
|
conentArray.set(this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), 90)
|
||||||
|
|
||||||
conentArray.set(this.timestampToArray(startTime), 94)
|
conentArray.set(this.timestampToArray(startTime), 94)
|
||||||
conentArray.set(this.timestampToArray(endTime), 98)
|
conentArray.set(this.timestampToArray(endTime), 98)
|
||||||
|
|
||||||
conentArray[102] = 16
|
conentArray[102] = 16
|
||||||
|
|
||||||
const md5Array = this.md5Encrypte(keyId + uid, this.currentLockInfo.token, this.currentLockInfo.signKey)
|
const md5Array = this.md5Encrypte(keyId + uid, this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), this.currentLockInfo.signKey)
|
||||||
|
|
||||||
conentArray.set(md5Array, 103)
|
conentArray.set(md5Array, 103)
|
||||||
|
|
||||||
|
|||||||
115
stores/lock.js
@ -3,6 +3,9 @@
|
|||||||
*/
|
*/
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { getLockListRequest } from '@/api/lock'
|
import { getLockListRequest } from '@/api/lock'
|
||||||
|
import { getPsaawordListRequest } from '@/api/keyboardPwd'
|
||||||
|
import { timeFormat } from 'uview-plus'
|
||||||
|
import { getKeyListRequest } from '@/api/key'
|
||||||
|
|
||||||
export const useLockStore = defineStore('lock', {
|
export const useLockStore = defineStore('lock', {
|
||||||
state() {
|
state() {
|
||||||
@ -10,10 +13,59 @@ export const useLockStore = defineStore('lock', {
|
|||||||
// 锁列表
|
// 锁列表
|
||||||
lockList: [],
|
lockList: [],
|
||||||
// 锁总数
|
// 锁总数
|
||||||
lockTotal: 0
|
lockTotal: 0,
|
||||||
|
// 锁列表搜索数据
|
||||||
|
lockSearch: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 50,
|
||||||
|
searchStr: ''
|
||||||
|
},
|
||||||
|
// 密码列表
|
||||||
|
passwordList: [],
|
||||||
|
// 密码总数
|
||||||
|
passwordTotal: 0,
|
||||||
|
// 当前密码详情
|
||||||
|
currentPasswordInfo: {},
|
||||||
|
// 密码列表搜索数据
|
||||||
|
passwordSearch: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 50,
|
||||||
|
searchStr: ''
|
||||||
|
},
|
||||||
|
// 电子钥匙总数
|
||||||
|
keyTotal: 0,
|
||||||
|
// 电子钥匙列表
|
||||||
|
keyList: [],
|
||||||
|
// 当前电子钥匙详情
|
||||||
|
currentKeyInfo: {},
|
||||||
|
// 电子钥匙列表搜索数据
|
||||||
|
keySearch: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 50,
|
||||||
|
searchStr: '',
|
||||||
|
endDate: '0',
|
||||||
|
startDate: '0',
|
||||||
|
keyStatus: [110401,110402,110412],
|
||||||
|
keyRight: 0
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
updateLockSearch(search) {
|
||||||
|
this.lockSearch = search
|
||||||
|
},
|
||||||
|
updatePasswordSearch(search) {
|
||||||
|
this.passwordSearch = search
|
||||||
|
},
|
||||||
|
updateKeySearch(search) {
|
||||||
|
this.keySearch = search
|
||||||
|
},
|
||||||
|
updateCurrentKeyInfo(info) {
|
||||||
|
this.currentKeyInfo = info
|
||||||
|
},
|
||||||
|
updateCurrentPasswordInfo(info) {
|
||||||
|
this.currentPasswordInfo = info
|
||||||
|
},
|
||||||
getRole(userType) {
|
getRole(userType) {
|
||||||
if(userType === 110301) {
|
if(userType === 110301) {
|
||||||
return '超级管理员'
|
return '超级管理员'
|
||||||
@ -21,6 +73,17 @@ export const useLockStore = defineStore('lock', {
|
|||||||
return '普通用户'
|
return '普通用户'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getKeyStatus(keyStatus) {
|
||||||
|
if(keyStatus === 110401) {
|
||||||
|
return '正常'
|
||||||
|
} else if(keyStatus === 110402) {
|
||||||
|
return '待接收'
|
||||||
|
} else if(keyStatus === 110412) {
|
||||||
|
return '已过期'
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
getTimeLimit(keyType) {
|
getTimeLimit(keyType) {
|
||||||
if(keyType === 1) {
|
if(keyType === 1) {
|
||||||
return '永久'
|
return '永久'
|
||||||
@ -49,6 +112,56 @@ export const useLockStore = defineStore('lock', {
|
|||||||
})
|
})
|
||||||
return { code, message }
|
return { code, message }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async getPasswordList(params) {
|
||||||
|
const { code, data, message } = await getPsaawordListRequest(params)
|
||||||
|
if(code === 0) {
|
||||||
|
this.passwordTotal = data.total
|
||||||
|
for(let i = 0; i < data.list.length; i++) {
|
||||||
|
if(data.list[i].keyboardPwdType === 2) {
|
||||||
|
data.list[i].timeText = `${timeFormat(new Date(data.list[i].created_at), 'yyyy-mm-dd h:M')} 永久`
|
||||||
|
} else if(data.list[i].keyboardPwdType === 3) {
|
||||||
|
data.list[i].timeText = `${data.list[i].validTimeStr} 限时`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(params.pageNo === 1) {
|
||||||
|
this.passwordList = data.list
|
||||||
|
} else {
|
||||||
|
this.passwordList = this.passwordList.concat(data.list)
|
||||||
|
}
|
||||||
|
return { code }
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return { code, message }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getKeyList(params) {
|
||||||
|
const { code, data, message } = await getKeyListRequest(params)
|
||||||
|
if(code === 0) {
|
||||||
|
this.keyTotal = data.total
|
||||||
|
for(let i = 0; i < data.list.length; i++) {
|
||||||
|
if(data.list[i].keyType === 2) {
|
||||||
|
data.list[i].timeText = `${timeFormat(new Date(data.list[i].startDate), 'yyyy-mm-dd h:M')} - ${timeFormat(new Date(data.list[i].endDate), 'yyyy-mm-dd h:M')} 限时`
|
||||||
|
} else {
|
||||||
|
data.list[i].timeText = `${timeFormat(new Date(data.list[i].startDate), 'yyyy-mm-dd h:M')} 永久`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(params.pageNo === 1) {
|
||||||
|
this.keyList = data.list
|
||||||
|
} else {
|
||||||
|
this.keyList = this.keyList.concat(data.list)
|
||||||
|
}
|
||||||
|
return { code }
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return { code, message }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
* @description 用户信息数据持久化
|
* @description 用户信息数据持久化
|
||||||
*/
|
*/
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { getUserInfoRequest } from '@/api/user'
|
import { getUserInfoRequest, loginRequest, phoneLoginRequest } from '@/api/user'
|
||||||
import { useLockStore } from '@/stores/lock'
|
import { useLockStore } from '@/stores/lock'
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', {
|
export const useUserStore = defineStore('user', {
|
||||||
@ -21,18 +21,57 @@ export const useUserStore = defineStore('user', {
|
|||||||
updateLoginStatus(status) {
|
updateLoginStatus(status) {
|
||||||
this.isLogin = status
|
this.isLogin = status
|
||||||
},
|
},
|
||||||
async login() {
|
// 获取用户信息
|
||||||
uni.setStorageSync('token', '3021|MZv7iEf0NwjCPSGx4QWs37zOjeVN3GrSJ2v7D56L7db1fcc5')
|
async getUserInfo() {
|
||||||
const { code, data } = await getUserInfoRequest()
|
const { code, data } = await getUserInfoRequest()
|
||||||
await useLockStore().getLockList({
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 50
|
|
||||||
})
|
|
||||||
if(code === 0) {
|
if(code === 0) {
|
||||||
this.updateUserInfo(data)
|
this.updateUserInfo(data)
|
||||||
|
this.updateLoginStatus(true)
|
||||||
}
|
}
|
||||||
this.isLogin = true
|
return code
|
||||||
return this.isLogin
|
},
|
||||||
|
async phoneLogin(params) {
|
||||||
|
const { iv, encryptedData } = params
|
||||||
|
const openid = uni.getStorageSync('openid')
|
||||||
|
const { code, data, message } = await phoneLoginRequest({ iv, encryptedData, openid })
|
||||||
|
if(code === 0) {
|
||||||
|
uni.setStorageSync('token', data.accessToken)
|
||||||
|
this.getUserInfo()
|
||||||
|
useLockStore().updateLockSearch({
|
||||||
|
...useLockStore().lockSearch,
|
||||||
|
pageNo: 1
|
||||||
|
})
|
||||||
|
useLockStore().getLockList(useLockStore().lockSearch)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async checkSession() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.checkSession({
|
||||||
|
success() {
|
||||||
|
resolve(true)
|
||||||
|
},
|
||||||
|
fail() {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
resolve(false)
|
||||||
|
},
|
||||||
|
fail() {
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
4
uni.scss
@ -77,3 +77,7 @@ $uni-color-subtitle: #555555; // 二级标题颜色
|
|||||||
$uni-font-size-subtitle:26px;
|
$uni-font-size-subtitle:26px;
|
||||||
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||||
$uni-font-size-paragraph:15px;
|
$uni-font-size-paragraph:15px;
|
||||||
|
|
||||||
|
.u-picker__view {
|
||||||
|
height: 500rpx !important;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import baseConfig from '@/config/env'
|
import env from '@/config/env'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* config
|
* config
|
||||||
@ -12,9 +12,12 @@ import baseConfig from '@/config/env'
|
|||||||
|
|
||||||
const request = (config) => {
|
const request = (config) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
const baseConfig = env[getApp().globalData.getEnvConfig()]
|
||||||
|
|
||||||
const token = config?.token ? config.token : uni.getStorageSync('token')
|
const token = config?.token ? config.token : uni.getStorageSync('token')
|
||||||
const headerDefault = {
|
const headerDefault = {
|
||||||
version: baseConfig.version,
|
appid: getApp().globalData.appid,
|
||||||
|
version: baseConfig.version + '+' + baseConfig.buildNumber,
|
||||||
authorization: `Bearer ${token}`
|
authorization: `Bearer ${token}`
|
||||||
}
|
}
|
||||||
const URL = config.baseUrl ? config.baseUrl + config.url : baseConfig.baseUrl + config.url
|
const URL = config.baseUrl ? config.baseUrl + config.url : baseConfig.baseUrl + config.url
|
||||||
@ -62,18 +65,14 @@ const request = (config) => {
|
|||||||
resolve({ code: -1, data, message: '网络不太好哦,请稍后再试' })
|
resolve({ code: -1, data, message: '网络不太好哦,请稍后再试' })
|
||||||
},
|
},
|
||||||
async complete(res) {
|
async complete(res) {
|
||||||
const env =
|
|
||||||
baseConfig.baseUrl.indexOf('test') !== -1
|
|
||||||
? 'test'
|
|
||||||
: baseConfig.baseUrl.indexOf('pre') !== -1
|
|
||||||
? 'pre'
|
|
||||||
: 'release'
|
|
||||||
console.log(URL.substring(baseConfig.baseUrl.length + 1), {
|
console.log(URL.substring(baseConfig.baseUrl.length + 1), {
|
||||||
|
env: getApp().globalData.getEnvConfig(),
|
||||||
url: URL.substring(baseConfig.baseUrl.length + 1),
|
url: URL.substring(baseConfig.baseUrl.length + 1),
|
||||||
req: config?.data || {},
|
req: config?.data || {},
|
||||||
code: res?.data?.errorCode,
|
code: res?.data?.errorCode,
|
||||||
res: res?.data?.data,
|
res: res?.data?.data,
|
||||||
token: header?.authorization || '',
|
token: header?.authorization || '',
|
||||||
|
message: res?.data?.errorMsg,
|
||||||
duration: new Date().getTime() - timestamp
|
duration: new Date().getTime() - timestamp
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||