533 lines
13 KiB
Vue
533 lines
13 KiB
Vue
<template>
|
||
<view class="page">
|
||
<view class="equipment">
|
||
<view class="header">
|
||
<text>我的设备</text>
|
||
<image
|
||
v-if="equipmentList.length > 1"
|
||
:src="arrow"
|
||
mode=""
|
||
:class="{ arrow: true, rotate: showAllEquipment }"
|
||
@click="handleShowAll"
|
||
>
|
||
</image>
|
||
</view>
|
||
<view v-if="!showAllEquipment" class="single">
|
||
<view class="left">
|
||
<image
|
||
:src="
|
||
showEquipment?.curDeviceUserAvatar
|
||
? showEquipment?.curDeviceUserAvatar
|
||
: defaultAvatar
|
||
"
|
||
mode=""
|
||
class="avatar"
|
||
></image>
|
||
<view class="info">
|
||
<view class="info_name">
|
||
<template v-if="!equipEmpty">
|
||
{{
|
||
showEquipment?.curDeviceUserName ? showEquipment?.curDeviceUserName : '未登录账号'
|
||
}}
|
||
</template>
|
||
<template v-else> 未绑定设备 </template>
|
||
</view>
|
||
<view class="info_serial">
|
||
<template v-if="!equipEmpty"> 序列号:{{ showEquipment?.simSerialNumber }} </template>
|
||
<template v-else> 请先绑定设备 </template>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<template v-else>
|
||
<view v-for="(i, idx) in equipmentList" :key="idx" class="single" @click="handleChecked(i)">
|
||
<view class="left">
|
||
<image
|
||
:src="i?.curDeviceUserAvatar ? i?.curDeviceUserAvatar : defaultAvatar"
|
||
mode=""
|
||
class="avatar"
|
||
></image>
|
||
<view class="info">
|
||
<view class="info_name">
|
||
{{ i?.curDeviceUserName ? i?.curDeviceUserName : '未登录账号' }}
|
||
</view>
|
||
<view class="info_serial"> 序列号:{{ i?.simSerialNumber }} </view>
|
||
</view>
|
||
</view>
|
||
<view class="right">
|
||
<image
|
||
:src="i.simSerialNumber === showEquipment.simSerialNumber ? checked : unchecked"
|
||
mode=""
|
||
class="check_icon"
|
||
>
|
||
</image>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
<!-- 设备应用 -->
|
||
<view class="equipment_application">
|
||
<view class="navigate">
|
||
<text
|
||
v-for="(i, idx) in navList"
|
||
:key="idx"
|
||
:class="{ navigate_item: true, active: activeNav.type === i.type }"
|
||
@click="switchNav(i)"
|
||
>{{ i.title }}</text
|
||
>
|
||
</view>
|
||
<view class="application">
|
||
<view v-if="appEmpty" class="empty_box">
|
||
<Empty
|
||
:content="
|
||
showEquipment.simSerialNumber ? '暂无应用数据~' : '您还没有绑定设备,暂无应用数据~'
|
||
"
|
||
/>
|
||
</view>
|
||
<template v-else>
|
||
<view v-for="(i, idx) in equipAppList" :key="idx" class="application_item">
|
||
<view class="left">
|
||
<image
|
||
:src="i.iconPath ? i.iconPath : `${OSS_URL}/urm/placeholder_apply_icon.png`"
|
||
mode=""
|
||
class="avatar"
|
||
></image>
|
||
<view class="info">
|
||
<view class="info_name"> {{ i.appName }} </view>
|
||
<!-- <view class="info_time"> 今日使用:1时38分 </view> -->
|
||
</view>
|
||
</view>
|
||
<!-- <view class="right">
|
||
<text class="control" @click="handleControl">管控</text>
|
||
<text class="delete" @click="handleDelete">卸载</text>
|
||
</view> -->
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
|
||
<CustomPopup
|
||
v-model="showCustomPopup"
|
||
titleText="温馨提示"
|
||
@handleConfirmBtn="handleConfirmPopup"
|
||
>
|
||
<view class="popup_box"> 确认卸载该应用? </view>
|
||
</CustomPopup>
|
||
<wd-popup
|
||
v-model="methodPopup"
|
||
safe-area-inset-bottom
|
||
position="bottom"
|
||
custom-style="border-radius: 20px 20px 0 0;padding-bottom: 30px;"
|
||
@click-modal="() => {}"
|
||
>
|
||
<view class="bottom_popup">
|
||
<view class="header_title"> 选择使用方式 </view>
|
||
<view class="method_list">
|
||
<view v-for="(i, idx) in methodList" :key="idx" class="item">
|
||
{{ i.name }}
|
||
</view>
|
||
</view>
|
||
<view class="footer">
|
||
<button class="confirm_btn" @click="handleConfirmControl">确定</button>
|
||
</view>
|
||
</view>
|
||
</wd-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, onMounted } from 'vue'
|
||
import { onShow } from '@dcloudio/uni-app'
|
||
import { studentHeadImage } from '@/hooks/useImage'
|
||
import { getParentBindDeviceApi, parentDeviceCurrentLoginApi, queryAppRecordApi } from '@/api'
|
||
|
||
import CustomPopup from '@/components/CustomPopup/index.vue'
|
||
import Empty from '@/components/Empty/index.vue'
|
||
import { useUserStore, bindApplyStore } from '@/store'
|
||
import { storeToRefs } from 'pinia'
|
||
import db from '@/utils/db'
|
||
import { useBadgeStore } from '@/store/badge'
|
||
|
||
const { userInfo } = storeToRefs(useUserStore())
|
||
const { refreshBadge } = useBadgeStore()
|
||
const OSS_URL = import.meta.env.VITE_OSS_HOST
|
||
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
|
||
const arrow = `${OSS_URL}/iconfont/down_arrow.png`
|
||
const checked = `${OSS_URL}/iconfont/checked.png`
|
||
const unchecked = `${OSS_URL}/iconfont/unchecked.png`
|
||
const showAllEquipment = ref(false)
|
||
const showCustomPopup = ref(false)
|
||
|
||
const methodPopup = ref(false)
|
||
const methodList = ref([
|
||
{
|
||
name: '允许使用',
|
||
},
|
||
{
|
||
name: '限制使用',
|
||
},
|
||
{
|
||
name: '禁止使用',
|
||
},
|
||
])
|
||
const showEquipment = ref<any>({})
|
||
|
||
const equipmentList = ref([])
|
||
const equipAppList = ref([]) // 设备应用
|
||
const equipEmpty = ref(false) // 无绑定设备
|
||
const appEmpty = ref(false)
|
||
const activeNav = ref({
|
||
title: '允许使用',
|
||
type: 1,
|
||
})
|
||
const navList = reactive([
|
||
{
|
||
title: '允许使用',
|
||
type: 1,
|
||
},
|
||
// {
|
||
// title: '限制使用',
|
||
// type: 2,
|
||
// },
|
||
// {
|
||
// title: '禁止使用',
|
||
// type: 3,
|
||
// },
|
||
])
|
||
|
||
function handleShowAll() {
|
||
showAllEquipment.value = !showAllEquipment.value
|
||
}
|
||
|
||
function handleChecked(i) {
|
||
showEquipment.value = i
|
||
equipmentList.value = equipmentList.value.map(item => {
|
||
if (item.id === i.id) {
|
||
return {
|
||
...item,
|
||
checked: true,
|
||
}
|
||
} else {
|
||
return {
|
||
...item,
|
||
checked: false,
|
||
}
|
||
}
|
||
})
|
||
fetchAppRecord()
|
||
}
|
||
|
||
function switchNav(i) {
|
||
activeNav.value = i
|
||
}
|
||
// 管控
|
||
function handleControl() {
|
||
methodPopup.value = true
|
||
}
|
||
|
||
function handleConfirmControl() {
|
||
methodPopup.value = false
|
||
setTimeout(() => {
|
||
methodPopup.value = false
|
||
}, 200)
|
||
}
|
||
|
||
// 卸载
|
||
function handleDelete() {
|
||
showCustomPopup.value = true
|
||
}
|
||
|
||
function handleConfirmPopup() {
|
||
showCustomPopup.value = false
|
||
}
|
||
|
||
// 我的设备
|
||
async function getParentBindDevice() {
|
||
equipmentList.value = []
|
||
try {
|
||
uni.showLoading({
|
||
title: '加载中...',
|
||
})
|
||
const data = await getParentBindDeviceApi({ parentId: userInfo.value.id, size: -1 })
|
||
equipEmpty.value = data.rows.length === 0
|
||
for (let i in data.rows) {
|
||
const _r = await deviceCurrentLogin(data.rows[i].id)
|
||
equipmentList.value.push({
|
||
...data.rows[i],
|
||
curDeviceUserName: _r.curDeviceUserName,
|
||
curDeviceUserAvatar: _r.curDeviceUserAvatar,
|
||
})
|
||
}
|
||
showEquipment.value = data.rows?.length ? equipmentList.value[0] : {}
|
||
|
||
uni.hideLoading()
|
||
} catch (err) {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
// 当前设备登录账号
|
||
async function deviceCurrentLogin(id: string) {
|
||
const data = await parentDeviceCurrentLoginApi(id)
|
||
return data
|
||
}
|
||
// 设备应用
|
||
async function fetchAppRecord() {
|
||
// 序列号不存在
|
||
if (!showEquipment.value.simSerialNumber) return
|
||
try {
|
||
uni.showLoading({
|
||
title: '加载中...',
|
||
})
|
||
const data = await queryAppRecordApi(showEquipment.value.simSerialNumber)
|
||
const res = data.filter(i => i.systemApp === 0)
|
||
equipAppList.value = res
|
||
appEmpty.value = res.length === 0
|
||
uni.hideLoading()
|
||
} catch (err) {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
|
||
onShow(() => {
|
||
refreshBadge()
|
||
})
|
||
|
||
onMounted(async () => {
|
||
await getParentBindDevice()
|
||
fetchAppRecord()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.page {
|
||
padding: 30rpx 30rpx 206rpx 30rpx;
|
||
|
||
.equipment {
|
||
padding: 0 30rpx;
|
||
border-radius: 20rpx;
|
||
background-color: #fff;
|
||
|
||
.header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 26rpx 0;
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
line-height: 48rpx;
|
||
|
||
.arrow {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
}
|
||
|
||
.rotate {
|
||
transform: rotate(180deg);
|
||
}
|
||
}
|
||
|
||
.single {
|
||
padding: 30rpx 0;
|
||
border-top: 1rpx solid rgba(238, 238, 238, 1);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.left {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.avatar {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.info {
|
||
&_name {
|
||
margin-bottom: 10rpx;
|
||
line-height: 45rpx;
|
||
font-size: 30rpx;
|
||
font-weight: 500;
|
||
color: rgba(51, 51, 51, 1);
|
||
max-width: 210rpx;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
&_serial {
|
||
line-height: 42rpx;
|
||
font-size: 28rpx;
|
||
color: rgba(169, 170, 181, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
.right {
|
||
.check_icon {
|
||
width: 30rpx;
|
||
height: 30rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.equipment_application {
|
||
margin-top: 40rpx;
|
||
.navigate {
|
||
display: flex;
|
||
|
||
&_item {
|
||
margin-right: 40rpx;
|
||
color: rgba(169, 170, 181, 1);
|
||
font-size: 28rpx;
|
||
line-height: 48rpx;
|
||
}
|
||
|
||
.active {
|
||
position: relative;
|
||
font-weight: 500;
|
||
font-size: 32rpx;
|
||
color: rgba(51, 51, 51, 1);
|
||
|
||
&::after {
|
||
position: absolute;
|
||
bottom: -10rpx;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
content: '';
|
||
display: block;
|
||
width: 30rpx;
|
||
height: 8rpx;
|
||
background-color: rgba(97, 93, 255, 1);
|
||
border-radius: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.application {
|
||
padding: 0 30rpx;
|
||
margin-top: 10rpx;
|
||
background-color: #fff;
|
||
border-radius: 20rpx;
|
||
.empty_box {
|
||
height: 698rpx;
|
||
height: #fff;
|
||
.empty {
|
||
padding-top: 40rpx;
|
||
margin-top: 0 !important;
|
||
justify-content: flex-start;
|
||
}
|
||
}
|
||
&_item {
|
||
padding: 30rpx 0;
|
||
border-bottom: 1rpx solid rgba(238, 238, 238, 1);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.left {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.avatar {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
margin-right: 20rpx;
|
||
border-radius: 25rpx;
|
||
}
|
||
|
||
.info {
|
||
&_name {
|
||
margin-bottom: 10rpx;
|
||
line-height: 45rpx;
|
||
font-size: 30rpx;
|
||
font-weight: 500;
|
||
color: rgba(51, 51, 51, 1);
|
||
// max-width: 210rpx;
|
||
max-width: 530rpx;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
&_time {
|
||
line-height: 36rpx;
|
||
font-size: 24rpx;
|
||
color: rgba(169, 170, 181, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
.right {
|
||
font-size: 24rpx;
|
||
line-height: 36rpx;
|
||
background-color: rgba(235, 235, 255, 1);
|
||
border-radius: 10rpx;
|
||
|
||
.control {
|
||
display: inline-block;
|
||
padding: 6rpx 20rpx;
|
||
color: rgba(97, 93, 255, 1);
|
||
border-right: 1rpx solid rgba(223, 223, 242, 1);
|
||
}
|
||
|
||
.delete {
|
||
display: inline-block;
|
||
padding: 6rpx 20rpx;
|
||
color: rgba(156, 153, 255, 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.popup_box {
|
||
margin: 50rpx 0;
|
||
}
|
||
|
||
.bottom_popup {
|
||
background-color: #fff;
|
||
border-radius: 20rpx 20rpx 0 0;
|
||
overflow: hidden;
|
||
|
||
.header_title {
|
||
margin: 30rpx 0 0 30rpx;
|
||
color: rgba(51, 51, 51, 1);
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
text-align: left;
|
||
}
|
||
|
||
.method_list {
|
||
text-align: center;
|
||
padding: 0 54rpx;
|
||
|
||
.item {
|
||
padding: 30rpx 0;
|
||
border-bottom: 1rpx solid rgba(235, 235, 235, 1);
|
||
font-weight: 400;
|
||
height: 45rpx;
|
||
color: rgba(169, 170, 181, 1);
|
||
}
|
||
}
|
||
.footer {
|
||
display: flex;
|
||
justify-content: center;
|
||
.confirm_btn {
|
||
margin: 16rpx auto 20rpx auto;
|
||
height: 90rpx;
|
||
width: 690rpx;
|
||
color: #fff;
|
||
background-color: #615dff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|