@ -9,8 +9,8 @@
< scroll-view class = "tab-bar" scroll -x = " true " scroll -with -animation >
< view class = "tab-container" >
< view v-for = "(tab, index) in tabs" :key="index"
: class = "['tab-item', activeTab === index ? 'active' : '']" @click ="switchTab(tab,index)" >
{{ tab.typeName }}
: class = "['tab-item', activeTab === index ? 'active' : '']" @click ="switchTab(tab, index)" >
{{ tab.typeName }}
< / view >
< / view >
< / scroll -view >
@ -18,45 +18,47 @@
< image src = "/static/images/common/more.png" mode = "aspectFit" class = "more" > < / image >
< / view >
< / view >
< view class = "sendFlex"
v-if = "activeTab && activeTab.id !== ''&& activeTabInfo.communicationMode==0" >
< view class = "sendFlex" v-if = "activeTab && activeTab.id !== '' && activeTabInfo.communicationMode == 0" >
< view class = "callpolice" @click ="callpolice" > 报警 < / view >
< view class = "Sendmessage" @click ="location" > 位置 < / view >
< view class = "Sendmessage" @click ="handleSend" > 发送信息 < / view >
< / view >
< scroll -view class = "device-list" scroll -y @scrolltolower ="onScrollToLower" :lower-threshold = "100 "
style = "height:80vh; ">
< view v-if = "deviceList.length> 0" >
< me scroll-uni class = "device-list" @init ="mescrollInit" @down ="downCallback" @up ="upCallback" :up = "upOption "
:down = "downOption" :fixed = "false ">
< view v-if = "deviceList.length > 0" >
< uni -swipe -action ref = "swipeAction" >
< block v-for = "(item, index) in deviceList" :key="index" :ref="'swipeItem_' + index" >
< uni -swipe -action -item :right-options = "Options"
@click ="handleSwipeClick($event, item, index)" class = "device-card"
: style = "{ border: item.communicationMode==0 && item.onlineStatus==1 && item.alarmStatus==1 ? '1px solid rgba(224, 52, 52, 1)' : 'none' }" >
: style = "{ border: item.communicationMode == 0 && item.onlineStatus == 1 && item.alarmStatus == 1 ? '1px solid rgba(224, 52, 52, 1)' : 'none' }" >
< view @click.stop ="handleFile(item)" >
< view class = "device-header" >
< view class = "deviceIMG" >
< image :src = "item.devicePic" class = "IMG" mode = "aspectFit" > < / image >
< / view >
< view class = "device-name" >
< view > 设备 : { { item . deviceName } } < / view >
< view > 设备 : { { item . deviceName } } < / view >
< view class = "ID" >
< view class = "ID" v-if = "item.communicationMode==0" > ID : {{ item.deviceImei }}
< view class = "ID" v-if = "item.communicationMode == 0" > ID : {{
item.deviceImei }}
< / view >
< view class = "ID" v-else > ID : {{ item.deviceMac }} < / view >
< view class = "ID" v-else > ID : {{ item.deviceMac }} < / view >
< ! - - 在线状态 - - >
< view class = "onlines"
v-if = "item.communicationMode==0 && item.onlineStatus==1" > 在线 < / view >
v-if = "item.communicationMode == 0 && item.onlineStatus == 1" > 在线
< / view >
< ! - - 离线状态 - - >
< view class = "offlines"
v-if = "item.communicationMode==0 && item.onlineStatus==0" > 离线 < / view >
< view > 电量 : { { item . battery || '0' } } % < / view >
v-if = "item.communicationMode == 0 && item.onlineStatus == 0" > 离线
< / view >
< view > 电量 : { { item . battery || '0' } } % < / view >
< / view >
< / view >
< / view >
< view class = "device-callpolice"
v-if = "item.communicationMode==0 && item.onlineStatus==1 && item.alarmStatus==1" >
v-if = "item.communicationMode == 0 && item.onlineStatus == 1 && item.alarmStatus == 1" >
报警中 < / view >
< view v-if = "item.communicationMode==1" >
< view v-if = "item.communicationMode == 1" >
< view class = "device-status online" > 已连接 < / view >
< view class = "device-status unline" > 未连接 < / view >
< / view >
@ -76,7 +78,7 @@
< / view >
暂无数据
< / view >
< / scroll-view >
< / me scroll-uni >
< / view >
<!-- 删除弹框 -- >
< view class = "agreement-mask" v-if = "deleteShow" @click="closePopup('delete')" catchtouchmove="true" >
@ -145,11 +147,11 @@
deviceReName
} from '@/api/common/index.js'
import BleHelper from '@/utils/BleHelper.js' ;
var ble = null ;
import MescrollUni from 'mescroll-uni/mescroll-uni.vue'
var ble = null ;
export default {
onPullDownRefresh ( ) {
// 执行下拉刷新时的操作,比如重新获取数据
this . onIntall ( ) ;
components : {
MescrollUni
} ,
data ( ) {
return {
@ -201,9 +203,23 @@
action : 'share'
}
] ,
mescroll : null ,
downOption : {
auto : false
} ,
upOption : {
auto : false ,
noMoreSize : 1 ,
offset : 80 ,
empty : {
tip : '暂无相关数据'
}
} ,
page : 1 , // 当前页码
size : 10 , // 每页条数
total : 0 , // 总数据量
loadedCount : 0 ,
loading : false ,
finished : false ,
deviceId : '' ,
@ -212,13 +228,57 @@
}
} ,
methods : {
mescrollInit ( mescroll ) {
this . mescroll = mescroll ;
} ,
// 下拉刷新
downCallback ( ) {
const currentDeviceType = this . activeTabInfo ? . id === '' ? undefined : this . activeTabInfo ? . id ;
const tempList = [ ... this . deviceList ] ;
// 重置分页参数
this . page = 1 ;
this . finished = false ;
this . loadedCount = 0 ;
this . getData ( currentDeviceType )
. then ( ( ) => {
this . mescroll . endDownScroll ( true ) ;
} )
. catch ( ( ) => {
this . deviceList = tempList ;
this . mescroll . endDownScroll ( false ) ;
} ) ;
} ,
// 上拉加载
upCallback ( ) {
// 防止重复加载
if ( this . finished || this . loading ) {
this . mescroll . endUpScroll ( false ) ;
return ;
}
const currentDeviceType = this . activeTabInfo ? . id === '' ? undefined : this . activeTabInfo ? . id ;
this . getData ( currentDeviceType )
. then ( ( ) => {
const hasMore = this . loadedCount < this . total ;
console . log ( ` 上拉加载 - 已加载: ${ this . loadedCount } , 总数: ${ this . total } , 是否还有更多: ${ hasMore } ` ) ;
this . mescroll . endUpScroll ( hasMore ) ;
} )
. catch ( ( ) => {
// 失败时回退页码
this . page -- ;
this . mescroll . endUpScroll ( false ) ;
} ) ;
} ,
// 更多
allMore ( ) {
this . showshare = ! this . showshare ;
} ,
// 所有分享,所有类型
handleshareClick ( item ) {
this . showshare = false ; // 关闭弹窗
this . showshare = false ;
switch ( item . action ) {
case 'type' :
uni . navigateTo ( {
@ -236,17 +296,16 @@
closePopup ( type ) {
if ( type === 'delete' ) {
this . deleteShow = false ;
uni . showTabBar ( ) ; // 显示TabBar
uni . showTabBar ( ) ;
} else if ( type === 'rename' ) {
this . RenameModel = false ;
uni . showTabBar ( ) ; // 显示TabBar
uni . showTabBar ( ) ;
}
} ,
// tab导航切换栏
getTab ( ) {
deviceTypeList ( { } ) . then ( ( res ) => {
if ( res . code == 200 ) {
//console.log("deviceTypeList=" + JSON.stringify(res.data));
this . tabs = [ {
id : '' ,
name : '全部设备' ,
@ -266,46 +325,77 @@
switchTab ( tab , index ) {
this . deviceList = [ ] ;
this . activeTab = index ;
this . activeTabInfo = tab
this . page = 1 ; // 重置页码
this . finished = false ; // 重
// 明确传递参数, 空字符串改为null或undefined
this . activeTabInfo = tab ;
// 完全重置分页状态
this . page = 1 ;
this . finished = false ;
this . loadedCount = 0 ;
const deviceType = tab . id === '' ? undefined : tab . id ;
this . getData ( deviceType ) ;
} ,
// 获取设备列表
getData ( deviceType = '' ) {
if ( this . loading || this . finished ) return ;
this . loading = true ;
let data = {
pageNum : this . page ,
pageSize : this . size ,
deviceType : deviceType // 使用传入的设备类型
if ( this . mescroll ) {
this . mescroll . resetUpScroll ( ) ;
}
deviceInfo ( data ) . then ( ( res ) => {
if ( res . code == 200 ) {
const newDevices = res . rows . map ( device => ( {
... device ,
showConfirm : false
} ) ) ;
// 如果是第一页或切换分类,替换数据
this . deviceList = this . page === 1 ? newDevices : [ ... this . deviceList , ... newDevices ] ;
this . total = res . total ;
// 判断是否加载完成
if ( res . rows . length < this . size || this . deviceList . length >= this . total ) {
this . finished = true ;
} else {
this . page ++ ;
}
}
} ) . finally ( ( ) => {
this . loading = false ;
} ) ;
} ,
// 滚动触底事件处理
onScrollToLower ( ) {
th is. getData ( ) ;
// 获取设备列表 - 核心修复
getData ( deviceType = '' ) {
return new Prom ise ( ( resolve , reject ) => {
if ( this . loading || this . finished ) {
reject ( '正在加载或已无更多数据' ) ;
return ;
}
this . loading = true ;
let data = {
pageNum : this . page ,
pageSize : this . size ,
deviceType : deviceType
}
deviceInfo ( data ) . then ( ( res ) => {
if ( res . code == 200 ) {
// 第一页加载时初始化总数据量
if ( this . page === 1 ) {
this . total = res . total ;
this . loadedCount = 0 ; // 重置计数
console . log ( ` 第1页加载 - 总数据量: ${ this . total } ` ) ;
}
const newDevices = res . rows . map ( device => ( {
... device ,
showConfirm : false
} ) ) ;
// 累加已加载数量
this . loadedCount += newDevices . length ;
console . log ( ` 第 ${ this . page } 页加载 - 新增: ${ newDevices . length } , 累计: ${ this . loadedCount } ` ) ;
// 数据累加逻辑(第一页替换,其他页追加)
if ( this . page === 1 ) {
this . deviceList = newDevices ;
} else {
this . deviceList = [ ... this . deviceList , ... newDevices ] ;
}
// 关键:正确判断是否加载完成
if ( this . loadedCount >= this . total || newDevices . length < this . size ) {
this . finished = true ;
console . log ( ` 加载完成 - 已加载 ${ this . loadedCount } / ${ this . total } ` ) ;
} else {
this . page ++ ; // 只有还有数据时才增加页码
}
resolve ( ) ;
} else {
reject ( res . msg || '获取数据失败' ) ;
}
} ) . catch ( ( err ) => {
console . error ( '获取设备列表失败:' , err ) ;
reject ( err ) ;
} ) . finally ( ( ) => {
this . loading = false ;
} ) ;
} ) ;
} ,
// 添加扫一扫图标
scan ( ) {
@ -317,19 +407,12 @@
} ,
// 添加设备,扫一扫,蓝牙
handleMenuClick ( item ) {
this . showTooltip = false ; // 关闭弹窗
this . showTooltip = false ;
switch ( item . action ) {
case 'scan' :
// 扫一扫
uni . scanCode ( {
success : ( res ) => {
console . log ( '条码内容:' , res ) ;
// 清除之前的数据
this . previousScanResult = null ;
// 处理新的扫码结果
const cleanedResult = res . result . trim ( ) ;
console . log ( '扫码结果:' , cleanedResult ) ;
// 跳转并传递扫描结果
uni . navigateTo ( {
url : ` /pages/common/qrcode/qrcode?deviceId= ${ encodeURIComponent ( cleanedResult ) } `
} ) ;
@ -352,10 +435,6 @@
} ,
// 右滑点击事件处理
handleSwipeClick ( e , item , index ) {
const {
content
} = e
console . log ( item , 'eeeee' ) ;
switch ( e . content . text ) {
case '删除' :
this . handleDeleteDevice ( item , index )
@ -374,9 +453,6 @@
// 确认删除
handleBtn ( ) {
uni . showTabBar ( )
let data = {
id : this . deviceId . id
}
deviceUnbind ( this . deviceId . id ) . then ( ( res ) => {
if ( res . code == 200 ) {
uni . showToast ( {
@ -389,10 +465,11 @@
this . getTab ( )
} , 500 ) ;
this . deleteShow = false
// 关闭所有滑动项
this . $refs . swipeAction . closeAll ( ) ;
ble && ble . DropDevice ( data . id ) ;
if ( this . $refs . swipeAction ) {
this . $refs . swipeAction . closeAll ( ) ;
}
ble && ble . DropDevice ( this . deviceId . id ) ;
} else {
uni . showToast ( {
title : res . msg ,
@ -410,11 +487,10 @@
} ,
handleBtnName ( ) {
uni . showTabBar ( )
let data = {
deviceReName ( {
id : this . deviceId . id ,
deviceName : this . deviceName
}
deviceReName ( data ) . then ( ( res ) => {
} ) . then ( ( res ) => {
if ( res . code == 200 ) {
uni . showToast ( {
title : res . msg ,
@ -426,8 +502,9 @@
} , 500 ) ;
this . RenameModel = false
this . deviceName = ''
// 关闭所有滑动项
this . $refs . swipeAction . closeAll ( ) ;
if ( this . $refs . swipeAction ) {
this . $refs . swipeAction . closeAll ( ) ;
}
} else {
uni . showToast ( {
title : res . msg ,
@ -440,13 +517,8 @@
// 报警
callpolice ( ) {
const currentTab = this . tabs [ this . activeTab ] ;
const deviceType = currentTab . id || '' ;
console . log ( ` 跳转到发送信息页面 \ n当前设备类型: ${ deviceType } \ n设备类型名称: ${ currentTab . typeName } ` ) ;
uni . navigateTo ( {
url : '/pages/6170/callPolice/index' ,
events : {
ack : function ( data ) { }
} ,
success : ( res ) => {
res . eventChannel . emit ( 'devicePolice' , {
data : currentTab
@ -457,16 +529,10 @@
// 发生短信
handleSend ( ) {
const currentTab = this . tabs [ this . activeTab ] ;
const deviceType = currentTab . id || '' ;
console . log ( ` 跳转到发送信息页面 \ n当前设备类型: ${ deviceType } \ n设备类型名称: ${ currentTab . typeName } ` ) ;
uni . navigateTo ( {
url : '/pages/common/send/index' ,
events : {
ack : function ( data ) { }
} ,
success : ( res ) => {
res . eventChannel . emit ( 'deviceSend' , {
//data: deviceType,
data : currentTab
} ) ;
}
@ -476,11 +542,7 @@
location ( ) {
uni . navigateTo ( {
url : '/pages/common/map/index' ,
events : {
ack : function ( data ) { }
} ,
success : ( res ) => {
// 页面跳转成功后的回调函数
res . eventChannel . emit ( 'Map' , {
data : this . deviceList ,
} ) ;
@ -490,50 +552,42 @@
// 列表跳转
handleFile ( item ) {
let url = item . detailPageUrl ;
// console.log("url=",url);
// if(!url){
//url="/pages/670/HBY670"
// }
uni . navigateTo ( {
url : url ,
events : {
ack : function ( data ) { }
} ,
success : ( res ) => {
// 页面跳转成功后的回调函数
res . eventChannel . emit ( 'detailData' , {
data : item ,
deviceType : this . tabs [ this . activeTab ] . id || '' ,
apiType : 'listA' //标识,根据这个参数,区分普通详情,分享跳转详情,查不一样的权限信息
apiType : 'listA'
} ) ;
} , fail ( ex ) {
console . log ( "ex=" , ex ) ;
} ,
fail ( ex ) {
console . log ( "ex=" , ex ) ;
}
} )
} ,
onIntall ( ) {
this . page = 1 ;
this . finished = false ;
this . loadedCount = 0 ; // 重置计数
const deviceType = this . activeTabInfo ? . id === '' ? undefined : this . activeTabInfo ? . id ;
this . getData ( deviceType ) ; // 重新加载第一页数据
this . getData ( deviceType ) ;
setTimeout ( ( ) => {
// 停止下拉刷新动画
uni . stopPullDownRefresh ( ) ;
} , 800 ) ;
} ,
updateDeviceStatus ( data ) {
this . deviceList = this . deviceList
. map ( item => {
if ( ! item ) return null ; // 如果 item 是 undefined/null, 返回 null
if ( ! item ) return null ;
if ( item . communicationMode == 0 ) {
let messageData ;
try {
messageData = data . message ;
} catch ( e ) {
return item ; // 解析失败则返回原 item
return item ;
}
const [ deviceId , onlineStatus , battery ] = messageData . state || [ ] ;
console . log ( '我收到消息了没' , item . battery ) ;
return {
... item ,
battery : battery ? ? item . battery ,
@ -549,20 +603,16 @@
onLoad ( ) {
this . getTab ( )
this . onIntall ( )
// 绑定页面做了监听,新增成功,刷新页面
uni . $on ( 'refreshDeviceList' , ( ) => {
this . getTab ( ) // 刷新数据
this . getTab ( )
this . onIntall ( )
} ) ;
// 监听设备状态更新事件
uni . $on ( 'deviceStatusUpdate' , ( data ) => {
console . log ( '列表收到消息了么' ) ;
this . onIntall ( )
} ) ;
ble = BleHelper . getBleTool ( ) ;
ble = BleHelper . getBleTool ( ) ;
} ,
beforeDestroy ( ) {
// 组件销毁前移除监听器
uni . $off ( 'refreshDeviceList' ) ;
} ,
onUnload ( ) {
@ -573,7 +623,7 @@
< / script >
< style >
/* 页面整体样式 */
/* 保持原有样式不变 */
. device - page {
display : flex ;
flex - direction : column ;
@ -586,7 +636,6 @@
width : 100 % ;
color : rgb ( 255 , 255 , 255 ) ;
white - space : nowrap ;
/* 禁止换行 */
overflow : hidden ;
position : relative ;
@ -597,17 +646,12 @@
cursor : pointer ;
margin - bottom : 40 rpx ;
padding - right : 80 rpx ;
/* 预留更多按钮空间 */
}
. tab - item {
font - size : 28 rpx ;
/* min-width: 120rpx; */
padding : 0 30 rpx ;
/* 左右内边距 */
text - align : center ;
/* 文字居中 */
/* 设置最小宽度 */
}
. active {
@ -627,16 +671,12 @@
. tab - bar - wrap {
display : flex ;
/* 横向排列 */
align - items : baseline ;
/* 垂直居中 */
position : relative ;
/* 可选(若需要绝对定位 fallback) */
}
. tab - more {
margin - left : 10 rpx ;
/* 与Tab的间距 */
display : flex ;
align - items : center ;
background : linear - gradient ( - 88.60 deg , rgba ( 18 , 18 , 18 , 1 ) , rgba ( 18 , 18 , 18 , 0 ) 100 % ) ;
@ -733,22 +773,6 @@
color : rgb ( 187 , 230 , 0 ) ;
}
. device - id {
font - size : 26 rpx ;
color : # 999 ;
margin - bottom : 20 rpx ;
display : block ;
}
. device - info {
display : flex ;
justify - content : space - evenly ;
font - size : 28 rpx ;
color : rgba ( 255 , 255 , 255 , 0.87 ) ;
position : relative ;
padding : 0 rpx 0 rpx 30 rpx 30 rpx ;
}
. deviceIMG {
width : 100 rpx ;
height : 100 rpx ;
@ -796,16 +820,6 @@
left : - 20 rpx
}
. line {
width : 2 rpx ;
height : 24 rpx ;
background : linear - gradient ( 90 deg ,
rgba ( 0 , 0 , 0 , 0 ) 0 % ,
rgb ( 255 , 255 , 255 ) 50 % ,
rgba ( 255 , 255 , 255 , 0 ) 100 % ) ;
margin - top : 12 rpx ;
}
. loading - status {
text - align : center ;
color : rgba ( 255 , 255 , 255 , 0.6 ) ;
@ -844,18 +858,6 @@
text - align : center ;
}
/* 弹窗主体 */
. agreement - popup {
width : 100 % ;
height : 50 % ;
background - color : rgb ( 42 , 42 , 42 ) ;
border - radius : 60 rpx 60 rpx 0 rpx 0 rpx ;
padding : 40 rpx ;
box - sizing : border - box ;
position : absolute ;
bottom : 0 rpx ;
}
. agreement - popupC {
width : 60 % ;
background - color : rgb ( 42 , 42 , 42 ) ;
@ -907,7 +909,6 @@
}
/* 同意按钮 */
. agreeBtn {
background : # FFC84E ;
color : # 232323 ;
@ -933,7 +934,6 @@
position : fixed ;
right : 18 rpx ;
top : 140 rpx ;
/* 根据导航栏高度调整 */
z - index : 9999 ;
}
@ -941,7 +941,6 @@
position : fixed ;
right : 18 rpx ;
top : 230 rpx ;
/* 根据导航栏高度调整 */
z - index : 9999 ;
}
@ -980,4 +979,4 @@
width : 16 px ;
height : 16 px ;
}
< / style >
< / style >