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

404 lines
9.5 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="searchStr"
bgColor="#ffffff"
:showAction="false"
maxlength="50"
></up-search>
</view>
<view style="padding: 0 0 calc(env(safe-area-inset-bottom) + 250rpx) 0">
<view v-if="list.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="item in list"
:key="item.keyboardPwdId"
:threshold="50"
@click="deleteItem(item)"
>
<view class="item" @click="toDetail(item)">
<image
class="item-left rounded-50%"
:src="
item.headUrl === ''
? 'https://oss-lock.xhjcn.ltd/mp/icon_user.png'
: item.headUrl
"
mode="aspectFill"
></image>
<view class="item-right">
<view style="display: flex; align-items: center">
<view class="item-right-top">{{ item.keyName }}</view>
<view class="status">
{{ $lock.getKeyStatus(item.keyStatus) }}
</view>
</view>
<view class="item-right-bottom">{{ item.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-create" @click="toCreate">添加授权管理员</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 setup>
import { onMounted, ref } from 'vue'
import { timeFormat } from 'uview-plus'
import { useBasicStore } from '@/stores/basic'
import { useBluetoothStore } from '@/stores/bluetooth'
import { deleteKeyRequest, getKeyListRequest } from '@/api/key'
import { useLockStore } from '@/stores/lock'
const $basic = useBasicStore()
const $bluetooth = useBluetoothStore()
const $lock = useLockStore()
const swipeItem = ref(null)
const searchStr = ref('')
const list = ref([])
const pageNo = ref(1)
const pageSize = 50
const total = ref(0)
const lockId = ref(null)
const deviceInfo = ref(null)
const requestFinished = ref(false)
const refresherTriggered = ref(false)
const options = ref([
{
text: '删除',
style: {
backgroundColor: '#f56c6c'
}
}
])
const showModal = ref(false)
const checked = ref(false)
const deleteData = ref(null)
onMounted(async () => {
uni.showLoading({
title: '加载中',
mask: true
})
deviceInfo.value = await $basic.getDeviceInfo()
lockId.value = $bluetooth.currentLockInfo.lockId
const { code, message } = await getList({
pageNo: pageNo.value
})
requestFinished.value = true
uni.hideLoading()
if (code !== 0) {
uni.showToast({
title: message,
icon: 'none'
})
}
})
const confirmModal = async () => {
uni.showLoading({
title: '删除中',
mask: true
})
const { code, message } = await deleteKeyRequest({
keyId: deleteData.value.keyId,
includeUnderlings: checked.value ? 1 : 0
})
showModal.value = false
if (code === 0) {
pageNo.value = 1
getList({
pageNo: pageNo.value
})
uni.hideLoading()
uni.showToast({
title: '删除成功',
icon: 'none'
})
} else {
uni.hideLoading()
uni.showToast({
title: message,
icon: 'none'
})
}
}
const cancelModal = () => {
showModal.value = false
checked.value = false
}
const changeRadio = () => {
checked.value = !checked.value
}
const deleteItem = async data => {
const index = list.value.findIndex(item => item.keyboardPwdId === data.keyboardPwdId)
swipeItem.value[index].closeHandler()
showModal.value = true
deleteData.value = data
}
const refresherList = async () => {
refresherTriggered.value = true
pageNo.value = 1
const { code, message } = await getList({
pageNo: pageNo.value,
searchStr: searchStr.value
})
if (code === 0) {
uni.showToast({
title: '刷新成功',
icon: 'none'
})
} else {
uni.showToast({
title: message,
icon: 'none'
})
}
refresherTriggered.value = false
}
const nextPage = async () => {
if (total.value <= pageNo.value * pageSize) {
return
}
const page = pageNo.value + 1
const params = {
searchStr: searchStr.value,
pageNo: page
}
const { code, message } = await getList(params)
if (code === 0) {
pageNo.value = page
} else {
uni.showToast({
title: message,
icon: 'none'
})
}
}
const getList = async params => {
const { code, data, message } = await getKeyListRequest({
...params,
lockId: lockId.value,
keyRight: 1,
endDate: '0',
startDate: '0',
keyStatus: [110401, 110402, 110412, 110405, 110403],
pageSize
})
if (code === 0) {
total.value = data.total
for (let i = 0; i < data.list.length; i++) {
if (data.list[i].keyType === 1) {
data.list[i].timeText = timeFormat(data.list[i].startDate, 'yyyy-mm-dd hh:MM') + ' 永久'
} else if (data.list[i].keyType === 2) {
data.list[i].timeText =
timeFormat(data.list[i].startDate, 'yyyy-mm-dd hh:MM') +
' - ' +
timeFormat(data.list[i].endDate, 'yyyy-mm-dd hh:MM')
}
}
if (params.pageNo === 1) {
list.value = data.list
} else {
list.value = list.value.concat(data.list)
}
return { code }
}
return { code, message }
}
const changeSearch = async data => {
pageNo.value = 1
const { code, message } = await getList({
searchStr: data,
pageNo: pageNo.value
})
if (code !== 0) {
uni.showToast({
title: message,
icon: 'none'
})
}
}
const toCreate = () => {
$basic.routeJump({
name: 'createAdmin',
events: {
refresherList() {
pageNo.value = 1
getList({
pageNo: pageNo.value
})
}
}
})
}
const toDetail = item => {
$basic.routeJump({
name: 'adminDetail',
params: {
info: JSON.stringify(item)
},
events: {
refresherList() {
pageNo.value = 1
getList({
pageNo: pageNo.value
})
}
}
})
}
</script>
<style lang="scss">
page {
background-color: $uni-bg-color-grey;
}
</style>
<style lang="scss" scoped>
.search {
width: 686rpx !important;
padding: 32rpx;
}
.button {
position: fixed;
bottom: calc(env(safe-area-inset-bottom) + 20rpx);
display: flex;
align-items: center;
font-weight: bold;
.button-create {
width: 686rpx;
height: 88rpx;
margin-left: 32rpx;
line-height: 88rpx;
color: white;
text-align: center;
background-color: #4777ee;
border-radius: 44rpx;
}
}
.item {
display: flex;
align-items: center;
width: 750rpx;
height: 120rpx;
background-color: #ffffff;
.item-left {
width: 80rpx;
height: 80rpx;
margin-left: 32rpx;
}
.item-right {
width: 574rpx;
margin-right: 32rpx;
margin-left: 32rpx;
.item-right-top {
max-width: 400rpx;
padding-bottom: 6rpx;
overflow: hidden;
text-overflow: ellipsis;
font-size: 32rpx;
font-weight: bold;
white-space: nowrap;
}
.item-right-bottom {
font-size: 24rpx;
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 {
font-size: 32rpx;
color: #999999;
text-align: center;
}
.status {
margin-left: auto;
font-size: 26rpx;
color: #df282d;
}
</style>