Merge branch 'liubiao-main'

This commit is contained in:
2025-08-26 08:39:27 +08:00
341 changed files with 36644 additions and 29198 deletions

View File

@ -1,311 +1,311 @@
<template>
<view class="container">
<!-- 设备列表 -->
<scroll-view class="device-list" scroll-y>
<view class="device-card" v-for="(item, index) in deviceList" :key="index" @click="toggleSelect(index)">
<!-- 复选框 -->
<view class="checkbox" :class="{ checked: item.checked }">
<uni-icons v-if="item.checked" type="checkmarkempty" size="18" color="rgb(0, 0, 0)"></uni-icons>
</view>
<!-- 设备信息 -->
<view class="device-content">
<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 class="ID">
<view class="ID">ID:{{item.deviceImei}}</view>
<view class="onlines" v-if="item.onlineStatus==1">在线</view>
<!-- 离线状态 -->
<view class="unlines" v-if="item.onlineStatus==0">离线</view>
<view>电量{{item.battery || '0'}}%</view>
</view>
</view>
</view>
</view>
</view>
<view class="editInfmation">
<button class="login-btn" @click="callMessage">呼叫设备</button>
</view>
</scroll-view>
<!-- 成功提示弹框 -->
<CustomPopup :show="showPopupFlag" :title="popupTitle" :message="popupMessage"
icon="/static/images/common/bj_1.png" :confirm-text="popupConfirmText" :show-cancel="false"
@confirm="onPopupConfirm" />
</view>
</template>
<script>
import CustomPopup from '@/components/CustomPopup/CustomPopup.vue'
import {
deviceInfo,
} from '@/api/common/index.js'
import {
deviceSendMessage
} from '@/api/6170/deviceControl.js'
export default {
components: {
CustomPopup
},
data() {
return {
deviceList: [],
showPopupFlag: false,
popupTitle: '',
popupMessage: '确定要呼叫所选设备!',
popupConfirmText: '确认'
}
},
methods: {
toggleSelect(index) {
this.deviceList[index].checked = !this.deviceList[index].checked
this.$forceUpdate()
},
// 获取设备列表
getData(deviceType) {
this.loading = true;
let data = {
pageNum: 1,
pageSize: 20,
deviceType: deviceType
}
deviceInfo(data).then((res) => {
if (res.code == 200) {
const newDevices = res.rows.map(device => ({
...device,
showConfirm: false,
checked: false
}));
this.total = res.total;
this.deviceList = newDevices
}
}).finally(() => {
this.loading = false;
});
},
//确认呼叫设备
callMessage() {
const selectedDevices = this.deviceList.filter(item => item.checked)
if (selectedDevices.length === 0) {
uni.showToast({
title: '请选择一个设备',
icon: 'none'
});
return;
}
this.showPopupFlag = true
},
//弹框确认
onPopupConfirm() {
const selectedDevices = this.deviceList.filter(item => item.checked)
const deviceIds = selectedDevices.map(item => item.id);
let data = {
deviceIds: deviceIds
}
deviceSendMessage(data).then((res) => {
if (res.code == 200) {
this.showPopupFlag = false
uni.navigateBack()
} else {
uni.showToast({
title: res.msg,
icon: 'none'
});
}
})
},
},
onLoad(options) {
const eventChannel = this.getOpenerEventChannel();
// 监听 'deviceSend' 事件,获取传过来的数据
eventChannel.on('deviceCall', (data) => {
console.log('Received detail data:', data);
this.getData(data.data)
});
// 如果需要向调用页面返回数据,可以触发 'ack' 事件
eventChannel.emit('ack', {})
},
}
</script>
<style scoped>
.container {
min-height: 100vh;
background-color: rgb(18, 18, 18);
box-sizing: border-box;
overflow-x: hidden;
}
.device-list {
flex: 1;
padding: 0 20rpx;
}
.device-card {
position: relative;
display: flex;
align-items: center;
width: 95%;
margin-bottom: 20rpx;
}
.checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid rgba(255, 255, 255, 0.5);
margin-right: 20rpx;
border-radius: 4rpx;
display: flex;
align-items: center;
justify-content: center;
}
.checkbox.checked {
background-color: rgb(187, 230, 0);
border-color: rgb(187, 230, 0);
}
.device-content {
background-color: rgb(26, 26, 26);
border-radius: 16rpx;
position: relative;
/* display: flex; */
align-items: center;
padding: 20rpx;
width: 95%;
}
.device-header {
display: flex;
align-items: center;
margin-bottom: 15rpx;
}
.device-name {
font-size: 32rpx;
color: rgba(255, 255, 255, 0.87);
margin-left: 12rpx;
line-height: 50rpx;
width: 83%;
white-space: nowrap;
}
.ID {
color: rgba(255, 255, 255, 0.6);
font-size: 26rpx;
display: flex;
justify-content: space-between;
position: relative;
}
.device-status {
width: 122rpx;
height: 52rpx;
font-size: 26rpx;
border-radius: 0px 8px 0px 8px;
background-color: rgb(42, 42, 42);
position: absolute;
top: 0rpx;
right: 0rpx;
text-align: center;
line-height: 52rpx;
}
.online {
color: rgb(187, 230, 0);
}
.unline {
color: rgba(255, 255, 255, 0.4);
}
.device-info {
display: flex;
justify-content: space-evenly;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.87);
padding-top: 10rpx;
position: relative;
}
.deviceIMG {
width: 100rpx;
height: 100rpx;
border-radius: 16rpx;
position: relative;
background-color: rgba(42, 42, 42, 0.6);
display: flex;
align-items: center;
}
.IMG {
width: 68rpx;
height: 50rpx;
margin-left: 17%;
}
.onlines {
position: relative;
}
.onlines::before {
content: '';
position: absolute;
width: 15rpx;
height: 15rpx;
background: rgb(0, 171, 103);
border-radius: 50%;
top: 20rpx;
left: -20rpx
}
.unlines {
position: relative;
}
.unlines::before {
content: '';
position: absolute;
width: 15rpx;
height: 15rpx;
background: rgba(255, 255, 255, 0.4);
border-radius: 50%;
top: 20rpx;
left: -20rpx
}
.line {
width: 2rpx;
height: 24rpx;
background: linear-gradient(90deg,
rgba(0, 0, 0, 0) 0%,
rgb(255, 255, 255) 50%,
rgba(255, 255, 255, 0) 100%);
margin-top: 12rpx;
}
.ql-editor {
color: rgba(255, 255, 255, 0.6);
font-size: 30rpx;
}
.editInfmation {
padding: 20rpx;
position: fixed;
bottom: 50rpx;
box-sizing: border-box;
width: 100%;
}
.login-btn {
margin-top: 30rpx;
background-color: rgb(187, 230, 0);
color: rgb(35, 35, 35);
border-radius: 50rpx;
width: 90%;
}
<template>
<view class="container">
<!-- 设备列表 -->
<scroll-view class="device-list" scroll-y>
<view class="device-card" v-for="(item, index) in deviceList" :key="index" @click="toggleSelect(index)">
<!-- 复选框 -->
<view class="checkbox" :class="{ checked: item.checked }">
<uni-icons v-if="item.checked" type="checkmarkempty" size="18" color="rgb(0, 0, 0)"></uni-icons>
</view>
<!-- 设备信息 -->
<view class="device-content">
<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 class="ID">
<view class="ID">ID:{{item.deviceImei}}</view>
<view class="onlines" v-if="item.onlineStatus==1">在线</view>
<!-- 离线状态 -->
<view class="unlines" v-if="item.onlineStatus==0">离线</view>
<view>电量{{item.battery || '0'}}%</view>
</view>
</view>
</view>
</view>
</view>
<view class="editInfmation">
<button class="login-btn" @click="callMessage">呼叫设备</button>
</view>
</scroll-view>
<!-- 成功提示弹框 -->
<CustomPopup :show="showPopupFlag" :title="popupTitle" :message="popupMessage"
icon="/static/images/common/bj_1.png" :confirm-text="popupConfirmText" :show-cancel="false"
@confirm="onPopupConfirm" />
</view>
</template>
<script>
import CustomPopup from '@/components/CustomPopup/CustomPopup.vue'
import {
deviceInfo,
} from '@/api/common/index.js'
import {
deviceSendMessage
} from '@/api/6170/deviceControl.js'
export default {
components: {
CustomPopup
},
data() {
return {
deviceList: [],
showPopupFlag: false,
popupTitle: '',
popupMessage: '确定要呼叫所选设备!',
popupConfirmText: '确认'
}
},
methods: {
toggleSelect(index) {
this.deviceList[index].checked = !this.deviceList[index].checked
this.$forceUpdate()
},
// 获取设备列表
getData(deviceType) {
this.loading = true;
let data = {
pageNum: 1,
pageSize: 20,
deviceType: deviceType
}
deviceInfo(data).then((res) => {
if (res.code == 200) {
const newDevices = res.rows.map(device => ({
...device,
showConfirm: false,
checked: false
}));
this.total = res.total;
this.deviceList = newDevices
}
}).finally(() => {
this.loading = false;
});
},
//确认呼叫设备
callMessage() {
const selectedDevices = this.deviceList.filter(item => item.checked)
if (selectedDevices.length === 0) {
uni.showToast({
title: '请选择一个设备',
icon: 'none'
});
return;
}
this.showPopupFlag = true
},
//弹框确认
onPopupConfirm() {
const selectedDevices = this.deviceList.filter(item => item.checked)
const deviceIds = selectedDevices.map(item => item.id);
let data = {
deviceIds: deviceIds
}
deviceSendMessage(data).then((res) => {
if (res.code == 200) {
this.showPopupFlag = false
uni.navigateBack()
} else {
uni.showToast({
title: res.msg,
icon: 'none'
});
}
})
},
},
onLoad(options) {
const eventChannel = this.getOpenerEventChannel();
// 监听 'deviceSend' 事件,获取传过来的数据
eventChannel.on('deviceCall', (data) => {
console.log('Received detail data:', data);
this.getData(data.data)
});
// 如果需要向调用页面返回数据,可以触发 'ack' 事件
eventChannel.emit('ack', {})
},
}
</script>
<style scoped>
.container {
min-height: 100vh;
background-color: rgb(18, 18, 18);
box-sizing: border-box;
overflow-x: hidden;
}
.device-list {
flex: 1;
padding: 0 20rpx;
}
.device-card {
position: relative;
display: flex;
align-items: center;
width: 95%;
margin-bottom: 20rpx;
}
.checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid rgba(255, 255, 255, 0.5);
margin-right: 20rpx;
border-radius: 4rpx;
display: flex;
align-items: center;
justify-content: center;
}
.checkbox.checked {
background-color: rgb(187, 230, 0);
border-color: rgb(187, 230, 0);
}
.device-content {
background-color: rgb(26, 26, 26);
border-radius: 16rpx;
position: relative;
/* display: flex; */
align-items: center;
padding: 20rpx;
width: 95%;
}
.device-header {
display: flex;
align-items: center;
margin-bottom: 15rpx;
}
.device-name {
font-size: 32rpx;
color: rgba(255, 255, 255, 0.87);
margin-left: 12rpx;
line-height: 50rpx;
width: 83%;
white-space: nowrap;
}
.ID {
color: rgba(255, 255, 255, 0.6);
font-size: 26rpx;
display: flex;
justify-content: space-between;
position: relative;
}
.device-status {
width: 122rpx;
height: 52rpx;
font-size: 26rpx;
border-radius: 0px 8px 0px 8px;
background-color: rgb(42, 42, 42);
position: absolute;
top: 0rpx;
right: 0rpx;
text-align: center;
line-height: 52rpx;
}
.online {
color: rgb(187, 230, 0);
}
.unline {
color: rgba(255, 255, 255, 0.4);
}
.device-info {
display: flex;
justify-content: space-evenly;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.87);
padding-top: 10rpx;
position: relative;
}
.deviceIMG {
width: 100rpx;
height: 100rpx;
border-radius: 16rpx;
position: relative;
background-color: rgba(42, 42, 42, 0.6);
display: flex;
align-items: center;
}
.IMG {
width: 68rpx;
height: 50rpx;
margin-left: 17%;
}
.onlines {
position: relative;
}
.onlines::before {
content: '';
position: absolute;
width: 15rpx;
height: 15rpx;
background: rgb(0, 171, 103);
border-radius: 50%;
top: 20rpx;
left: -20rpx
}
.unlines {
position: relative;
}
.unlines::before {
content: '';
position: absolute;
width: 15rpx;
height: 15rpx;
background: rgba(255, 255, 255, 0.4);
border-radius: 50%;
top: 20rpx;
left: -20rpx
}
.line {
width: 2rpx;
height: 24rpx;
background: linear-gradient(90deg,
rgba(0, 0, 0, 0) 0%,
rgb(255, 255, 255) 50%,
rgba(255, 255, 255, 0) 100%);
margin-top: 12rpx;
}
.ql-editor {
color: rgba(255, 255, 255, 0.6);
font-size: 30rpx;
}
.editInfmation {
padding: 20rpx;
position: fixed;
bottom: 50rpx;
box-sizing: border-box;
width: 100%;
}
.login-btn {
margin-top: 30rpx;
background-color: rgb(187, 230, 0);
color: rgb(35, 35, 35);
border-radius: 50rpx;
width: 90%;
}
</style>

View File

@ -128,9 +128,9 @@
</view> -->
<view class="mode-section">
<view class="mode-buttons">
<view v-for="(item, index) in modeItems" :key="index" class="mode-v1"
:class="{ 'active-mode': selectedIndex === index }">
<view class="mode-v2" @click="handleModeClick(index)">
<view v-for="(item, index) in modeItems" :key="index" class="mode-v1" :class="{ 'active-mode': selectedIndex === index }">
<view class="mode-v2"
@click="handleModeClick(index)">
<image :src="item.image" class="setIMG" mode="aspectFit"></image>
<view>
<view class="battery-v2">{{ item.title }}</view>
@ -249,31 +249,23 @@
<script>
// 弹框配置中心
const POPUP_CONFIGS = {
// 人员信息发送
person: {
config: {
icon: '/static/images/common/sendSucc.png',
message: '信息发送成功',
showCancel: false
},
confirm() {
return true; // 直接关闭
}
},
// 上传开机log
// 开机log
logo: {
config: {
icon: '/static/images/common/upload.png',
message: '上传成功',
showCancel: false
},
confirm() {
return true; // 直接关闭
}
},
// 电量低于20%.提示框
bettery: {
config: {
title: '设备电量低于20%',
@ -284,24 +276,24 @@
confirmBtnBg: 'rgba(224, 52, 52, 1)',
showCancel: true
},
confirm() {
onConfirm() {
console.log('确认按钮');
return true; // 直接关闭
}
},
// 解除报警关闭的那个提示
cancel: {
config: {
titleColor: 'rgba(224, 52, 52, 1)',
icon: '/static/images/6170/svg.png',
icon: '/static/images/common/svg.png',
popupBorder: '1rpx solid rgba(224, 52, 52, 0.3)',
confirmBtnBg: 'rgba(224, 52, 52, 1)',
showCancel: true //取消按钮
},
confirm() {
onConfirm() {
console.log('解除报警确认');
}
},
// 手动报警弹框
del: {
config: {
message: '确定开启报警?',
@ -310,26 +302,8 @@
confirmBtnBg: 'rgba(255, 200, 78, 1)',
showCancel: true
},
confirm() {
return 'alarmCountdown'; //点击确认,再次弹框,解除报警,再次报警的类型
}
},
// 手动报警再次弹框 再次报警,解除报警指令
alarmCountdown: {
config: {
title: '报警倒计时',
icon: '/static/images/6170/svg.png',
message: '59秒',
popupBorder: '1rpx solid rgba(224, 52, 52, 1)',
confirmBtnBg: 'rgba(224, 52, 52, 1)',
cancelBtnColor:"rgba(224, 52, 52, 1)",
confirmBtnColor:"rgba(255, 255, 255, 0.87)",
confirmText: '解除报警',
cancelText:"再次报警",
showCancel: true //取消按钮
},
confirm() {
console.log('解除报警确认');
onConfirm() {
console.log('删除确认');
}
},
// 自动报警
@ -346,8 +320,9 @@
confirmBtnColor: "rgba(255, 255, 255, 0.87)",
showCancel: false,
},
confirm() {
console.log('自动报警解除报警的弹框');
onConfirm() {
console.log('自动报警确认');
// 这里可以添加自动报警的逻辑
}
}
@ -462,19 +437,12 @@
this.currentPopup = {
show: true,
config: POPUP_CONFIGS[type].config,
callback: POPUP_CONFIGS[type].confirm
callback: POPUP_CONFIGS[type].onConfirm
}
},
handleConfirm() {
if (this.currentPopup.callback) {
const nextPopupType = this.currentPopup.callback(); // 执行回调并获取下一个弹框类型
this.currentPopup.show = false; // 关闭当前弹框
if (nextPopupType) {
this.showPopup(nextPopupType); // 打开下一个弹框
}
} else {
this.currentPopup.show = false; // 默认关闭
}
this.currentPopup.show = false;
console.log('这是点击了确认');
},
// 统一处理取消
handleCancel() {
@ -920,8 +888,7 @@
.mode-v1.active-mode .battery-v2 {
color: #BBE600 !important;
}
.mode-v1.active-mode .mode-v3 {
.mode-v1.active-mode .mode-v3{
color: #BBE600 !important;
}

View File

@ -2,7 +2,7 @@
<view>
<view class="device-page">
<view class="sendFlex">
<view class="Sendmessage" @click="call">呼叫</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"
@ -79,20 +79,6 @@
}
})
},
// 呼叫功能
call(){
uni.navigateTo({
url: '/pages/210/call/index',
events: {
ack: function(data) {}
},
success: (res) => {
res.eventChannel.emit('deviceCall', {
data:this.deviceType
});
}
})
}
},
onShow() {
this.getData()

View File

@ -25,18 +25,21 @@
onLoad: function(option) {
const eventChannel = this.getOpenerEventChannel();
var these = this;
eventChannel.on('checkImg', function(data) {
eventChannel.on('checkImg', (data)=> {
console.log("我收到你的消息了,消息内容是:" + JSON.stringify(data));
these.src = data.data;
this.src = data.data;
console.log("我收到你的消息了,消息内容是:",data);
})
},
methods: {
handleCrop(e) {
var these = this;
this.Statu = true;
console.log("裁剪完成");
console.log(e.tempFilePath);
//
const ctx = uni.createCanvasContext('splashCanvas', this);
ctx.drawImage(
e.tempFilePath,
@ -53,11 +56,12 @@
height: 80,
success: (res) => {
// 处理像素数据并发送
const eventChannel = these.getOpenerEventChannel();
console.log("res.data.length="+res.data.length);
// this.processAndSendImageData(res.data).then(
// resolve).catch(reject);
const eventChannel = these.getOpenerEventChannel();
eventChannel.emit('ImgCutOver',res.data);
eventChannel.emit('ImgCutOver_Path',e.tempFilePath);
uni.navigateBack();
},
fail: (err) => {

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,23 @@
<template>
<view class="share">
<!-- 下拉刷新区域 -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :up="upOption" :down="downOption">
<view class="device-title">已分享用户</view>
<view class="" v-if="deviceList.length>0">
<view class="device-info" v-for="(item, index) in deviceList" :key="index">
<view class="device-header" @click.stop="handleFile(item)">
<view class="deviceIMG">
<image src="@/static/images/common/user.png" mode="aspectFit" class="IMG"></image>
</view>
<view class="device-name">
<view>用户名{{item.deviceName}}</view>
<view class="ID">
<view class="ID">{{item.phonenumber}}
</view>
</view>
</view>
<view class="device-delete">
<text class="delete" @click.stop="handleDelete(item)">移除</text>
<view class="device-title">已分享用户</view>
<view class="device-info" v-for="(item, index) in deviceList" :key="index">
<view class="device-header" @click.stop="handleFile(item)">
<view class="deviceIMG">
<image src="@/static/images/common/user.png" mode="aspectFit" class="IMG"></image>
</view>
<view class="device-name">
<view>用户名{{item.deviceName}}</view>
<view class="ID">
<view class="ID">{{item.phonenumber}}
</view>
</view>
</view>
</view>
<view v-else class="noDATA">
<view> <uni-icons type="image-filled" size="120" color="rgba(255, 255, 255, 0.9)"></uni-icons>
<view class="device-delete">
<text class="delete" @click.stop="handleDelete(item)">移除</text>
</view>
暂无数据
</view>
</mescroll-uni>
</view>
<!-- 删除弹框 -->
<view class="agreement-mask" v-if="deleteShow" @click="closePopup('delete')">
<view class="agreement-popup" @click.stop>
@ -53,62 +42,16 @@
deviceShareList,
deviceShareDelete
} from '@/api/6170/share.js'
import MescrollUni from 'mescroll-uni/mescroll-uni.vue'
export default {
components: {
MescrollUni
},
data() {
return {
deviceList: [],
deleteShow: false,
delelteItemInfo: '',
itemInfo: '',
mescroll: null, // mescroll实例对象
downOption: {
auto: false // 不自动加载
},
upOption: {
auto: false, // 不自动加载
noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据
empty: {
tip: '暂无相关数据'
}
},
page: 1, // 当前页码
size: 10, // 每页条数
total: 0 // 总数据量
itemInfo: ''
}
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
mescrollInit(mescroll) {
this.mescroll = mescroll;
},
// 下拉刷新的回调
downCallback() {
// 重置分页参数
this.page = 1;
this.getData(this.itemInfo.id).then(res => {
// 数据请求成功后,隐藏下拉刷新的状态
this.mescroll.endSuccess();
}).catch(() => {
// 请求失败,隐藏下拉刷新的状态
this.mescroll.endErr();
})
},
// 上拉加载的回调
upCallback() {
this.getData(this.itemInfo.id).then(res => {
// 根据是否有数据来决定是否显示无更多数据的提示
const hasNext = this.deviceList.length < this.total;
this.mescroll.endSuccess(this.deviceList.length, hasNext);
}).catch(() => {
// 请求失败,隐藏上拉加载的状态
this.mescroll.endErr();
})
},
// 点击弹框外的区域关闭
closePopup(type) {
if (type === 'delete') {
@ -130,43 +73,25 @@
icon: 'none'
})
this.deleteShow = false
// 删除后刷新列表
this.page = 1;
this.getData(this.itemInfo.id).then(() => {
this.mescroll.resetUpScroll();
})
this.getData()
} else {
uni.showToast({
title: res.msg,
icon: 'none'
})
}
})
//
},
getData(val) {
return new Promise((resolve, reject) => {
let data = {
deviceId: val,
pageNum: this.page,
pageSize: this.size,
let data = {
deviceId: val
}
deviceShareList(data).then((res) => {
if (res.code == 200) {
this.deviceList = res.rows
}
deviceShareList(data).then((res) => {
if (res.code == 200) {
this.total = res.total;
if (this.page === 1) {
// 如果是第一页,直接替换数据
this.deviceList = res.rows;
} else {
// 如果不是第一页,追加数据
this.deviceList = this.deviceList.concat(res.rows);
}
resolve(res);
} else {
reject(res);
}
}).catch(err => {
reject(err);
})
})
},
// 跳转分享详情
@ -182,6 +107,7 @@
}
})
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
@ -189,14 +115,7 @@
eventChannel.on('shareManagement', (data) => {
console.log(data, 'data1t111');
this.itemInfo = data.data;
// 初始化加载数据
this.page = 1;
this.getData(this.itemInfo.id).then(() => {
// 数据加载完成后,如果需要可以手动触发下拉刷新结束
if (this.mescroll) {
this.mescroll.endSuccess();
}
})
this.getData(this.itemInfo.id)
})
}
}
@ -211,7 +130,7 @@
.device-title {
color: rgba(255, 255, 255, 0.87);
padding: 30rpx;
padding: 30rpx 0;
}
.device-info {
@ -243,7 +162,7 @@
.deviceIMG {
/* width: 100rpx; */
/* height: 100rpx; */
/* height: 100rpx; */
position: relative;
display: flex;
align-items: center;
@ -254,12 +173,6 @@
width: 50%;
}
.noDATA {
text-align: center;
color: rgba(255, 255, 255, 0.87);
transform: translate(-0%, 100%);
}
.delete {
border-radius: 32px;
background: rgba(255, 200, 78, 0.06);

1841
pages/650/HBY650.vue Normal file

File diff suppressed because it is too large Load Diff

1841
pages/670/HBY670.vue Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,472 @@
<template>
<view class="content">
<canvas canvas-id="flashCanvas"
style="width: 160px; height: 80px; z-index: 9999;position: fixed; top:-9999px;left:-9999px;"></canvas>
<f-video ref="compARef" :src="videoPath" :direction="-90" :autoplay="true" @shotVideoClick="shotVideoClick"
:videoWidth="videoWidth" :videoHeight="videoHeight"></f-video>
<view>
<text>发送间隔</text>
<input type="text" v-model="inteval" />
</view>
<view>
<button @click="checkVideo">选择视频</button>
<!-- <button @click="CutImg">发送</button> -->
<button @click="uploadVideo">发送</button>
</view>
<view class="sending-progress" v-if="isSending">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>
</view>
</view>
</template>
<script>
import Common from '@/utils/Common';
export default {
data() {
return {
videoPath: '',
inteval: 0,
progress: 0,
currentPacket: 0,
totalPackets: 100,
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
isSending: "",
textProgress: "",
imgs: [],
videoWidth: 320,
videoHeight: 160,
videoDuration: 2,
hexArray: []
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('receiveDevice', (data) => {
this.connectedDeviceId = data.connectedDeviceId;
this.serviceId = data.serviceId;
this.writeCharacteristicId = data.writeCharacteristicId;
this.notifyCharacteristicId = data.notifyCharacteristicId;
})
},
methods: {
checkVideo: function() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
maxDuration: 2,
camera: 'back',
success: (res) => {
this.videoPath = res.tempFilePath;
this.imgs = [];
this.hexArray = [];
this.$refs.compARef.base64 = [];
this.videoWidth = res.width;
this.videoHeight = res.height;
this.videoDuration = res.duration;
console.log("视频宽:" + res.width + ",视频高:" + res.height + ",视频时长:" + res.duration);
}
})
},
uploadVideo: function() {
if (this.hexArray.length > 0) {
console.log("开始处理,无需上传");
this.shotVideoClick(this.hexArray, 'rgb565');
return;
}
if(!this.videoPath){
uni.showToast({
title: "请选择视频",
icon: 'fail'
})
return;
}
console.log("正在上传视频");
uni.showLoading({
title: "上传中"
});
let p2=new Promise((resolve,reject)=>{
let start = new Date();
console.log("Common.baseURL="+Common.baseURL);
uni.uploadFile({
url:Common.baseURL+'video/upload',
filePath: this.videoPath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data"
},
timeout: 600000,
fail: (ex) => {
//console.log("上传视频失败" + JSON.stringify(ex));
uni.showToast({
title: "视频文件上传失败了,请检查网络连接",
icon: 'fail'
})
uni.hideLoading();
reject(ex);
},
success: (res) => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("上传完成,耗时:" + m + "分" + s + "秒");
uni.hideLoading();
resolve(res);
}
});
});
let p1=this.HoldYouHand();
Promise.all([p2,p1]).then((arr)=>{
if(arr[1]===true){
let res=arr[0];
res = JSON.parse(res.data);
if (res.data) {
this.hexArray = res.data;
uni.showLoading({
title: "正在发送"
});
setTimeout(() => {
this.shotVideoClick(res.data, 'rgb565');
}, 0)
} else {
console.log("res")
uni.showModal({
content: "服务器未返回RGB565数据",
title: '错误'
})
}
}else{
uni.showModal({
content:"与设备握手失败了",
title:"错误"
})
}
});
},
shotVideoClick: function(array, type) {
//console.log("处理视频完成", array);
//console.log("type=" + type)
//console.log("array=", array);
this.imgs = array;
var sendImagePackets = (imageData) => {
return new Promise((resolve, reject) => {
this.isSending = true;
this.progress = 0;
this.currentPacket = 0;
// 总数据包数
const totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
// 发送单个数据包
const sendNextPacket = () => {
////console.log("currentPacket="+currentPacket+",imageData.length="+imageData.length);
if (currentPacket > totalPackets) {
this.isSending = false;
resolve();
return;
}
// 计算当前包的数据
let packetSize = 250;
if (type == 'rgb565') {
packetSize = 500;
}
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部5字节 + 数据部分
const buffer = new ArrayBuffer(bufferSize);
const dataView = new DataView(buffer);
let sortNo = currentPacket.toString(16).padStart(4, '0');
// 填充头部
dataView.setUint8(0, 0x55); // 帧头
dataView.setUint8(1, 0x04); // 帧类型:开机画面
dataView.setUint8(2, '0x' + sortNo.substring(0, 2)); // 包序号
dataView.setUint8(3, '0x' + sortNo.substring(2, 4)); // 包序号
dataView.setUint8(4, 0x01);
dataView.setUint8(5, 0xF4);
if (type == 'rgb565') {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(6 + i, '0x' + packetData[i]);
}
} else {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(6 + i * 2, packetData[i], false);
}
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
this.sendData(buffer).then(() => {
// 更新进度
this.currentPacket = currentPacket;
this.progress = Math.round((currentPacket / totalPackets) *
100);
//console.log(`发送数据包完成 ${currentPacket}/${totalPackets}`);
// 发送下一个包(添加延迟避免蓝牙缓冲区溢出)
currentPacket++;
setTimeout(sendNextPacket, inteval);
}).catch(err => {
// console.log(err.errMsg + ",发送失败了,正在补偿:" + currentPacket);
setTimeout(sendNextPacket, inteval);
// uni.showToast({
// title:"发送失败"+JSON.stringify(err)
// })
});
};
sendNextPacket();
});
}
if (type == 'rgb565') {
let start = new Date();
console.log("开始发送");
sendImagePackets(array).then(() => {
console.log("发送完成");
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff-s) / 60;
console.log("发送完成,耗时:" + m + "分" + s + "秒");
uni.showToast({
title: "发送完成,耗时:" + m + "分" + s + "秒",
icon: 'success'
})
}).catch((ex1) => {
//console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
return;
}
},
HoldYouHand() {
var promise=new Promise((resolve,reject)=>{
try{
let start=new Date();
var str = "video transmit start"; //握手的协议字符串
console.log("开始握手:"+str)
// 1. 创建 ArrayBuffer 和 DataView
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
// 2. 将字符串转换为 ASCII 码并写入 DataView
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
//console.log("111111");
this.sendData(buffer).then(() => {
// 开始发送第一个包
setTimeout(()=>{
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("握手成功并完成2200ms等待,耗时"+m+"分"+s+"秒");
resolve(true);
}, 2200);
}).catch(err => {
//console.log("握手没有成功");
reject(err);
});
}catch(ex){
reject(ex);
}
});
return promise;
},
sendData(buffer) {
////console.log("deviceId=" + this.connectedDeviceId);
////console.log("serviceId=" + this.serviceId);
return new Promise(async (resolve, reject) => {
// //console.log("开始发送数据buffer");
var promise = new Promise((succ, err) => {
uni.writeBLECharacteristicValue({
deviceId: this.connectedDeviceId,
serviceId: this.serviceId,
characteristicId: this.writeCharacteristicId,
value: buffer,
writeType: plus.os.name == 'iOS' ? 'write' : 'writeNoResponse',
success: () => {
// //console.log("发送数据成功");
succ();
},
fail: (ex) => {
//console.log("发送数据失败", ex);
err(ex);
},
complete: function() {
// //console.log("123456");
}
});
});
if (plus.os.name == 'iOS') {
function timeout(ms) {
return new Promise((_, err) => {
setTimeout(() => {
err({
code: -1,
errMsg: '超时了'
})
}, ms);
});
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
Promise.race([promise, timeout(inteval)]).then(resolve).catch((ex) => {
//console.log("ex=", ex);
if (ex.code == -1) {
resolve();
} else {
reject();
}
}).finally(() => {
//console.log("完成了")
});
} else {
promise.then(resolve).catch(reject);
}
});
},
CutImg: function() {
if (this.imgs.length == 30) {
this.shotVideoClick(this.imgs, 'img');
return;
}
//console.log("开始处理视频")
uni.showLoading({
title: '开始处理'
});
this.$refs.compARef.shotVideoClick(0);
}
}
}
</script>
<style>
.sending-progress {
margin-top: 30rpx;
width: 100%;
}
.progress-bar {
height: 12rpx;
background-color: #e0e0e0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #409eff;
transition: width 0.3s;
}
input {
border: 2rpx solid #000000;
}
button {
height: 100rpx;
line-height: 100rpx;
font-size: 28rpx;
float: left;
}
.content {
width: 100vw;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,517 @@
<template>
<view class="content">
<canvas canvas-id="flashCanvas"
style="width: 160px; height: 80px; z-index: 9999;position: fixed; top:-9999px;left:-9999px;"></canvas>
<f-video ref="compARef" :src="videoPath" :direction="-90" :autoplay="true" @shotVideoClick="shotVideoClick"
:videoWidth="videoWidth" :videoHeight="videoHeight"></f-video>
<view>
<text>并发包数量</text>
<input type="text" v-model="packgeCnt" />
</view>
<view>
<text>发送间隔</text>
<input type="text" v-model="inteval" />
</view>
<view>
<button @click="checkVideo">选择视频</button>
<!-- <button @click="CutImg">发送</button> -->
<button @click="uploadVideo">发送</button>
</view>
<view class="sending-progress" v-if="isSending">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
videoPath: '',
packgeCnt: 20,
inteval: 0,
progress: 0,
currentPacket: 0,
totalPackets: 100,
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
isSending: "",
textProgress: "",
imgs: [],
videoWidth: 320,
videoHeight: 160,
videoDuration: 2,
hexArray: []
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('receiveDevice', (data) => {
this.connectedDeviceId = data.connectedDeviceId;
this.serviceId = data.serviceId;
this.writeCharacteristicId = data.writeCharacteristicId;
this.notifyCharacteristicId = data.notifyCharacteristicId;
})
},
methods: {
checkVideo: function() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
maxDuration: 2,
camera: 'back',
success: (res) => {
this.videoPath = res.tempFilePath;
this.imgs = [];
this.hexArray = [];
this.$refs.compARef.base64 = [];
this.videoWidth = res.width;
this.videoHeight = res.height;
this.videoDuration = res.duration;
console.log("视频宽:" + res.width + ",视频高:" + res.height + ",视频时长:" + res.duration);
}
})
},
uploadVideo: function() {
if (this.hexArray.length > 0) {
console.log("开始处理,无需上传");
this.shotVideoClick(this.hexArray, 'rgb565');
return;
}
if(!this.videoPath){
uni.showToast({
title: "请选择视频",
icon: 'fail'
})
return;
}
console.log("正在上传视频");
uni.showLoading({
title: "上传中"
});
let p2=new Promise((resolve,reject)=>{
console.log("Common.baseURL="+Common.baseURL);
let start = new Date();
uni.uploadFile({
url: Common.baseURL+'video/upload',
// url: 'http://192.168.110.169:5000/video/upload',
filePath: this.videoPath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data"
},
timeout: 600000,
fail: (ex) => {
//console.log("上传视频失败" + JSON.stringify(ex));
uni.showToast({
title: "视频文件上传失败了,请检查网络连接",
icon: 'fail'
})
uni.hideLoading();
reject(ex);
},
success: (res) => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("上传完成,耗时:" + m + "分" + s + "秒");
uni.hideLoading();
resolve(res);
}
});
});
let p1=this.HoldYouHand();
Promise.all([p2,p1]).then((arr)=>{
if(arr[1]===true){
let res=arr[0];
res = JSON.parse(res.data);
if (res.data) {
this.hexArray = res.data;
uni.showLoading({
title: "正在发送"
});
setTimeout(() => {
this.shotVideoClick(res.data, 'rgb565');
}, 0)
} else {
console.log("res")
uni.showModal({
content: "服务器未返回RGB565数据",
title: '错误'
})
}
}else{
uni.showModal({
content:"与设备握手失败了",
title:"错误"
})
}
});
},
pause(e) {
////console.log('pause--------------------------', e);
},
shotVideoClick: function(array, type) {
//console.log("处理视频完成", array);
//console.log("type=" + type)
//console.log("array=", array);
this.imgs = array;
var sendImagePackets = (imageData) => {
return new Promise((resolve, reject) => {
this.isSending = true;
this.progress = 0;
this.currentPacket = 0;
// 总数据包数
const totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
let promises = [];
// 发送单个数据包
const sendNextPacket = () => {
////console.log("currentPacket="+currentPacket+",imageData.length="+imageData.length);
if (currentPacket > totalPackets) {
this.isSending = false;
resolve();
return;
}
// 计算当前包的数据
let packetSize = 250;
if (type == 'rgb565') {
packetSize = 500;
}
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部5字节 + 数据部分
const buffer = new ArrayBuffer(bufferSize);
const dataView = new DataView(buffer);
let sortNo = currentPacket.toString(16).padStart(4, '0');
// 填充头部
dataView.setUint8(0, 0x55); // 帧头
dataView.setUint8(1, 0x04); // 帧类型:开机画面
dataView.setUint8(2, '0x' + sortNo.substring(0, 2)); // 包序号
dataView.setUint8(3, '0x' + sortNo.substring(2, 4)); // 包序号
dataView.setUint8(4, 0x01);
dataView.setUint8(5, 0xF4);
if (type == 'rgb565') {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(6 + i, '0x' + packetData[i]);
}
} else {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(6 + i * 2, packetData[i], false);
}
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
let promise = this.sendData(buffer);
promises.push(promise);
let packgeCnt = parseInt(this.packgeCnt || 20);
if (currentPacket % packgeCnt == 0 || (currentPacket >= totalPackets &&
promises.length > 0)) {
Promise.all(promises).then(() => {
if (currentPacket >= totalPackets) {
this.isSending = false;
resolve();
return;
}
this.currentPacket = currentPacket;
this.progress = Math.round((currentPacket / totalPackets) *
100);
currentPacket++;
setTimeout(sendNextPacket, inteval);
})
} else {
currentPacket++;
sendNextPacket();
}
// .then(() => {
// // 更新进度
// this.currentPacket = currentPacket;
// this.progress = Math.round((currentPacket / totalPackets) *
// 100);
// currentPacket++;
// setTimeout(sendNextPacket, inteval);
// }).catch(err => {
// console.log(err.errMsg+",发送失败了,正在补偿:" + currentPacket);
// setTimeout(sendNextPacket, inteval);
// });
};
//
sendNextPacket();
});
}
if (type == 'rgb565') {
let start = new Date();
console.log("开始发送");
sendImagePackets(array).then(() => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("发送完成,耗时:" + m + "分" + s + "秒");
uni.showToast({
title: "发送完成,耗时:" + m + "分" + s + "秒",
icon: 'success',
})
}).catch((ex1) => {
//console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
return;
}
},
HoldYouHand() {
var promise=new Promise((resolve,reject)=>{
try{
let start=new Date();
var str = "video transmit start"; //握手的协议字符串
console.log("开始握手:"+str)
// 1. 创建 ArrayBuffer 和 DataView
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
// 2. 将字符串转换为 ASCII 码并写入 DataView
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
//console.log("111111");
this.sendData(buffer).then(() => {
// 开始发送第一个包
setTimeout(()=>{
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("握手成功并完成2200ms等待,耗时"+m+"分"+s+"秒");
resolve(true);
}, 2200);
}).catch(err => {
//console.log("握手没有成功");
reject(err);
});
}catch(ex){
reject(ex);
}
});
return promise;
},
sendData(buffer) {
let sendBuffer = () => {
return new Promise((resolve, reject) => {
var promise = new Promise((succ, err) => {
uni.writeBLECharacteristicValue({
deviceId: this.connectedDeviceId,
serviceId: this.serviceId,
characteristicId: this.writeCharacteristicId,
value: buffer,
writeType: plus.os.name == 'iOS' ? 'write' : 'writeNoResponse',
success: () => {
// console.log("发送数据成功");
succ();
},
fail: (ex) => {
if (ex.code == '10007') {
// console.log("失败重试");
setTimeout(() => {
sendBuffer().then(succ).catch(err);
}, this.inteval || 0)
// succ()
} else
{
// console.log("发送数据失败",ex);
err(ex);
}
},
complete: function() {
//console.log("123456");
}
});
});
if (plus.os.name == 'iOS') {
function timeout(ms) {
return new Promise((_, err) => {
setTimeout(() => {
err({
code: -1,
errMsg: '超时了'
})
}, ms);
});
}
Promise.race([promise, timeout(this.inteval ? this.inteval : 0)]).then(() => {
// console.log("成功了");
resolve();
})
.catch((ex) => {
if (ex.code == -1) {
// console.log("超时了")
resolve();
} else {
reject(ex);
// console.log("异常了", ex);
//sendBuffer().then(resolve).catch(reject);
}
});
} else {
promise.then(() => {
//console.log("then........")
resolve();
}).catch(() => {
//console.log("catch.........")
reject()
});
}
});
}
return sendBuffer();
},
CutImg: function() {
if (this.imgs.length == 30) {
this.shotVideoClick(this.imgs, 'img');
return;
}
//console.log("开始处理视频")
uni.showLoading({
title: '开始处理'
});
this.$refs.compARef.shotVideoClick(0);
}
}
}
</script>
<style>
.sending-progress {
margin-top: 30rpx;
width: 100%;
}
.progress-bar {
height: 12rpx;
background-color: #e0e0e0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #409eff;
transition: width 0.3s;
}
input {
border: 2rpx solid #000000;
}
button {
height: 100rpx;
line-height: 100rpx;
font-size: 28rpx;
float: left;
}
.content {
width: 100vw;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,537 @@
<template>
<view class="content">
<canvas canvas-id="flashCanvas"
style="width: 160px; height: 80px; z-index: 9999;position: fixed; top:-9999px;left:-9999px;"></canvas>
<view>
<view>
选择的视频:{{videoPath}}</view>
</view>
<view>
重发包序号:{{reSendNumber}}
</view>
<view>
<text>发送间隔</text>
<input type="text" v-model="inteval" />
</view>
<view>
<button @click="checkVideo">选择视频</button>
<button @click="uploadVideo">发送</button>
</view>
<view class="sending-progress" v-if="isSending">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>
</view>
</view>
</template>
<script>
import Common from '../../../utils/Common';
var mqttClient=null;
export default {
data() {
return {
videoPath: '',
inteval: 0,
progress: 0,
currentPacket: 0,
totalPackets: 100,
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
isSending: "",
textProgress: "",
netMode:"ble",
IMEI:"",
imgs: [],
videoWidth: 320,
videoHeight: 160,
videoDuration: 2,
hexArray: [],
reSendNumber:""
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('receiveDevice', (data) => {
this.connectedDeviceId = data.connectedDeviceId;
this.serviceId = data.serviceId;
this.writeCharacteristicId = data.writeCharacteristicId;
this.notifyCharacteristicId = data.notifyCharacteristicId;
this.netMode=data.netMode;
mqttClient=data.mqttClient;
this.IMEI=data.IMEI;
});
eventChannel.on('ReSendVideo',(data)=>{
//重新发送某一包
this.reSendNumber=data.videoNo;
setTimeout(()=>{
this.shotVideoClick(this.hexArray,'rgb565',data.videoNo);
},0);
});
},
methods: {
checkVideo: function() {
uni.chooseVideo({
sourceType: ['album', 'camera'],
compressed: false,
maxDuration: 2,
camera: 'back',
success: (res) => {
this.videoPath = res.tempFilePath;
this.imgs = [];
this.hexArray = [];
this.videoWidth = res.width;
this.videoHeight = res.height;
this.videoDuration = res.duration;
console.log("视频宽:" + res.width + ",视频高:" + res.height + ",视频时长:" + res.duration);
}
})
},
uploadVideo: function() {
if (this.hexArray.length > 0) {
console.log("开始处理,无需上传");
this.shotVideoClick(this.hexArray, 'rgb565');
return;
}
if(!this.videoPath){
uni.showToast({
title: "请选择视频",
icon: 'fail'
})
return;
}
console.log("正在上传视频");
uni.showLoading({
title: "上传中"
});
let p2=new Promise((resolve,reject)=>{
let start = new Date();
console.log("Common.baseURL="+Common.baseURL);
uni.uploadFile({
url:Common.baseURL+'video/upload',
filePath: this.videoPath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data"
},
timeout: 600000,
fail: (ex) => {
//console.log("上传视频失败" + JSON.stringify(ex));
uni.showToast({
title: "视频文件上传失败了,请检查网络连接",
icon: 'fail'
})
uni.hideLoading();
reject(ex);
},
success: (res) => {
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("上传完成,耗时:" + m + "分" + s + "秒");
uni.hideLoading();
resolve(res);
}
});
});
let p1=this.HoldYouHand();
Promise.all([p2,p1]).then((arr)=>{
if(arr[1]===true){
let res=arr[0];
res = JSON.parse(res.data);
if (res.data) {
this.hexArray = res.data;
uni.showLoading({
title: "正在发送"
});
setTimeout(() => {
this.shotVideoClick(res.data, 'rgb565');
}, 0)
} else {
console.log("res")
uni.showModal({
content: "服务器未返回RGB565数据",
title: '错误'
})
}
}else{
uni.showModal({
content:"与设备握手失败了",
title:"错误"
})
}
});
},
shotVideoClick: function(array, type,ReSendNo) {
//console.log("处理视频完成", array);
//console.log("type=" + type)
//console.log("array=", array);
this.imgs = array;
var sendImagePackets = (imageData) => {
return new Promise((resolve, reject) => {
this.isSending = true;
this.progress = 0;
this.currentPacket = 0;
// 总数据包数
var totalPackets = 1536;
this.totalPackets = totalPackets;
let currentPacket = 1;
if(ReSendNo){
this.progress = ReSendNo-1;
this.currentPacket = ReSendNo-1;
currentPacket=ReSendNo;
totalPackets=ReSendNo;
this.totalPackets=ReSendNo;
}
// 发送单个数据包
const sendNextPacket = () => {
////console.log("currentPacket="+currentPacket+",imageData.length="+imageData.length);
if (currentPacket > totalPackets) {
this.isSending = false;
if(!ReSendNo){
this.bleSendComplete();
}else{
// this.reSendNumber="";
}
resolve();
return;
}
// 计算当前包的数据
let packetSize = 250;
if (type == 'rgb565') {
packetSize = 500;
}
// 创建数据包
const startIndex = (currentPacket - 1) * packetSize;
const endIndex = Math.min(startIndex + packetSize, imageData.length);
if (startIndex > endIndex) {
resolve();
return;
}
////console.log("111111");
const packetData = imageData.slice(startIndex, endIndex);
// 构建数据包
////console.log("packetData.length"+packetData.length);
const bufferSize = 506; // 头部5字节 + 数据部分
const buffer = new ArrayBuffer(bufferSize);
const dataView = new DataView(buffer);
let sortNo = currentPacket.toString(16).padStart(4, '0');
// 填充头部
dataView.setUint8(0, 0x55); // 帧头
dataView.setUint8(1, 0x04); // 帧类型:开机画面
dataView.setUint8(2, '0x' + sortNo.substring(0, 2)); // 包序号
dataView.setUint8(3, '0x' + sortNo.substring(2, 4)); // 包序号
dataView.setUint8(4, 0x01);
dataView.setUint8(5, 0xF4);
if (type == 'rgb565') {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(6 + i, '0x' + packetData[i]);
}
} else {
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(6 + i * 2, packetData[i], false);
}
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
this.sendData(buffer).then(() => {
// 更新进度
this.currentPacket = currentPacket;
this.progress = Math.round((currentPacket / totalPackets) *
100);
console.log(`发送数据包完成 ${currentPacket}/${totalPackets}`);
// 发送下一个包(添加延迟避免蓝牙缓冲区溢出)
currentPacket++;
setTimeout(sendNextPacket, inteval);
}).catch(err => {
console.log(err.errMsg + ",发送失败了,正在补偿:" + currentPacket);
setTimeout(sendNextPacket, inteval);
// uni.showToast({
// title:"发送失败"+JSON.stringify(err)
// })
});
};
sendNextPacket();
});
}
if (type == 'rgb565') {
let start = new Date();
console.log("开始发送");
sendImagePackets(array).then(() => {
console.log("发送完成");
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff-s) / 60;
console.log("发送完成,耗时:" + m + "分" + s + "秒");
uni.showModal({
content: "发送完成,耗时:" + m + "分" + s + "秒",
title: 'success'
});
}).catch((ex1) => {
console.log("出现了异常", ex1)
}).finally(() => {
uni.hideLoading();
});
return;
}
},
HoldYouHand() {
var promise=new Promise((resolve,reject)=>{
try{
let start=new Date();
var str = "video transmit start"; //握手的协议字符串
console.log("开始握手:"+str)
// 1. 创建 ArrayBuffer 和 DataView
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
// 2. 将字符串转换为 ASCII 码并写入 DataView
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
//console.log("111111");
this.sendData(buffer).then(() => {
// 开始发送第一个包
setTimeout(()=>{
let end = new Date();
var diff = (end.getTime() - start.getTime()) / 1000;
let s = diff % 60;
let m = (diff - s) / 60;
console.log("握手成功并完成2200ms等待,耗时"+m+"分"+s+"秒");
resolve(true);
}, 2200);
}).catch(err => {
//console.log("握手没有成功");
reject(err);
});
}catch(ex){
reject(ex);
}
});
return promise;
},
bleSendComplete() {
var str = "transmit complete"; //握手的协议字符串
let buffer = new ArrayBuffer(str.length);
let dataView = new DataView(buffer);
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
setTimeout(()=>{
this.sendData(buffer).then(() => {
console.log("完成指令发送成功");
}).catch(err => {
console.log("完成指令发送失败");
});
},500)
},
sendData(buffer) {
if(this.netMode=='ble'){
return this.sendBle(buffer);
}
return this.sendMQ(buffer);
},
sendBle(buffer){
return new Promise(async (resolve, reject) => {
// //console.log("开始发送数据buffer");
var promise = new Promise((succ, err) => {
uni.writeBLECharacteristicValue({
deviceId: this.connectedDeviceId,
serviceId: this.serviceId,
characteristicId: this.writeCharacteristicId,
value: buffer,
writeType: plus.os.name == 'iOS' ? 'write' : 'writeNoResponse',
success: () => {
// //console.log("发送数据成功");
succ();
},
fail: (ex) => {
//console.log("发送数据失败", ex);
err(ex);
},
complete: function() {
// //console.log("123456");
}
});
});
if (plus.os.name == 'iOS') {
function timeout(ms) {
return new Promise((_, err) => {
setTimeout(() => {
err({
code: -1,
errMsg: '超时了'
})
}, ms);
});
}
let inteval = parseInt(this.inteval ? this.inteval : 0);
Promise.race([promise, timeout(inteval)]).then(resolve).catch((ex) => {
//console.log("ex=", ex);
if (ex.code == -1) {
resolve();
} else {
reject();
}
}).finally(() => {
//console.log("完成了")
});
} else {
promise.then(resolve).catch(reject);
}
});
},
sendMQ(message) {
const topic = `B/${this.IMEI}`;
return new Promise((resolve, reject) => {
if(!mqttClient){
reject("MQTT未连接");
return;
}
try {
let flag=mqttClient.publish(topic, message, {
qos: 1
});
if(flag){
resolve();
return;
}
reject("MQTT未连接无法发布消息");
} catch (error) {
reject(error);
}
});
}
}
}
</script>
<style>
.sending-progress {
margin-top: 30rpx;
width: 100%;
}
.progress-bar {
height: 12rpx;
background-color: #e0e0e0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #409eff;
transition: width 0.3s;
}
input {
border: 2rpx solid #000000;
}
button {
height: 100rpx;
line-height: 100rpx;
font-size: 28rpx;
float: left;
}
.content {
width: 100vw;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,115 @@
<template>
<view class="container">
<view class="grid">
<view class="cell" @click="goToDetail(item.name)" v-for="item,index in options">{{item.url}}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
options: [{
name: '/pages/BlueTooth/ModeSetting/ModeSetting',
url: '7307'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY650',
url: 'HBY650'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY650_1',
url: 'HBY650_V1'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY6155',
url: '6155'
},
{
name: '/pages/BlueTooth/ModeSetting/HBY6155V1',
url: '6155_V1'
},
{
name: "/pages/BlueTooth/ModeSetting/HBY670",
url: 'HBY670'
},
{
name: '/pages/MapTest/MapTest',
url: '地图测试'
},
{
name: '',
url: '更多'
}
]
}
},
onShow: () => {
},
methods: {
goToDetail: function(url) {
console.log("url=" + url)
let qd = () => {
uni.showToast({
title: '敬请期待',
duration: 2000,
icon: "none"
});
};
if (url) {
uni.navigateTo({
url: url,
success: () => {
},
fail: () => {
qd();
}
});
} else {
qd();
}
}
}
}
</script>
<style>
.container {
padding: 15px;
background-color: #f5f5f5;
min-height: 100vh;
}
.grid {
display: flex;
align-content: space-around;
align-items: stretch;
justify-items: center;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
}
.cell {
padding: 0rpx 20rpx;
border: 2rpx solid rgba(0, 0, 0, 0.3);
border-radius: 15rpx;
font-size: 28rpx;
height: 70rpx;
line-height: 70rpx;
margin-left: 30rpx;
margin-top: 20rpx;
}
</style>

View File

@ -0,0 +1,273 @@
<template>
<view class="update-container">
<!-- 进度条 -->
<view v-if="showProgress" class="progress-container">
<view class="progress-title">正在更新 {{ progress }}%</view>
<view class="progress-bar">
<view class="progress" :style="{ width: progress + '%' }"></view>
</view>
</view>
<!-- 更新提示弹窗 -->
<view v-if="showUpdateDialog" class="dialog-mask">
<view class="dialog">
<view class="dialog-title">发现新版本 v{{ newVersion }}</view>
<view class="dialog-content">{{ updateInfo.desc || '有新的功能和优化,建议立即更新' }}</view>
<view class="dialog-buttons">
<button v-if="!updateInfo.force" class="cancel-btn" @click="showUpdateDialog = false">稍后更新</button>
<button class="confirm-btn" @click="startUpdate">立即更新</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
// 当前版本
currentVersion: '',
// 最新版本
newVersion: '',
// 更新信息
updateInfo: {},
// 是否显示更新弹窗
showUpdateDialog: false,
// 是否显示进度条
showProgress: false,
// 更新进度
progress: 0
};
},
onLoad() {
// 初始化时检查版本
this.checkVersion();
},
methods: {
/**
* 检查当前版本
*/
async checkVersion() {
try {
// 获取当前应用版本
const versionInfo = plus.runtime.version;
this.currentVersion = versionInfo;
console.log('当前版本:', this.currentVersion);
// 调用后端接口检查最新版本
// 这里替换为你的后端接口地址
const res = await this.$http.get('/api/checkVersion', {
platform: uni.getSystemInfoSync().platform,
version: this.currentVersion
});
if (res.code === 0 && res.data.hasUpdate) {
this.newVersion = res.data.version;
this.updateInfo = res.data;
// 显示更新提示
this.showUpdateDialog = true;
} else {
console.log('当前已是最新版本');
}
} catch (error) {
console.error('版本检查失败:', error);
}
},
/**
* 开始更新
*/
startUpdate() {
if (!this.updateInfo.downloadUrl) {
uni.showToast({
title: '更新地址不存在',
icon: 'none'
});
return;
}
this.showUpdateDialog = false;
this.showProgress = true;
this.downloadWgt(this.updateInfo.downloadUrl);
},
/**
* 下载wgt包
*/
downloadWgt(url) {
const downloadTask = uni.downloadFile({
url: url,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
// 下载成功安装wgt包
this.installWgt(downloadResult.tempFilePath);
} else {
this.showProgress = false;
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
},
fail: (err) => {
this.showProgress = false;
console.error('下载失败:', err);
uni.showToast({
title: '下载失败,请稍后重试',
icon: 'none'
});
}
});
// 监听下载进度
downloadTask.onProgressUpdate((res) => {
this.progress = res.progress;
});
},
/**
* 安装wgt包
*/
installWgt(path) {
plus.runtime.install(
path,
{
force: false // 是否强制安装
},
() => {
console.log('安装成功');
this.showProgress = false;
// 安装成功后提示重启
uni.showModal({
title: '更新完成',
content: '应用已更新,是否立即重启?',
showCancel: !this.updateInfo.force,
success: (res) => {
if (res.confirm) {
// 重启应用
plus.runtime.restart();
}
}
});
},
(err) => {
console.error('安装失败:', err);
this.showProgress = false;
uni.showToast({
title: '更新失败: ' + err.message,
icon: 'none',
duration: 3000
});
}
);
}
}
};
</script>
<style scoped>
.update-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
}
/* 进度条样式 */
.progress-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
padding: 10rpx 20rpx;
pointer-events: auto;
}
.progress-title {
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
text-align: center;
}
.progress-bar {
height: 8rpx;
background-color: #eee;
border-radius: 4rpx;
overflow: hidden;
}
.progress {
height: 100%;
background-color: #007aff;
transition: width 0.3s ease;
}
/* 弹窗样式 */
.dialog-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
pointer-events: auto;
}
.dialog {
width: 600rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.dialog-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
padding: 30rpx;
text-align: center;
border-bottom: 1px solid #eee;
}
.dialog-content {
font-size: 32rpx;
color: #666;
padding: 40rpx 30rpx;
line-height: 1.6;
}
.dialog-buttons {
display: flex;
border-top: 1px solid #eee;
}
.cancel-btn, .confirm-btn {
flex: 1;
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
border: none;
background-color: transparent;
}
.cancel-btn {
color: #666;
border-right: 1px solid #eee;
}
.confirm-btn {
color: #007aff;
}
</style>

View File

@ -1,22 +1,296 @@
<template>
<view>
<view class="content">
<view class="deviceDetail">
<view class="imgContent">
<image src="/static/images/BLEAdd/addBleDevice.png" class="titleIco" mode="aspectFit">
</image>
</view>
<view class="deviceName">
蓝牙名:{{device.name}}
</view>
<view class="deviceName">
设备名:{{device.deviceName}}
</view>
<view class="deviceId">
ID:{{device.deviceId}}
</view>
<view class="bound" v-bind:class="boundStatu">
{{Statu.boundRemark}}
</view>
</view>
<view class="btnLink" @click="Link()">
连接
</view>
<global-loading ref="loading" />
</view>
</template>
<script>
import request from '@/utils/request.js';
import bleTool from '@/utils/BleHelper.js';
import {
showLoading,
hideLoading,
updateLoading
} from '@/utils/loading.js';
const pagePath="pages/common/addBLE/LinkBle";
var these = null;
var eventChannel = null;
var ble = null;
export default {
data() {
return {
Statu: {
bound: null
},
device: {
"deviceId": "",
"name": "",
"deviceName": "",
"RSSI": -37,
"localName": "",
"advertisServiceUUIDs": [
],
"linkStatu": false,
"macAddress": ""
}
}
},
methods: {
computed: {
boundStatu: function() {
if (this.Statu.bound === null) {
return "displayNone"
}
if (this.Statu.bound) {
return "green"
} else {
return "red";
}
}
},
onBackPress() {
console.log("返回时断开蓝牙连接,取消订阅");
ble.disconnectDevice(these.device.deviceId);
ble.removeReceiveCallback(pagePath);
},
onUnload() {
ble.removeReceiveCallback(pagePath);
},
onLoad(option) {
these = this;
ble = bleTool.getBleTool();
ble.addReceiveCallback((receive,f,path) => {
console.log("收到设备消息,", receive);
if (these.device.deviceId == receive.deviceId) {
console.log("11111");
if (receive.bytes[0] == 0xFC || receive.str.indexOf('mac address:') == 0) {
if (f && f.macAddress) {
these.device.macAddress = f.macAddress;
console.log("222222");
these.initDevice();
}
}
}
},pagePath);
eventChannel = this.getOpenerEventChannel();
eventChannel.on('LinkItem', function(data) {
let f = ble.data.LinkedList.find((v) => {
return v.deviceId = data.deviceId;
});
if (f) {
these.device = Object.assign({}, these.device, f);
console.log("获取到设备", f);
} else {
console.log("未获取到设备");
}
})
},
methods: {
initDevice: function() {
showLoading(these, {
text: '正在获取设备信息'
});
request({
url: '/app/device/getDeviceInfoByDeviceMac',
method: 'GET',
data: {
deviceMac: these.device.macAddress
}
}).then(res => {
console.log("获取设备信息", res);
if (res && res.code == 200) {
let data = res.data;
if (data) {
let keys = Object.keys(data);
ble.data.LinkedList.find((v) => {
if(v.deviceId = these.device.deviceId){
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
v[key] = data[key];
console.log("key="+key);
console.log("value="+data[key]);
these.$set(these.device, key, data[key]);
}
ble.setBleData();
}
});
console.log("device=",these.device);
console.log("LinkedList=",ble.data.LinkedList);
}
}
}).catch((ex) => {
console.log("获取设备出现异常:", ex);
}).finally(() => {
hideLoading(these);
});
},
Link() {
// 调用绑定设备接口
let f = ble.data.LinkedList.find((v) => {
return v.deviceId = these.device.deviceId;
});
if (!f) {
these.Statu.bound = false;
these.Statu.boundRemark = "蓝牙连接不成功";
return;
}
if (!f.macAddress) {
these.Statu.bound = false;
these.Statu.boundRemark = "设备上报Mac地址异常";
return;
}
these.Statu.bound = null;
these.Statu.boundRemark = "";
showLoading(these, {
text: "连接中..."
})
let promise = request({
url: '/app/device/bind',
method: 'POST',
data: {
deviceImei: '',
deviceMac: these.device.macAddress,
communicationMode: '1', //0是4g,1是蓝牙
}
});
promise.then((res) => {
console.log("1111" + JSON.stringify(res));
if (res.code == 200) {
these.Statu.bound = true;
these.Statu.boundRemark = "设备绑定成功!";
uni.$emit("refreshDeviceList");
setTimeout(() => {
uni.switchTab({
url: "/pages/common/index/index"
});
}, 500);
} else {
these.Statu.bound = false;
these.Statu.boundRemark = res.msg;
}
}).catch((ex) => {
these.Statu.bound = false;
these.Statu.boundRemark = '出现了未知的异常,操作失败';
}).finally(() => {
hideLoading(this);
});
}
}
}
</script>
<style>
.content {
background-color: #1d1d1d;
color: #ffffffde;
box-sizing: border-box;
overflow: hidden;
width: 100%;
min-height: 100vh;
height: auto;
font-family: "PingFang SC";
}
</style>
.deviceDetail {
margin: 200rpx auto;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
}
.imgContent,
.titleIco {
width: 120rpx;
height: 120rpx;
}
.deviceId {
color: rgba(255, 255, 255, 0.87);
font-size: 32rpx;
line-height: 44rpx;
letter-spacing: 0.14rpx;
margin-top: 5rpx;
}
.btnLink {
position: fixed;
bottom: 30rpx;
left: 30rpx;
right: 30rpx;
width: calc(100% - 60rpx);
border-radius: 91px;
height: 90rpx;
background: rgba(187, 230, 0, 1);
color: rgba(35, 35, 35, 1);
font-size: 32rpx;
line-height: 90rpx;
letter-spacing: 12rpx;
text-align: center;
}
.bound,
.deviceName {
font-size: 32rpx;
font-weight: 400;
line-height: 44rpx;
letter-spacing: 0.14rpx;
margin-top: 5rpx;
}
.displayNone {
display: none !important;
}
.green {
color: rgba(187, 230, 0, 1);
}
.red {
color: rgba(245, 80, 80, 1);
}
</style>

View File

@ -81,13 +81,22 @@
</view>
</view>
</BottomSlideMenuPlus>
<global-loading ref="loading" />
</view>
</template>
<script>
import ble from '../../../api/6155/BlueHelper.js';
import request from '../../../utils/request.js';
import bleTool from '@/utils/BleHelper.js';
import request from '@/utils/request.js';
import {
showLoading,
hideLoading,
updateLoading
} from '@/utils/loading.js'
const pagePath="pages/common/addBLE/addEquip";
var ble = null;
var these = null;
export default {
data() {
return {
@ -127,72 +136,71 @@
},
onHide: function() {
ble.StopSearch();
ble.removeReceiveCallback(pagePath);
},
onBackPress: (e) => {
ble.StopSearch();
ble.disconnectDevice();
ble.removeDeviceFound(pagePath);
ble.removeReceiveCallback(pagePath);
},
onUnload(){
ble.StopSearch();
ble.removeDeviceFound(pagePath);
ble.removeReceiveCallback(pagePath);
},
onLoad() {
these = this;
ble = bleTool.getBleTool();
ble.addDeviceFound((arr) => {
arr = arr.devices;
for (var i = 0; i < arr.length; i++) {
onShow: function() {
// return;
var these = this;
uni.getStorage({
key: "linkedDevices",
success: (res) => {
this.PairEquip = JSON.parse(res.data);
},
fail: (ex) => {
this.PairEquip = [];
}
});
if (process.env.UNI_PLATFORM == 'mp-weixin' ||
process.env.UNI_PLATFORM == 'mp-alipay' ||
process.env.UNI_PLATFORM == 'app-plus' ||
process.env.UNI_PLATFORM == 'app'
) {
//打开蓝牙开始搜索设备
ble.OpenBlue(true, () => {
ble.StartSearch(function(arr) {
arr = arr.devices;
for (var i = 0; i < arr.length; i++) {
arr[i].linkStatu = false;
let f = these.EquipMents.find(function(v) {
return v.deviceId == arr[i].deviceId;
});
if (!f) {
these.EquipMents.push(arr[i]);
}
}
console.log("设备列表:" + JSON.stringify(these.EquipMents));
});
},
() => {
these.showOpenSetting();
arr[i].linkStatu = false;
if(!arr[i].name){
continue;
}
let f = these.EquipMents.find(function(v) {
return v.deviceId == arr[i].deviceId;
});
if (!f) {
these.EquipMents.push(arr[i]);
} else {
}
)
}
},pagePath);
} else {
console.log('当前环境:' + process.env.UNI_PLATFORM + '不支持蓝牙');
}
},
onShow: function() {
this.EquipMents=[];
this.PairEquip=[];
ble.StartSearch().catch((ex) => {
if (ex.code == 10001) {
these.showOpenSetting();
}
});
ble.addReceiveCallback((receivData) => {
console.log("收到数据了:", receivData);//数据格式:{bytes:[109,97],str:"",hexs:"FA 01"}
console.log("LinkedList=",ble.data.LinkedList);
let data=uni.getStorageSync(ble.StorageKey);
console.log("data=",data);
},pagePath);
},
methods: {
isItemLink: function(item, index) {
let src = '/static/images/BLEAdd/noLink.png';
if (this.PairEquip && this.PairEquip instanceof Array) {
if (this.PairEquip && this.PairEquip.length) {
if (this.PairEquip.length > 0) {
let f = this.PairEquip.find(function(v) {
return v.deviceId == item.deviceId;
@ -206,114 +214,56 @@
}
return src;
},
alert: function(title, content, callback) {
if (!title) {
title = '提示'
}
if (!content) {
content = title;
}
uni.showModal({
title: title,
content: content,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
if (callback) {
callback(res);
}
}
});
},
showOpenSetting: function() {
this.Status.BottomMenu.show = true;
},
gotoSetting: function() {
this.Status.BottomMenu.show = false;
ble.showBluetoothGuide(false);
ble.showBlueSetting(false);
},
Link: function(item, index) {
var these = this;
if (process.env.UNI_PLATFORM == 'mp-weixin' ||
process.env.UNI_PLATFORM == 'mp-alipay' ||
process.env.UNI_PLATFORM == 'app-plus' ||
process.env.UNI_PLATFORM == 'app'
) {
uni.showLoading({
title: "正在连接",
mask: true
});
setTimeout(() => {
ble.LinkBlue(item.deviceId, function() {
let c = these.PairEquip.find(function(v) {
return v.deviceId == item.deviceId;
});
if (!c) {
these.PairEquip.push(item);
uni.setStorage({
key: 'linkedDevices',
data: JSON.stringify(these.PairEquip),
success: () => {}
});
}
// 调用绑定设备接口
let promise = request({
url: '/app/device/bind',
method: 'POST',
data: {
deviceImei: '',
deviceMac: item.deviceId,
communicationMode: '1', //0是4g,1是蓝牙
}
});
promise.then((res) => {
console.log("1111" + JSON.stringify(res));
if (res.code == 0) {
uni.hideLoading()
uni.showToast({
title: res.data,
icon: 'success'
});
} else {
uni.showToast({
title: res.msg,
});
}
}).catch((ex) => {
uni.showToast({
title: '出现了未知的异常,操作失败',
});
});
}, (ex) => {
uni.hideLoading();
showLoading(this,{
text: "正在连接"
});
setTimeout(() => {
let serviceid=null;
if(item.advertisServiceUUIDs.length>0){
serviceid=item.advertisServiceUUIDs[0];
}
ble.LinkBlue(item.deviceId,serviceid).then((res) => {
let c = these.PairEquip.find(function(v) {
return v.deviceId == item.deviceId;
});
}, 0);
if (!c) {
these.PairEquip.push(item);
}
ble.removeReceiveCallback(pagePath);
uni.navigateTo({
url:"/pages/common/addBLE/LinkBle",
events:{
},
success(res) {
res.eventChannel.emit('LinkItem', item);
}
});
}).catch((ex) => {
console.log("ex=",ex)
uni.showModal({
content:"连接失败:"+ex.msg
});
}).finally(()=>{
hideLoading(this);
});
}, 0);
} else {
these.alert("提示", "当前平台不支持蓝牙");
}
}
}
}
@ -451,7 +401,7 @@
.mainContent .lblTitle {
color: #ffffffde;
font-family: PingFang SC;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 700;
text-align: left;
@ -516,7 +466,7 @@
.list .item .name {
color: #ffffffde;
font-family: PingFang SC;
font-family: "PingFang SC";
font-size: 26rpx;
font-weight: 400;
line-height: 50rpx;
@ -525,7 +475,7 @@
.list .item .id {
color: #ffffff99;
font-family: PingFang SC;
font-family: "PingFang SC";
font-size: 24rpx;
font-weight: 400;
line-height: 30rpx;
@ -547,7 +497,7 @@
.openBlue .txt {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
letter-spacing: 0.14rpx;
@ -572,7 +522,7 @@
width: 25%;
height: 60rpx;
text-align: center;
font-family: PingFang SC;
font-family: "PingFang SC";
font-size: 28rpx;
letter-spacing: 12rpx;
display: flex !important;
@ -584,10 +534,12 @@
justify-content: center;
}
.openBlue .cancel {
border: 1px solid rgba(255, 255, 255, 1);
color: rgba(255, 255, 255, 1);
}
.openBlue .ok {
background-color: #BBE600;
color: #232323;

View File

@ -60,7 +60,7 @@
data() {
return {
showView: false,
phone: '13800138002', //手机号码
phone: '17671332251', //手机号码
code: "123456", //验证码
agreed: false,
isCounting: false,
@ -145,6 +145,29 @@
return false
}
try {
console.log('44444');
if(uni.getStorageSync("token") && uni.getStorageSync("clientID")){//免登陆
let time=uni.getStorageSync("tokenTime");
if(!time){
time=0;
}
let currTime=new Date().getTime();
if(currTime<time){
uni.switchTab({
url: '/pages/common/index/index'
});
return;
}else{
//token过期了
uni.removeStorageSync("token")
uni.removeStorageSync("clientID")
uni.removeStorageSync("tokenTime")
}
}
uni.showLoading({
title: '登录中...'
})
@ -155,30 +178,37 @@
tenantId: '894078' //租户ID
})
if (res.code == 200) {
uni.hideLoading()
uni.setStorageSync('token', res.data.access_token) // 缓存token
uni.setStorageSync('clientID', res.data.client_id) // 缓存token
console.log(res, 'ressss');
uni.hideLoading();
uni.setStorageSync('token', res.data.access_token); // 缓存token
uni.setStorageSync('clientID', res.data.client_id); // 缓存token
uni.setStorageSync('tokenTime',new Date().getTime()+86400000);//过期时间
uni.showToast({
title: '登录成功',
icon: 'success'
})
uni.switchTab({
url: '/pages/common/index/index'
})
});
// uni.navigateTo({
// url:"/pages/BlueTooth/ModeSetting/index"
// });
} else {
uni.showToast({
title: res.msg || '服务器异常,请稍后重试',
title: res.msg,
icon: 'none'
})
}
} catch (error) {
console.log('捕获错误:', error);
uni.hideLoading()
uni.showToast({
title: error.msg || '登录失败',
title: error.msg,
icon: 'none'
});
uni.hideLoading()
}
},
// 跳转到协议页面
goToPage(type) {

View File

@ -5,13 +5,17 @@
<image src="/static/images/common/svg.png" class="svg"></image>
<view class="scanT">ID: {{ deviceId }}</view>
</view>
<!-- 连接中状态 -->
<view class="connecting-container" v-else>
<view class="device-info">
<view class="">
<image src="/static/images/common/svg.png" class="svg"></image>
</view>
<!-- <view>
<image src="/static/images/bip.6.png" class="bip"></image>
</view> -->
<text class="device-name">设备名{{deviceId}}</text>
<text class="device-model1">ID:{{deviceId}}</text>
</view>
@ -67,7 +71,6 @@
})
console.log(this.deviceId, 'deerer ere');
if (res.code == 200) {
this.isConnectNo = false
this.isSuccess = true
uni.hideLoading()