wx-starlock/pages/feature/keyList.vue
2025-07-29 11:07:43 +08:00

473 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<template>
<view>
<scroll-view
v-if="deviceInfo"
scroll-y="true"
:style="{ height: deviceInfo.windowHeight - 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="48rpx"
:inputStyle="{ fontSize: '32rpx' }"
height="80rpx"
placeholder="搜索"
:clearabled="false"
@change="changeSearch"
v-model="keySearch.searchStr"
bgColor="#ffffff"
:showAction="false"
maxlength="50"
></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="https://oss-lock.xhjcn.ltd/mp/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 in keyList"
:key="key.keyboardPwdId"
:threshold="50"
@click="deleteKey(key)"
>
<view class="key" @click="toKeyDetail(key)">
<image
class="key-left"
:src="
key.headUrl === '' ? 'https://oss-lock.xhjcn.ltd/mp/icon_user.png' : key.headUrl
"
mode="aspectFill"
></image>
<view class="key-right">
<view style="display: flex">
<view class="key-right-top">{{ key.keyName }}</view>
<image
class="key-admin"
mode="aspectFill"
v-if="key.remoteEnable === 1"
src="https://oss-lock.xhjcn.ltd/mp/icon_remote_unlock.png"
></image>
<image
class="key-admin"
mode="aspectFill"
v-if="key.keyRight === 1"
src="https://oss-lock.xhjcn.ltd/mp/icon_admin.png"
></image>
<view
class="key-status"
:style="{ color: key.keyStatus === 110401 ? '#4777ee' : '#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>
<up-modal
:show="showModal"
title="是否删除授权管理员钥匙?"
:showCancelButton="true"
width="600rpx"
@cancel="cancelModal"
@confirm="confirmModal"
>
<view class="slot-content" @click="changeRadio">
<view style="display: flex; align-items: center">
<radio :checked="checked"></radio>
<view>同时删除其发送的所有钥匙钥匙删除后不能恢复</view>
</view>
</view>
</up-modal>
</view>
</template>
<script>
import { mapActions, mapState } from 'pinia'
import { useBasicStore } from '@/stores/basic'
import { useBluetoothStore } from '@/stores/bluetooth'
import { useLockStore } from '@/stores/lock'
import { useUserStore } from '@/stores/user'
import { deleteKeyRequest, resetKeyRequest } from '@/api/key'
export default {
data() {
return {
showModal: false,
checked: false,
deviceInfo: null,
refresherTriggered: false,
requestFinished: false,
options: [
{
text: '删除',
style: {
backgroundColor: '#f56c6c'
}
}
],
deleteKeyId: ''
}
},
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, message } = await this.getKeyList(this.keySearch)
uni.hideLoading()
this.requestFinished = true
if (code !== 0) {
uni.showToast({
title: message,
icon: 'none'
})
}
},
onUnload() {
this.clearList('key')
},
methods: {
...mapActions(useBasicStore, ['routeJump', 'getDeviceInfo']),
...mapActions(useLockStore, [
'getKeyList',
'updateCurrentKeyInfo',
'updateKeySearch',
'getKeyStatus',
'clearList'
]),
changeRadio() {
this.checked = !this.checked
},
async confirmModal() {
uni.showLoading({
title: '删除中',
mask: true
})
const that = this
const { code, message } = await deleteKeyRequest({
keyId: that.deleteKeyId,
includeUnderlings: that.checked ? 1 : 0
})
that.showModal = false
if (code === 0) {
that.updateKeySearch({
...that.keySearch,
pageNo: 1
})
that.getKeyList(that.keySearch)
uni.hideLoading()
uni.showToast({
title: '删除成功',
icon: 'none'
})
} else {
uni.hideLoading()
uni.showToast({
title: message,
icon: 'none'
})
}
},
cancelModal() {
this.showModal = false
this.checked = false
},
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()
if (data.keyRight === 1) {
this.deleteKeyId = key.keyId
this.showModal = true
return
}
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
if (that.keyList.length === 0) {
uni.showToast({
title: '暂无钥匙,无需重置',
icon: 'none'
})
return
}
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, message } = await this.getKeyList(this.keySearch)
if (code === 0) {
uni.showToast({
title: '刷新成功',
icon: 'none'
})
} else {
uni.showToast({
title: message,
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, message } = await this.getKeyList(params)
if (code === 0) {
this.updateKeySearch({
...this.keySearch,
pageNo
})
} else {
uni.showToast({
title: message,
icon: 'none'
})
}
},
async changeSearch(data) {
this.updateKeySearch({
...this.keySearch,
searchStr: data
})
const { code, message } = await this.getKeyList(this.keySearch)
if (code !== 0) {
uni.showToast({
title: message,
icon: 'none'
})
}
}
}
}
</script>
<style lang="scss">
page {
background-color: $uni-bg-color-grey;
}
</style>
<style lang="scss" scoped>
.search {
width: 686rpx !important;
margin-top: 32rpx;
margin-left: 32rpx;
}
.button {
position: fixed;
bottom: calc(env(safe-area-inset-bottom) + 48rpx);
display: flex;
align-items: center;
font-weight: bold;
.button-reset {
width: 300rpx;
height: 88rpx;
margin-left: 50rpx;
line-height: 88rpx;
color: white;
text-align: center;
background-color: #df282d;
border-radius: 44rpx;
}
.button-create {
width: 300rpx;
height: 88rpx;
margin-left: 50rpx;
line-height: 88rpx;
color: white;
text-align: center;
background-color: #4777ee;
border-radius: 44rpx;
}
}
.key {
display: flex;
align-items: center;
width: 750rpx;
height: 120rpx;
background-color: #ffffff;
.key-left {
width: 80rpx;
height: 80rpx;
margin-left: 32rpx;
border-radius: 50%;
}
.key-right {
width: 574rpx;
margin-right: 32rpx;
margin-left: 32rpx;
.key-right-top {
max-width: 400rpx;
padding-bottom: 6rpx;
overflow: hidden;
text-overflow: ellipsis;
font-size: 32rpx;
font-weight: bold;
white-space: nowrap;
}
.key-admin {
width: 25rpx;
height: 25rpx;
margin-top: 8rpx;
margin-left: 10rpx;
}
.key-right-bottom {
font-size: 24rpx;
color: #999999;
}
}
.key-status {
margin-top: 4rpx;
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 {
font-size: 32rpx;
color: #999999;
text-align: center;
}
</style>