Merge branch 'fanpeng' into 'master'
完成绑定设备全部功能 See merge request StarlockTeam/wx-starlock!2
21
App.vue
@ -10,6 +10,25 @@
|
||||
// 更新登录状态
|
||||
updateIsLogin(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: {
|
||||
@ -22,7 +41,7 @@
|
||||
const checkResult = await this.checkSetting()
|
||||
console.log(checkResult)
|
||||
if(checkResult === true) {
|
||||
this.initAndListenBluetooth()
|
||||
this.initAndListenBluetooth(false)
|
||||
}
|
||||
},
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定锁管理员
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
// 登录
|
||||
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'
|
||||
|
||||
const version = '1.0.0.0'
|
||||
const version = '1.0.0'
|
||||
const buildNumber = 0
|
||||
|
||||
const DEV = {
|
||||
name: '开发',
|
||||
baseUrl: 'https://dev.lock.star-lock.cn/api',
|
||||
webviewBaseUrl: 'https://dev.lock.star-lock.cn',
|
||||
version: version
|
||||
version,
|
||||
buildNumber
|
||||
}
|
||||
const PRE = {
|
||||
name: '预发',
|
||||
baseUrl: 'https://pre.lock.star-lock.cn/api',
|
||||
webviewBaseUrl: 'https://pre.lock.star-lock.cn',
|
||||
version: version
|
||||
version,
|
||||
buildNumber
|
||||
}
|
||||
|
||||
const PROD = {
|
||||
name: '线上',
|
||||
baseUrl: '',
|
||||
version: version
|
||||
baseUrl: 'https://lock.xhjcn.ltd/api',
|
||||
webviewBaseUrl: 'https://lock.xhjcn.ltd',
|
||||
version,
|
||||
buildNumber
|
||||
}
|
||||
|
||||
// 更换环境的时候 切换导出就行
|
||||
export default PRE
|
||||
export default { DEV, PRE, PROD }
|
||||
|
||||
@ -5,49 +5,6 @@
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"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" : {
|
||||
"appid" : "wx9829a39e65550757",
|
||||
@ -55,20 +12,17 @@
|
||||
"urlCheck" : true,
|
||||
"minified" : true
|
||||
},
|
||||
"permission" : {
|
||||
"scope.bluetooth" : {
|
||||
"desc" : "蓝牙将用于控制和管理您的智能门锁"
|
||||
},
|
||||
"scope.userLocation" : {
|
||||
"desc" : "获取您的位置信息将用于智能门锁的位置服务"
|
||||
}
|
||||
},
|
||||
"requiredPrivateInfos" : [ "getLocation" ],
|
||||
"usingComponents" : true,
|
||||
"lazyCodeLoading" : "requiredComponents"
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
|
||||
132
pages.json
@ -9,123 +9,139 @@
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/home/home",
|
||||
"path": "pages/home/home"
|
||||
},
|
||||
{
|
||||
"path": "pages/selectAddress/selectAddress",
|
||||
"style": {
|
||||
"navigationBarTitleText": "星星锁",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "锁地址",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/mine",
|
||||
"style": {
|
||||
"navigationBarTitleText": "星星锁",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/index"
|
||||
"path": "pages/mine/mine"
|
||||
},
|
||||
{
|
||||
"path": "pages/userInfo/userInfo",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人信息",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "个人信息"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/updateName/updateName",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改昵称",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "修改昵称"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/updatePassword/updatePassword",
|
||||
"style": {
|
||||
"navigationBarTitleText": "重置密码",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "重置密码"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/updateEmail/updateEmail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改邮箱",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "修改邮箱"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/verifyEmail/verifyEmail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "验证邮箱",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "验证邮箱"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/safeQuestion/safeQuestion",
|
||||
"style": {
|
||||
"navigationBarTitleText": "安全问题",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "安全问题"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/updateSafeQuestion/updateSafeQuestion",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改安全问题",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "修改安全问题"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/webview/webview",
|
||||
"style": {
|
||||
"navigationBarTitleText": "介绍",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "介绍"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/lockDetail/lockDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "星星锁",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"navigationBarTitleText": "星星锁"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/bindLock/bindLock",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加锁"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/searchDevice/searchDevice",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"navigationStyle": "default"
|
||||
"disableScroll": true,
|
||||
"navigationBarTitleText": "附近设备"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarTitleText": "星星锁",
|
||||
"navigationBarBackgroundColor": "#F3F3F3",
|
||||
"navigationBarBackgroundColor": "#63b8af",
|
||||
"backgroundColor": "#F3F3F3",
|
||||
"navigationStyle": "custom"
|
||||
"navigationStyle": "default"
|
||||
},
|
||||
"tabBar": {
|
||||
"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 v-if="!penging">
|
||||
<view v-if="isLogin">
|
||||
<scroll-view scroll-y="true" :style="{ height: 'calc(100vh)' }" lower-threshold="100"
|
||||
@refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
|
||||
<scroll-view v-if="deviceInfo" scroll-y="true" :style="{ height: deviceInfo.windowHeight + 'px' }"
|
||||
lower-threshold="100" @refresherrefresh="refresherList" :refresher-enabled="true" @scrolltolower="nextPage"
|
||||
:refresher-triggered="refresherTriggered">
|
||||
<view class="search">
|
||||
<up-search :searchIconSize="48" :inputStyle="{ fontSize: '32rpx' }" @focus="getFocus" @blur="getBlur"
|
||||
:height="80" placeholder="搜索" :clearabled="false" @change="changeSearch"
|
||||
v-model="search.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
|
||||
v-model="lockSearch.searchStr" bgColor="#ffffff" :showAction="false" maxlength="20"></up-search>
|
||||
</view>
|
||||
<view class="lock-list" v-if="!penging">
|
||||
<view v-if="lockList.length === 0 && search.searchStr === '' && !focus">
|
||||
<image src="/static/images/icon_add.png" mode="aspectFill" class="button-add-big" @click="toSearchDevice"></image>
|
||||
<view v-if="lockList.length === 0 && lockSearch.searchStr === '' && !focus">
|
||||
<image src="/static/images/icon_add_round.png" mode="aspectFill" class="button-add-big"
|
||||
@click="toSearchDevice"></image>
|
||||
<view class="text">填加锁时,手机必须在锁旁边</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
@ -32,9 +33,9 @@
|
||||
<view>{{getRole(lock.userType)}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="lock-name">{{lock.lockName}}</view>
|
||||
<view class="lock-name">{{lock.lockAlias}}</view>
|
||||
<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>{{ timeFormat(lock.startDate, 'yyyy-mm-dd h:M') }}</view>
|
||||
<view>{{ timeFormat(lock.endDate, 'yyyy-mm-dd h:M ') + getTimeLimit(lock.keyType) }}</view>
|
||||
@ -45,19 +46,23 @@
|
||||
</view>
|
||||
</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>
|
||||
</view>
|
||||
<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>
|
||||
<button open-type="getPhoneNumber" style="display:none" id="phone" @getphonenumber="getphonenumber"></button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { timeFormat } from 'uview-plus'
|
||||
import { getUserInfoRequest } from '@/api/user'
|
||||
import { getUserInfoRequest, loginRequest } from '@/api/user'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useLockStore } from '@/stores/lock'
|
||||
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||
@ -67,68 +72,130 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
search: {
|
||||
pageNo: 1,
|
||||
pageSize: 50,
|
||||
searchStr: ''
|
||||
},
|
||||
refresherTriggered: false,
|
||||
focus: false,
|
||||
penging: true
|
||||
penging: true,
|
||||
deviceInfo: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(useUserStore, ['userInfo', 'isLogin']),
|
||||
...mapState(useLockStore, ['lockList', 'lockTotal']),
|
||||
...mapState(useLockStore, ['lockList', 'lockTotal', 'lockSearch']),
|
||||
...mapState(useBluetoothStore, ['bluetoothStatus', 'isInitBluetooth']),
|
||||
},
|
||||
async onLoad() {
|
||||
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')
|
||||
if(token) {
|
||||
this.updateLoginStatus(true)
|
||||
const code = await this.getUserInfo()
|
||||
if(code === 0) {
|
||||
await this.getLockList(this.search)
|
||||
}
|
||||
this.getLockList(this.lockSearch)
|
||||
await this.getUserInfo()
|
||||
} else {
|
||||
await this.homeLogin()
|
||||
}
|
||||
this.penging = false
|
||||
uni.hideLoading()
|
||||
},
|
||||
methods: {
|
||||
timeFormat,
|
||||
...mapActions(useUserStore, ['updateUserInfo', 'updateLoginStatus', 'login']),
|
||||
...mapActions(useLockStore, ['getLockList', 'getRole', 'getTimeLimit']),
|
||||
...mapActions(useBluetoothStore, ['getBluetoothStatus', 'initAndListenBluetooth', 'updateCurrentLockInfo', 'checkSetting']),
|
||||
...mapActions(useBasicStore, ['routeJump']),
|
||||
...mapActions(useUserStore, ['updateUserInfo', 'updateLoginStatus', 'phoneLogin', 'getUserInfo']),
|
||||
...mapActions(useLockStore, ['getLockList', 'getRole', 'getTimeLimit', 'updateLockSearch']),
|
||||
...mapActions(useBluetoothStore, ['getBluetoothStatus', 'initAndListenBluetooth', 'updateCurrentLockInfo',
|
||||
'checkSetting', 'updateKeyId']),
|
||||
...mapActions(useBasicStore, ['routeJump', 'getDeviceInfo']),
|
||||
homeLogin() {
|
||||
const that = this
|
||||
return new Promise((resolve) => {
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: async function (loginRes) {
|
||||
const { code, data } = await loginRequest({
|
||||
js_code: loginRes.code
|
||||
})
|
||||
if(code === 0) {
|
||||
uni.setStorageSync('openid', data.openid)
|
||||
if(data.accessToken) {
|
||||
uni.setStorageSync('token', data.accessToken)
|
||||
that.getLockList(that.lockSearch)
|
||||
await that.getUserInfo()
|
||||
that.updateLoginStatus(true)
|
||||
resolve(true)
|
||||
} else {
|
||||
that.updateLoginStatus(false)
|
||||
resolve(false)
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '登录失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
resolve(false)
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
uni.showToast({
|
||||
title: '登录失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
async getphonenumber(data) {
|
||||
if(data.detail.errMsg === 'getPhoneNumber:fail user deny') {
|
||||
return
|
||||
}
|
||||
const result = await this.phoneLogin({
|
||||
encryptedData: data.detail.encryptedData,
|
||||
iv: data.detail.iv
|
||||
})
|
||||
if(!result) {
|
||||
uni.showToast({
|
||||
title: '登录失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
async nextPage() {
|
||||
if(this.lockList.length < this.lockTotal) {
|
||||
this.search.pageNo++
|
||||
const { code } = await this.getLockList(this.search)
|
||||
const sreach = {
|
||||
...this.lockSearch,
|
||||
pageNo: this.lockSearch.pageNo + 1
|
||||
}
|
||||
const { code } = await this.getLockList(search)
|
||||
if(code !== 0) {
|
||||
this.search.pageNo--
|
||||
this.updateLockSearch(search)
|
||||
}
|
||||
}
|
||||
},
|
||||
async refresherList() {
|
||||
this.refresherTriggered = true
|
||||
this.search.pageNo = 1
|
||||
await this.getLockList(this.search)
|
||||
this.updateLockSearch({
|
||||
...this.lockSearch,
|
||||
pageNo: 1
|
||||
})
|
||||
await this.getLockList(this.lockSearch)
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.refresherTriggered = false
|
||||
},
|
||||
async changeSearch(data) {
|
||||
this.search.searchStr = data
|
||||
await this.getLockList(this.search)
|
||||
},
|
||||
async getUserInfo() {
|
||||
const { code, data } = await getUserInfoRequest()
|
||||
if(code === 0) {
|
||||
this.updateUserInfo(data)
|
||||
console.log(this.userInfo)
|
||||
}
|
||||
return code
|
||||
this.updateLockSearch({
|
||||
...this.lockSearch,
|
||||
searchStr: data
|
||||
})
|
||||
await this.getLockList(this.lockSearch)
|
||||
},
|
||||
getFocus() {
|
||||
this.focus = true
|
||||
@ -163,7 +230,16 @@
|
||||
result = await this.initAndListenBluetooth()
|
||||
}
|
||||
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({
|
||||
name: 'lockDetail'
|
||||
})
|
||||
@ -189,7 +265,6 @@ page {
|
||||
}
|
||||
|
||||
.button-login {
|
||||
margin-top: 40vh;
|
||||
border-radius: 46rpx;
|
||||
width: 650rpx;
|
||||
height: 120rpx;
|
||||
@ -314,4 +389,12 @@ page {
|
||||
margin-top: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 40vh;
|
||||
padding: 32rpx 0;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</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>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<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 {
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
@ -31,35 +31,132 @@
|
||||
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
||||
</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 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>
|
||||
<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>
|
||||
|
||||
<script>
|
||||
import { useBasicStore } from '@/stores/basic'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useLockStore } from '@/stores/lock'
|
||||
import { mapState, mapActions } from 'pinia'
|
||||
import { phoneLoginRequest } from '@/api/user'
|
||||
import env from '@/config/env'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
buttonInfo: null
|
||||
buttonInfo: null,
|
||||
env: null,
|
||||
envVersion: '',
|
||||
envList: [],
|
||||
show: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(useUserStore, ['isLogin'])
|
||||
...mapState(useUserStore, ['isLogin']),
|
||||
...mapState(useLockStore, ['lockSearch'])
|
||||
},
|
||||
async onLoad() {
|
||||
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: {
|
||||
...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() {
|
||||
this.routeJump({
|
||||
name: 'userInfo'
|
||||
@ -72,21 +169,8 @@
|
||||
type
|
||||
}
|
||||
})
|
||||
},
|
||||
logout() {
|
||||
const that = this
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定退出登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('token')
|
||||
that.updateLoginStatus(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -136,23 +220,48 @@ page {
|
||||
background: #EBEBEB;
|
||||
}
|
||||
|
||||
.button-logout {
|
||||
.switch-account {
|
||||
position: absolute;
|
||||
border-radius: 46rpx;
|
||||
bottom: 60rpx;
|
||||
width: 710rpx;
|
||||
width: 600rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
margin-left: 20rpx;
|
||||
background: #ec433c;
|
||||
margin-left: 75rpx;
|
||||
background: #63b8af;
|
||||
color: #ffffff;
|
||||
font-size: 40rpx;
|
||||
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 {
|
||||
margin-top: 40vh;
|
||||
border-radius: 46rpx;
|
||||
width: 650rpx;
|
||||
height: 120rpx;
|
||||
@ -164,4 +273,12 @@ page {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 35vh;
|
||||
padding: 32rpx 0;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</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>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'pinia'
|
||||
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||
import { useBasicStore } from '@/stores/basic'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
export default {
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
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: {
|
||||
...mapActions(useUserStore, ['updateUserInfo']),
|
||||
...mapActions(useBasicStore, ['routeJump']),
|
||||
...mapActions(useBasicStore, ['routeJump', 'backAndToast']),
|
||||
updateInputEmail(data) {
|
||||
this.email = data.detail.value
|
||||
},
|
||||
@ -100,14 +100,7 @@ export default {
|
||||
...this.userInfo,
|
||||
email: this.email
|
||||
})
|
||||
uni.navigateBack({
|
||||
complete () {
|
||||
uni.showToast({
|
||||
title: '邮箱更新成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
this.backAndToast('邮箱绑定成功')
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
import { mapActions, mapState } from 'pinia'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { updateUserInfoRequest } from '@/api/user'
|
||||
import { useBasicStore } from '@/stores/basic'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -26,6 +27,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useUserStore, ['updateUserInfo']),
|
||||
...mapActions(useBasicStore, ['backAndToast']),
|
||||
updateInput(data) {
|
||||
this.nickname = data.detail.value
|
||||
console.log(data)
|
||||
@ -50,14 +52,7 @@ export default {
|
||||
...this.userInfo,
|
||||
nickname: this.nickname
|
||||
})
|
||||
uni.navigateBack({
|
||||
complete() {
|
||||
uni.showToast({
|
||||
title: '昵称更新成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
this.backAndToast('昵称更新成功')
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '昵称更新失败',
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<view>
|
||||
<input class="input" :password="true" style="margin-top: 48rpx;" :value="oldPassword" maxlength="20"
|
||||
placeholder="请输入原密码" placeholder-class="input-placeholder" :focus="true" @input="updateOldPassword"></input>
|
||||
<input class="input" :password="true" :value="newPassword" maxlength="20" placeholder="请输入新密码"
|
||||
<input class="input" :password="true" :value="password" maxlength="20" placeholder="请输入新密码"
|
||||
placeholder-class="input-placeholder" @input="updateNewPassword"></input>
|
||||
<input class="input" :password="true" :value="confirmPassword" maxlength="20" placeholder="请确认密码"
|
||||
placeholder-class="input-placeholder" @input="updateConfirmPassword"></input>
|
||||
<view class="view-top">
|
||||
<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="button" @click="updatePassword">保存</view>
|
||||
</view>
|
||||
@ -14,15 +15,17 @@
|
||||
<script>
|
||||
import { mapActions, mapState } from 'pinia'
|
||||
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 {
|
||||
data () {
|
||||
return {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
pending: false
|
||||
text: '获取验证码',
|
||||
password: '',
|
||||
pending: false,
|
||||
verificationCode: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -30,34 +33,61 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useUserStore, ['updateUserInfo']),
|
||||
updateOldPassword (data) {
|
||||
this.oldPassword = data.detail.value
|
||||
},
|
||||
...mapActions(useBasicStore, ['backAndToast']),
|
||||
updateNewPassword (data) {
|
||||
this.newPassword = data.detail.value
|
||||
this.password = data.detail.value
|
||||
},
|
||||
updateConfirmPassword (data) {
|
||||
this.confirmPassword = data.detail.value
|
||||
updateInputCode (data) {
|
||||
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 () {
|
||||
if (this.oldPassword === '' || this.newPassword === '' || this.confirmPassword === '') {
|
||||
if (this.password === '') {
|
||||
uni.showToast({
|
||||
title: '密码不能为空',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (this.newPassword.length < 8 || this.newPassword.length > 20 || this.confirmPassword.length < 8 ||
|
||||
this.confirmPassword.length > 20 || this.oldPassword.length < 8 || this.oldPassword.length > 20) {
|
||||
if (this.password.length < 8 || this.password.length > 20) {
|
||||
uni.showToast({
|
||||
title: '密码长度必须是8-20位',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (this.newPassword !== this.confirmPassword) {
|
||||
if (!(this.verificationCode.length === 6 && test.digits(this.verificationCode))) {
|
||||
uni.showToast({
|
||||
title: '两次密码输入不一致',
|
||||
title: '验证码为6位纯数字',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@ -66,24 +96,13 @@ export default {
|
||||
return
|
||||
}
|
||||
this.pending = true
|
||||
const { code, message } = await updatePasswordRequest({
|
||||
oldPassword: this.oldPassword,
|
||||
newPassword: this.newPassword,
|
||||
date: new Date().getTime()
|
||||
const { code, message } = await changePasswordRequest({
|
||||
verificationCode: this.verificationCode,
|
||||
password: this.password,
|
||||
channel: '1'
|
||||
})
|
||||
if (code === 0) {
|
||||
this.updateUserInfo({
|
||||
...this.userInfo,
|
||||
nickname: this.nickname
|
||||
})
|
||||
uni.navigateBack({
|
||||
complete () {
|
||||
uni.showToast({
|
||||
title: '密码重置成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
this.backAndToast('密码重置成功')
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
@ -107,7 +126,7 @@ page {
|
||||
border-radius: 16rpx;
|
||||
background: #FFFFFF;
|
||||
margin-left: 35rpx;
|
||||
margin-top: 24rpx;
|
||||
margin-top: 48rpx;
|
||||
height: 108rpx;
|
||||
width: 616rpx;
|
||||
padding-left: 32rpx;
|
||||
@ -140,4 +159,34 @@ page {
|
||||
font-size: 28rpx;
|
||||
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>
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
import { getQuestionAnswerRequest, getQuestionListRequest, updateQuestionAnswerRequest } from '@/api/safeAnswer'
|
||||
import { mapActions, mapState } from 'pinia'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useBasicStore } from '@/stores/basic'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -75,6 +76,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useUserStore, ['updateUserInfo']),
|
||||
...mapActions(useBasicStore, ['backAndToast']),
|
||||
async updateAnswer() {
|
||||
console.log('答案', this.answer)
|
||||
for(let i = 0; i < this.answer.length; i++) {
|
||||
@ -107,14 +109,7 @@ export default {
|
||||
...this.userInfo,
|
||||
haveSafeAnswer: 1
|
||||
})
|
||||
uni.navigateBack({
|
||||
complete() {
|
||||
uni.showToast({
|
||||
title: '安全问题设置成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
this.backAndToast('设置成功')
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
|
||||
@ -19,14 +19,16 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="view-line"></view>
|
||||
<view class="view-button">
|
||||
<view>手机号</view>
|
||||
<view class="view-button" style="padding: 0">
|
||||
<view v-if="userInfo.mobile !== ''" class="info">{{userInfo.mobile}}</view>
|
||||
<view v-else class="red-dot"></view>
|
||||
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
||||
<label for="phone">
|
||||
<view class="view-button">
|
||||
<view>手机号</view>
|
||||
<view class="view-button" style="padding: 0">
|
||||
<view v-if="userInfo.mobile !== ''" class="info">{{userInfo.mobile}}</view>
|
||||
<view v-else class="red-dot"></view>
|
||||
<image class="icon-arrow" src="/static/images/icon_arrow.png" mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</label>
|
||||
<view class="view-line"></view>
|
||||
<view class="view-button" @click="toUpdateEmail">
|
||||
<view>邮箱</view>
|
||||
@ -58,6 +60,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
@ -66,7 +69,7 @@ import { mapActions, mapState } from 'pinia'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useBasicStore } from '@/stores/basic'
|
||||
import { getUploadParamsRequest } from '@/api/file'
|
||||
import { updateUserInfoRequest } from '@/api/user'
|
||||
import { rebindPhoneRequest, updateUserInfoRequest } from '@/api/user'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -79,11 +82,44 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...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) {
|
||||
console.log(e)
|
||||
const that = this
|
||||
|
||||
if(that.pending) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="tips">为了你的账号安全,修改账号前请先使用验证码验证</view>
|
||||
<view class="view-top">
|
||||
<input type="number" class="input" :value="verificationCode" maxlength="20" placeholder="请输入验证码"
|
||||
placeholder-class="input-placeholder" @input="updateInput"></input>
|
||||
@ -87,37 +88,6 @@ export default {
|
||||
},
|
||||
updateInput(data) {
|
||||
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 scoped lang="scss">
|
||||
.tips {
|
||||
padding: 24rpx 32rpx 0 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.button-verify {
|
||||
margin-top: 48rpx;
|
||||
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',
|
||||
path: '/pages/searchDevice/searchDevice',
|
||||
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
|
||||
})
|
||||
},
|
||||
// 计算字符串长度
|
||||
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 { sm4 } from 'sm-crypto'
|
||||
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 characteristicValueCallback = null
|
||||
// 搜索次数
|
||||
let searchNumber = 10
|
||||
// 搜索提示标志
|
||||
let searchTipFlag = true
|
||||
|
||||
// 命令ID
|
||||
const cmdIds = {
|
||||
@ -58,14 +67,40 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
// 消息序号
|
||||
messageCount: 1,
|
||||
// 是否初始化蓝牙
|
||||
isInitBluetooth: false
|
||||
isInitBluetooth: false,
|
||||
// 服务器时间
|
||||
serverTimestamp: 0,
|
||||
// 设备keyID
|
||||
keyId: '0'
|
||||
}
|
||||
},
|
||||
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) {
|
||||
// 更新蓝牙初始化状态
|
||||
this.updateInitBluetooth(true)
|
||||
@ -86,7 +121,7 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
this.isInitBluetooth = value
|
||||
},
|
||||
// 初始化蓝牙模块
|
||||
initBluetooth() {
|
||||
initBluetooth(tipFlag = true) {
|
||||
const that = this
|
||||
// 初始化蓝牙模块
|
||||
return new Promise(resolve => {
|
||||
@ -119,6 +154,23 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
resolve(true)
|
||||
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)
|
||||
}
|
||||
})
|
||||
@ -168,7 +220,7 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
if(binaryData[14] === 0) {
|
||||
that.updateCurrentLockInfo({
|
||||
...that.currentLockInfo,
|
||||
publicKey: binaryData.slice(15, 31)
|
||||
publicKey: [...binaryData.slice(15, 31)]
|
||||
})
|
||||
}
|
||||
characteristicValueCallback({
|
||||
@ -191,7 +243,8 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
that.updateCurrentLockInfo({
|
||||
...that.currentLockInfo,
|
||||
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('signKey', Array.from(that.currentLockInfo.signKey))
|
||||
@ -211,28 +264,28 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
case cmdIds.getLockStatus:
|
||||
if (decrypted[2] === 0) {
|
||||
const lockConfig = {
|
||||
vendor: decrypted.slice(3, 23),
|
||||
vendor: that.uint8ArrayToString(decrypted.slice(3, 23)),
|
||||
product: decrypted[23],
|
||||
model: decrypted.slice(24, 44),
|
||||
fwVersion: decrypted.slice(44, 64),
|
||||
hwVersion: decrypted.slice(64, 84),
|
||||
serialNum0: decrypted.slice(84, 100),
|
||||
serialNum1: decrypted.slice(100, 116),
|
||||
btDeviceName: decrypted.slice(116, 132),
|
||||
battRemCap: decrypted[132],
|
||||
battRemCapStandby: decrypted[133],
|
||||
restoreCounter: decrypted.slice(134, 136),
|
||||
restoreDate: decrypted.slice(136, 140),
|
||||
icPartNo: decrypted.slice(140, 150),
|
||||
inDate: decrypted.slice(150, 154),
|
||||
mac: decrypted.slice(154, 174),
|
||||
featurevalueLength: decrypted[174],
|
||||
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]]),
|
||||
model: that.uint8ArrayToString(decrypted.slice(24, 44)),
|
||||
fwVersion: that.uint8ArrayToString(decrypted.slice(44, 64)),
|
||||
hwVersion: that.uint8ArrayToString(decrypted.slice(64, 84)),
|
||||
serialNum0: that.uint8ArrayToString(decrypted.slice(84, 100)),
|
||||
serialNum1: that.uint8ArrayToString(decrypted.slice(100, 116)),
|
||||
btDeviceName: that.uint8ArrayToString(decrypted.slice(116, 132)),
|
||||
electricQuantity: decrypted[132],
|
||||
electricQuantityStandby: decrypted[133],
|
||||
restoreCount: decrypted[134] * 256 + decrypted[135],
|
||||
restoreDate: this.arrayToTimestamp(decrypted.slice(136, 140)),
|
||||
icPartNo: that.uint8ArrayToString(decrypted.slice(140, 150)),
|
||||
indate: this.arrayToTimestamp(decrypted.slice(150, 154)),
|
||||
mac: that.uint8ArrayToString(decrypted.slice(154, 174)),
|
||||
timezoneOffset: new Date().getTimezoneOffset() * 60
|
||||
}
|
||||
that.updateCurrentLockInfo({
|
||||
...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
|
||||
})
|
||||
console.log('获取锁状态成功', that.currentLockInfo.lockConfig)
|
||||
@ -246,6 +299,13 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
...that.currentLockInfo,
|
||||
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({
|
||||
code: decrypted[46]
|
||||
})
|
||||
@ -282,11 +342,47 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
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:
|
||||
that.updateCurrentLockInfo({
|
||||
...that.currentLockInfo,
|
||||
token: decrypted.slice(2,6)
|
||||
})
|
||||
console.log('默认结果', decrypted[6], that.currentLockInfo.token)
|
||||
characteristicValueCallback({
|
||||
code: decrypted[6]
|
||||
})
|
||||
@ -335,6 +431,7 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
this.getBluetoothStatus()
|
||||
return
|
||||
}
|
||||
this.deviceList = []
|
||||
uni.startBluetoothDevicesDiscovery({
|
||||
success: function (res) {
|
||||
setTimeout(() => {
|
||||
@ -343,6 +440,23 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
fail: async function (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) {
|
||||
// 重新初始化蓝牙适配器
|
||||
await that.initBluetooth()
|
||||
@ -362,7 +476,26 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
timer = setInterval(() => {
|
||||
uni.getBluetoothDevices({
|
||||
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
|
||||
if(deviceList.length !== 0) {
|
||||
searchTipFlag = false
|
||||
}
|
||||
that.deviceList = []
|
||||
for(let i = 0; i < deviceList.length; i++) {
|
||||
if(deviceList[i]?.advertisServiceUUIDs) {
|
||||
@ -386,6 +519,8 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
// 停止搜索蓝牙设备
|
||||
stopGetBluetoothDevices() {
|
||||
searchNumber = 10
|
||||
searchTipFlag = true
|
||||
clearInterval(timer)
|
||||
uni.stopBluetoothDevicesDiscovery()
|
||||
},
|
||||
@ -396,7 +531,15 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
title: '提示',
|
||||
content: '蓝牙尚未打开,请先打开蓝牙',
|
||||
showCancel: false,
|
||||
confirmText: '确定',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
wx.openSystemBluetoothSetting({
|
||||
success (res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if(this.bluetoothStatus === 2 || this.bluetoothStatus === 3) {
|
||||
uni.showModal({
|
||||
@ -466,7 +609,7 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
success (res) {
|
||||
let serviceId
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -520,6 +663,10 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
})
|
||||
},
|
||||
fail(res) {
|
||||
if(res.errno === 1509007) {
|
||||
resolve(true)
|
||||
return
|
||||
}
|
||||
uni.showToast({
|
||||
title: '连接失败,请靠近设备并保持设备处于唤醒状态',
|
||||
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) {
|
||||
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('设备名称:', that.currentLockInfo.name)
|
||||
console.log('设备主服务:', that.currentLockInfo.serviceId)
|
||||
@ -668,6 +919,37 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
// 获取公钥
|
||||
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 conentArray = new Uint8Array(42)
|
||||
|
||||
@ -685,6 +967,37 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
// 获取私钥
|
||||
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 headArray = this.createPackageHeader(2, length)
|
||||
const conentArray = new Uint8Array(length)
|
||||
@ -736,6 +1049,37 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
// 获取锁状态
|
||||
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 length = 2 + 40 + 20 + 4 + 4
|
||||
const headArray = this.createPackageHeader(3, length)
|
||||
@ -769,10 +1113,46 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
array[3] = (timestamp & 0xff)
|
||||
return array
|
||||
},
|
||||
// 二进制转时间戳
|
||||
arrayToTimestamp(array) {
|
||||
const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]
|
||||
return timestamp >>> 0
|
||||
},
|
||||
// 添加用户
|
||||
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,
|
||||
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 headArray = this.createPackageHeader(3, length)
|
||||
const conentArray = new Uint8Array(length)
|
||||
@ -825,24 +1205,33 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
|
||||
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)
|
||||
await this.writeBLECharacteristicValue(packageArray)
|
||||
await this.writeBLECharacteristicValue(packageArray, false)
|
||||
return this.getWriteResult(this.addLockUser, data)
|
||||
},
|
||||
// 获取写入结果
|
||||
getWriteResult(request, params) {
|
||||
const that = this
|
||||
return new Promise(resolve => {
|
||||
const timer = setTimeout(() => {
|
||||
const getWriteResultTimer = setTimeout(() => {
|
||||
resolve({ code: -1 })
|
||||
}, 10000)
|
||||
}, 20000)
|
||||
characteristicValueCallback = async (data) => {
|
||||
// code 6 token过期,重新获取
|
||||
if(data.code === 6) {
|
||||
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 {
|
||||
clearTimeout(timer)
|
||||
clearTimeout(getWriteResultTimer)
|
||||
resolve(data)
|
||||
}
|
||||
}
|
||||
@ -850,6 +1239,45 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
// 开门
|
||||
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 length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
|
||||
const headArray = this.createPackageHeader(3, length)
|
||||
@ -870,11 +1298,14 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
@ -885,13 +1316,132 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
||||
|
||||
const packageArray = this.createPackageEnd(headArray, cebArray)
|
||||
|
||||
await this.writeBLECharacteristicValue(packageArray)
|
||||
this.writeBLECharacteristicValue(packageArray)
|
||||
|
||||
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) {
|
||||
// 确认蓝牙状态正常
|
||||
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 length = 2 + 40 + 20 + 4 + 1 + 16
|
||||
const headArray = this.createPackageHeader(3, length)
|
||||
@ -907,10 +1457,10 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
for(let i = 0; i < authUid.length; 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
|
||||
|
||||
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)
|
||||
|
||||
const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' })
|
||||
@ -923,6 +1473,45 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
},
|
||||
// 重置开锁密码
|
||||
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 length = 2 + 1 + 1 + 40 + 20 + 4 + 1 + 16
|
||||
const headArray = this.createPackageHeader(3, length)
|
||||
@ -944,11 +1533,11 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
@ -960,13 +1549,47 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
|
||||
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) {
|
||||
// 确认蓝牙状态正常
|
||||
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 length = 2 + 1 + 1 + 40 + 20 + 2 + 1 + 1 + 20 + 2 + 4 + 4 + 4 + 1 + 16
|
||||
const headArray = this.createPackageHeader(3, length)
|
||||
@ -1001,14 +1624,14 @@ export const useBluetoothStore = defineStore('ble', {
|
||||
conentArray[88] = 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(endTime), 98)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
115
stores/lock.js
@ -3,6 +3,9 @@
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
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', {
|
||||
state() {
|
||||
@ -10,10 +13,59 @@ export const useLockStore = defineStore('lock', {
|
||||
// 锁列表
|
||||
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: {
|
||||
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) {
|
||||
if(userType === 110301) {
|
||||
return '超级管理员'
|
||||
@ -21,6 +73,17 @@ export const useLockStore = defineStore('lock', {
|
||||
return '普通用户'
|
||||
}
|
||||
},
|
||||
getKeyStatus(keyStatus) {
|
||||
if(keyStatus === 110401) {
|
||||
return '正常'
|
||||
} else if(keyStatus === 110402) {
|
||||
return '待接收'
|
||||
} else if(keyStatus === 110412) {
|
||||
return '已过期'
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
getTimeLimit(keyType) {
|
||||
if(keyType === 1) {
|
||||
return '永久'
|
||||
@ -49,6 +112,56 @@ export const useLockStore = defineStore('lock', {
|
||||
})
|
||||
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 用户信息数据持久化
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
import { getUserInfoRequest } from '@/api/user'
|
||||
import { getUserInfoRequest, loginRequest, phoneLoginRequest } from '@/api/user'
|
||||
import { useLockStore } from '@/stores/lock'
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
@ -21,18 +21,57 @@ export const useUserStore = defineStore('user', {
|
||||
updateLoginStatus(status) {
|
||||
this.isLogin = status
|
||||
},
|
||||
async login() {
|
||||
uni.setStorageSync('token', '3021|MZv7iEf0NwjCPSGx4QWs37zOjeVN3GrSJ2v7D56L7db1fcc5')
|
||||
// 获取用户信息
|
||||
async getUserInfo() {
|
||||
const { code, data } = await getUserInfoRequest()
|
||||
await useLockStore().getLockList({
|
||||
pageNo: 1,
|
||||
pageSize: 50
|
||||
})
|
||||
if(code === 0) {
|
||||
this.updateUserInfo(data)
|
||||
this.updateLoginStatus(true)
|
||||
}
|
||||
this.isLogin = true
|
||||
return this.isLogin
|
||||
return code
|
||||
},
|
||||
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-color-paragraph: #3F536E; // 文章段落颜色
|
||||
$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
|
||||
@ -12,9 +12,12 @@ import baseConfig from '@/config/env'
|
||||
|
||||
const request = (config) => {
|
||||
return new Promise((resolve) => {
|
||||
const baseConfig = env[getApp().globalData.getEnvConfig()]
|
||||
|
||||
const token = config?.token ? config.token : uni.getStorageSync('token')
|
||||
const headerDefault = {
|
||||
version: baseConfig.version,
|
||||
appid: getApp().globalData.appid,
|
||||
version: baseConfig.version + '+' + baseConfig.buildNumber,
|
||||
authorization: `Bearer ${token}`
|
||||
}
|
||||
const URL = config.baseUrl ? config.baseUrl + config.url : baseConfig.baseUrl + config.url
|
||||
@ -62,18 +65,14 @@ const request = (config) => {
|
||||
resolve({ code: -1, data, message: '网络不太好哦,请稍后再试' })
|
||||
},
|
||||
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), {
|
||||
env: getApp().globalData.getEnvConfig(),
|
||||
url: URL.substring(baseConfig.baseUrl.length + 1),
|
||||
req: config?.data || {},
|
||||
code: res?.data?.errorCode,
|
||||
res: res?.data?.data,
|
||||
token: header?.authorization || '',
|
||||
message: res?.data?.errorMsg,
|
||||
duration: new Date().getTime() - timestamp
|
||||
})
|
||||
}
|
||||
|
||||