xlolic 2ヶ月前
コミット
01f76101a4
28個のファイルの変更2443行の追加29行の削除
  1. +0
    -2
      App.vue
  2. +108
    -0
      components/privacy/index.vue
  3. +1
    -1
      env/dev.js
  4. +6
    -2
      manifest.json
  5. +37
    -1
      pages.json
  6. +501
    -0
      pages/bluetooth/connect.vue
  7. +345
    -0
      pages/bluetooth/detail.vue
  8. +123
    -0
      pages/bluetooth/wdetail.vue
  9. +544
    -0
      pages/bluetooth/wifi.vue
  10. +1
    -1
      pages/center/RuleEditing/RuleEditing.vue
  11. +86
    -1
      pages/index/customer.vue
  12. +266
    -17
      pages/index/index.vue
  13. +15
    -3
      pages/index/personal.vue
  14. +54
    -1
      pages/mine/reception/addreception.vue
  15. バイナリ
      static/images/bluetooth-con.png
  16. バイナリ
      static/images/bluetooth-del.png
  17. バイナリ
      static/images/bluetooth-empty.png
  18. バイナリ
      static/images/bluetooth-ghh-ac.png
  19. バイナリ
      static/images/bluetooth-ghh.png
  20. バイナリ
      static/images/bluetooth-scan.png
  21. バイナリ
      static/images/bluetooth-search.png
  22. バイナリ
      static/images/bluetooth-sx.png
  23. バイナリ
      static/images/bluetooth-wifi.png
  24. バイナリ
      static/images/bluetooth.png
  25. バイナリ
      static/images/ly-ac.png
  26. バイナリ
      static/images/ly.png
  27. +11
    -0
      store/index.js
  28. +345
    -0
      utils/blue.js

+ 0
- 2
App.vue ファイルの表示

@@ -13,7 +13,6 @@
// 获取用户信息
uni.getSystemInfo({
success: function(e) {
console.log(e, 'phoneInfo')
// #ifdef MP-WEIXIN
Vue.prototype.StatusBar = e.statusBarHeight;
let custom = wx.getMenuButtonBoundingClientRect();
@@ -314,7 +313,6 @@
}
})


this.$u.get(config.service.notReadNum, {
id: uni.getStorageSync('weapp_session_userInfo_data').accountId,
projectId: uni.getStorageSync('buildingID').id


+ 108
- 0
components/privacy/index.vue ファイルの表示

@@ -0,0 +1,108 @@
<template>
<uni-popup ref="privacyPopup" type="center" :is-mask-click="true">
<view class="privacyPopup">
<view class="title">
<view>数智工牌</view>
</view>
<view class="content_pri">
<text>在你使用【数智工牌】服务之前,请仔细阅读</text>
<text style="color: #1793ee;" @click="goToPrivacy">《数智工牌小程序隐私保护指引》</text>。
<text>如你同意数智工牌小程序隐私保护指引,请点击“同意”开始使用【数智工牌】。</text>
</view>
<view class="pri_btn">
<button class="confuse_btn" @click="confusePrivacy">拒绝</button>
<button class="confirm_btn" id="agree-btn"
open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button>
</view>
</view>
</uni-popup>
</template>

<script>
export default {
data(){
return{
}
},
methods:{
init(resolve){
this.$refs.privacyPopup.open()
this.resolvePrivacyAuthorization = resolve
},
// 打开隐私协议
goToPrivacy(){
uni.openPrivacyContract({
success: () => {
console.log('打开成功');
},
fail: () => {
uni.showToast({
title:'打开失败,稍后重试',
icon: 'none'
})
}
})
},
// 拒绝
confusePrivacy(){
this.$refs.privacyPopup.close();
this.resolvePrivacyAuthorization({ event:'disagree' });
},
// 同意
handleAgreePrivacyAuthorization(){
this.resolvePrivacyAuthorization({ buttonId: 'agree-btn', event: 'agree' });
this.$refs.privacyPopup.close();
}
}
}
</script>

<style>
*{
box-sizing: border-box;
}
.privacyPopup{
width: 520rpx;
/* height: 500rpx; */
background-color: #fff;
border-radius: 20rpx;
padding: 20rpx 40rpx;
}
.title{
display: flex;
align-items: center;
justify-content: start;
margin: 20rpx 0;
font-size: 38rpx;
font-weight: 600;
}
.content_pri{
width: 480rpx;
margin: 0 auto;
font-size: 34rpx;
line-height: 1.5;
}
.pri_btn{
width: 100%;
height: 158rpx;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.pri_btn .confuse_btn,.pri_btn .confirm_btn{
width: 200rpx;
height: 90rpx;
border-radius: 20rpx;
font-size: 34rpx;
}
.pri_btn .confuse_btn{
background-color: #eee;
color: #52bf6b;
}
.pri_btn .confirm_btn{
background-color: #52bf6b;
color: #fff;
}
</style>

+ 1
- 1
env/dev.js ファイルの表示

@@ -1,5 +1,5 @@
const ENV_PATH = {
baseUrl: 'http://39.97.244.65:9999', // 微信的测试环境
baseUrl: 'https://test.quhouse.com', // 微信的测试环境39.97.244.65 http://120.92.19.130:9999
}

module.exports = ENV_PATH

+ 6
- 2
manifest.json ファイルの表示

@@ -1,6 +1,6 @@
{
"name" : "AI销讲助手",
"appid" : "__UNI__7A1611D",
"appid" : "__UNI__725D632",
"description" : "AI销讲助手",
"versionName" : "1.1.0",
"versionCode" : "100",
@@ -80,7 +80,11 @@
"minified" : true
},
"usingComponents" : true,
"permission" : {},
"permission" : {
"scope.bluetooth" : {
"desc" : "需要使用蓝牙功能,请允许访问您的蓝牙设备"
}
},
"requiredBackgroundModes" : [ "audio" ],
"lazyCodeLoading" : "requiredComponents",
"plugins" : {


+ 37
- 1
pages.json ファイルの表示

@@ -643,6 +643,42 @@
}
]
},
{
"root": "pages/bluetooth", //中心逻辑的模块都放到这里
"name": "bluetooth",
"pages": [{
"path" : "connect",
"style" :
{
"navigationBarTitleText" : "蓝牙连接",
"enablePullDownRefresh" : false
}
},
{
"path" : "detail",
"style" :
{
"navigationBarTitleText" : "蓝牙详情",
"enablePullDownRefresh" : false
}
},
{
"path" : "wifi",
"style" :
{
"navigationBarTitleText" : "wifi列表",
"enablePullDownRefresh" : false
}
},
{
"path" : "wdetail",
"style" :
{
"navigationBarTitleText" : "wifi资料",
"enablePullDownRefresh" : false
}
}]
}
],
@@ -700,4 +736,4 @@
"navigationBarTitleText": "AI销讲助手",
"navigationBarTextStyle": "black"
}
}
}

+ 501
- 0
pages/bluetooth/connect.vue ファイルの表示

@@ -0,0 +1,501 @@
<template>
<view class="bt">
<view class="bt-t1">工牌开机后,须开启手机蓝牙和位置定位搜索</view>
<view class="bt-c1">
<text>蓝牙</text>
<view @click="openBlue()" :class="['bt-sw',connectState?'bt-sw-ac':'']"></view>
</view>
<view class="bt-t2">
智能工牌开机后2分钟内会发送蓝牙信号,请先开机后并2分钟内搜索设备;如超时请重新开机搜索!或者请重新进入小程序并开启定位功能!
</view>
<!-- <view class="bt-t3">
输入或搜索需要查询的SN
</view>
<view class="bt-input1">
<view class="bt-input1-c">
<image src="/static/images/bluetooth-search.png" />
<input v-model="keyword" @confirm="getBluetoothDevices" placeholder="请输入设备SN" />
</view>
<image class="scan" @click="ermScan" src="/static/images/bluetooth-scan.png" />
</view> -->
<view class="bt-c2">
<view class="bt-c2-l">我的工牌</view>
<image @click="startBluetoothDevicesDiscovery" src="/static/images/bluetooth-sx.png"
:class="['bt-c2-r',isSearch?'bt-c2-r-ani':'']" />
</view>

<view v-for="(item,index) in blist" :key="index" @click="goDetail(item)" class="bt-c3">
<view class="bt-c3-l">{{item.name}}</view>
<image src="/static/images/jiantop.png" />
</view>

<view class="bt-c2">
<view class="bt-c2-l">已绑定的工牌</view>
</view>

<view v-for="(item,index) in savelist" :key="index" @click="goDetail(item)" @longpress="delOld(index)" class="bt-c3">
<view class="bt-c3-l">
{{item.name}}
<image mode="heightFix" v-if="item.isConnect && item.isConnect == 1" src="/static/images/bluetooth-con.png" />
</view>
<image src="/static/images/jiantop.png" />
</view>
<view v-if="savelist.length > 0" class="bt-c2" style="margin-top: 20rpx;">
<view class="bt-c2-l">长按删除</view>
</view>

</view>
</template>

<script>
import {
serviceId,
closeBlueAdapter,
readCharacteristicId,
writeCharacteristicId
} from "@/utils/blue.js";
import {
mapState,
} from 'vuex';

export default {
data() {
return {
privacyVisible: false,
open: false,
serviceId,
readCharacteristicId,
writeCharacteristicId,
blist: [],
keyword: "",
savelist: [],
isSearch: false
}
},
computed: {
...mapState(['connectDev', 'connectState']),
},
watch: {
connectDev(newVal) {
this.savelist = this.savelist.filter(v => {
v.isConnect = '0';
if (newVal && v.deviceId == newVal.deviceId) v.isConnect = '1';
if (v.name && v.deviceId) return v;
})
}
},
onShow() {
this.keyword = uni.getStorageSync("imeiCode");
if (this.connectState == true) {
this.getBluetoothDevices();
} else {
this.savelist = this.savelist.filter(v => {
v.isConnect = '0';
if (that.connectDev && v.deviceId == that.connectDev.deviceId) v.isConnect = '1';
if (v.name && v.deviceId) return v;
})
}
},
methods: {
//搜索
ermScan() {
var that = this
uni.scanCode({
success: (res) => {
that.keyword = res.result
that.getBluetoothDevices();
},
fail: (err) => {
console.error('扫码失败:' + err);
}
});
},
//打开蓝牙
openBlue() {
var that = this
if (!that.connectState) {
uni.showLoading({
title: "链接中...",
icon: "none"
})
uni.authorize({
scope: 'scope.bluetooth',
success: () => {
uni.openBluetoothAdapter({
success: (res) => {
uni.hideLoading();
that.$store.commit('setConnectState', true);
that.getBluetoothAdapterState();
},
fail: (res) => {
uni.hideLoading();
uni.showToast({
title: "蓝牙适配器打开失败",
icon: "none"
})
}
});
},
fail: () => {
uni.hideLoading();
uni.showModal({
title: '提示',
content: '需要使用蓝牙功能,请授权使用',
showCancel: false,
success: () => {
uni.openSetting();
}
})
}
})
} else {
that.blist = [];
that.savelist = [];
closeBlueAdapter();
}
},
//搜索蓝牙
getBluetoothAdapterState() {
var that = this;
that.blist = [];
uni.getBluetoothAdapterState({
success: function(res) {
if (!res.discovering) {
that.startBluetoothDevicesDiscovery();
}
if (!res.available) {
uni.showModal({
title: '提示',
content: '当前蓝牙适配器不可用',
confirmColor: '#00b6b5',
showCancel: false,
success(res) {}
})
}
},
fail: function(res) {
uni.showModal({
title: '提示',
content: '适配蓝牙失败',
confirmColor: '#00b6b5',
showCancel: false,
success(res) {}
})
}
});
},
//搜索蓝牙
startBluetoothDevicesDiscovery() {
var that = this;
that.isSearch = true
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: function(res) {
setTimeout(() => {
that.isSearch = false
that.lanya5()
}, 5000)
that.onBluetoothDeviceFound();
},
fail: function(res) {
that.isSearch = false
uni.showModal({
title: '提示',
content: '搜索蓝牙设备失败'
})
}
})
},
//获取所有已发现的设备
getBluetoothDevices() {
var that = this;
that.savelist = [];

let islist = uni.getStorageSync("connectDevList")?uni.getStorageSync("connectDevList"):[]
that.savelist = islist.filter(v => {
v.isConnect = '0';
if (that.connectDev && v.deviceId == that.connectDev.deviceId) v.isConnect = '1';
if (v.name && v.deviceId) return v;
})
uni.getBluetoothDevices({
success(res){
res.devices.filter(v => {
if (!that.blist.find(v2 => v2.deviceId == v.deviceId)) {
if (v.name.toLowerCase() == that.keyword.toLowerCase()) that.blist.push(v);
}
})
}
})
},
// 获取所有已发现的设备
onBluetoothDeviceFound() {
var that = this;
that.savelist = [];
let islist = uni.getStorageSync("connectDevList")?uni.getStorageSync("connectDevList"):[]
that.savelist = islist.filter(v => {
v.isConnect = '0';
if (that.connectDev && v.deviceId == that.connectDev.deviceId) v.isConnect = '1';
if (v.name && v.deviceId) return v;
})
uni.onBluetoothDeviceFound((res) => {
res.devices.filter(v => {
//判断blist中如果没有就添加
if (!that.blist.find(v2 => v2.deviceId == v.deviceId)) {
if (v.name.toLowerCase() == that.keyword.toLowerCase()) that.blist.push(v);
}
})
})
},

//停止搜索周边设备
lanya5() {
uni.getBluetoothAdapterState({
success: function(res) {
if (res.discovering) {
uni.stopBluetoothDevicesDiscovery({
success: function(res) {
console.log("蓝牙停止搜索")
}
})
}
}
})
},
//关闭蓝牙
closeBluetoothAdapter() {
var that = this
uni.closeBluetoothAdapter({
complete() {}
})
},
delOld(index){
var that = this;
uni.showModal({
title: '提示',
content: '确定要删除该工牌吗?',
success(res) {
if (res.confirm) {
let item = that.savelist[index];
if (item.isConnect == 1) {
uni.setStorageSync("lyDetail", item)
uni.showToast({
title: '该工牌蓝牙已连接,请先进入"蓝牙详情"页面断开蓝牙',
duration: 3000,
icon: "none",
})
setTimeout(() => {
uni.navigateTo({
url: '/pages/bluetooth/detail'
})
}, 3000)
return
}
that.savelist.splice(index,1);
uni.setStorageSync("connectDevList",that.savelist);
}
}
})
},
//去详情页
goDetail(item) {
uni.setStorageSync("lyDetail", item)
uni.navigateTo({
url: "/pages/bluetooth/detail"
})
}
}
}
</script>

<style scoped lang="scss">
.bt {
background-color: #F1F2F4;
min-height: 100vh;
width: 100%;
box-sizing: border-box;
padding: 40rpx 28rpx;

.bt-t1 {
font-weight: 400;
font-size: 26rpx;
color: #666666;
margin-bottom: 20rpx;
}

.bt-c1 {
height: 88rpx;
background: #FFFFFF;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #333333;
box-sizing: border-box;
padding: 0 28rpx;
}

.bt-sw {
width: 60rpx;
height: 36rpx;
background: #D8D8D8;
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(9, 23, 44, 0.3);
border-radius: 18rpx;
display: flex;
align-items: center;
transition: all 0.3s linear;
position: relative;
}

.bt-sw::after {
content: " ";
position: absolute;
left: 8rpx;
width: 20rpx;
height: 20rpx;
background: #FFFFFF;
border-radius: 16rpx;
transition: all 0.3s linear;
}

.bt-sw-ac {
background: #2671E2;
}

.bt-sw-ac::after {
left: 32rpx;
}

.bt-t2 {
font-size: 30rpx;
color: #999999;
margin-top: 20rpx;
line-height: 1.6;
}

.bt-t3 {
margin-top: 60rpx;
font-size: 26rpx;
color: #666666;
}

.bt-input1 {
width: 100%;
background: #FFFFFF;
border-radius: 12rpx;
box-sizing: border-box;
padding: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;

&-c {
width: 100%;
height: 66rpx;
background: #F1F2F4;
border-radius: 8rpx;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 0 20rpx;

image {
width: 36rpx;
height: 36rpx;
margin-right: 10rpx;
flex-shrink: 0;
}

input {
width: 100%;
font-weight: 400;
font-size: 26rpx;
color: #333;
}
}

.scan {
width: 30rpx;
height: 30rpx;
margin-left: 28rpx;
flex-shrink: 0;
}
}

.bt-c2 {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 60rpx;

.bt-c2-l {
font-weight: 400;
font-size: 26rpx;
color: #666666;
transform: translateY(-2rpx);
}

.bt-c2-r {
width: 32rpx;
height: 32rpx;
}

.bt-c2-r-ani {
animation: spin 2.5s linear infinite;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}

100% {
transform: rotate(360deg);
}
}
}

.bt-c3 {
box-sizing: border-box;
padding: 32rpx;
background: #FFFFFF;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;

.bt-c3-l {
display: flex;
align-items: center;
font-weight: 400;
font-size: 28rpx;
color: #333333;

image {
height: 36rpx;
margin-left: 12rpx;
flex-shrink: 0;
}
}

image {
width: 12rpx;
height: 28rpx;
margin-left: 20rpx;
flex-shrink: 0;
}
}

}
</style>

+ 345
- 0
pages/bluetooth/detail.vue ファイルの表示

@@ -0,0 +1,345 @@
<template>
<view class="detail">
<view class="de-t1">{{info.name}}</view>
<view class="de-label">蓝牙连接</view>
<view class="de-input">
<view class="de-input-t1">蓝牙</view>
<view @click.stop="connectTO()" class="de-input-t2">{{connectDev.deviceId != info.deviceId?'未连接':'已连接'}}</view>
<image src="/static/images/jiantop.png" />
</view>
<template v-if="connectDev.deviceId != info.deviceId">
<view class="empty">
<image mode="widthFix" src="/static/images/bluetooth-empty.png" />
<view class="empty-l">设备状态与配置请在连接蓝牙后查询</view>
</view>
</template>
<template v-else>
<!-- wifi列表 -->
<view class="de-label">设备配置</view>
<view class="de-lic">
<view class="de-lic-li line">
<view class="de-lic-1">WIFI</view>
</view>
<view @click="goWifi()" class="de-lic-li">
<view class="de-lic-1">设置WIFI状态</view>
<view class="de-lic-2">
{{(wifiDetail && wifiDetail.connect == 1)?wifiDetail.ssid+"已连接":"未连接"}}
</view>
<image @click.stop="goWdetial()" style="width: 36rpx;height: 36rpx;margin-left: 12rpx;"
:src="'/static/images/bluetooth-ghh'+ ((wifiDetail && wifiDetail.connect == 1)?'-ac':'') +'.png'" />
</view>
</view>
<!-- 设备状态 -->
<view @click="getDevInfo" class="de-label">
设备状态 <text>刷新</text>
</view>
<view class="de-lic" style="margin-bottom: 60rpx;">
<view class="de-lic-li line">
<view class="de-lic-1">设备SN</view>
<view class="de-lic-2">{{detail.sn?detail.sn:'--'}}</view>
</view>
<view @click="onOffRec()" class="de-lic-li line">
<view class="de-lic-1">录音</view>
<view class="de-lic-2">{{detail.rec == 1?"已开启":"未开启"}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">电量</view>
<view class="de-lic-2">{{detail.rsoc?detail.rsoc:0}}%</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">存储空间</view>
<view class="de-lic-2">{{detail.df?detail.df:0}}MB/{{detail.total_df?detail.total_df:0}}MB</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">信号强度</view>
<view class="de-lic-2">{{(wifiDetail && wifiDetail.connect == 1)?wifiDetail.rssi+"dbm":"未连接"}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">固件版本</view>
<view class="de-lic-2">{{detail.v?detail.v:'0.0.0'}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">USB接入</view>
<view class="de-lic-2">{{detail.usb == 1?"插入":"未插入"}}</view>
</view>
<view class="de-lic-li">
<view class="de-lic-1">时钟</view>
<view class="de-lic-2">{{detail.time?detail.time:"--:--:--"}}</view>
</view>
</view>
</template>
</view>
</template>

<script>
import { connectBlue,sendData,closeBlue,setNotification,ab2hex,cnum } from "@/utils/blue.js";
import { mapState, mapMutations } from 'vuex';
export default {
data() {
return {
info : "",
wifiList : [],
detail: "",
wifiDetail: "",
type : 0,
}
},
computed: {
...mapState(['connectDev','connectState']),
},
onShow() {
//设定异步通知
this.info = uni.getStorageSync("lyDetail")
this.notiInit();
},
onLoad() {
},
methods: {
//连接设备
connectTO() {
var that = this;
if (this.connectDev.deviceId != this.info.deviceId) {
uni.showModal({
title: '链接蓝牙',
content: '确定要链接此蓝牙吗?',
cancelText: '取消',
confirmText: '确定',
success(res) {
//设置设置通知
if (res.confirm) {
connectBlue(that.info).then(() => {
setTimeout(() => {
that.notiInit()
},1000)
});
}
}
})
} else {
uni.showModal({
title: '断开蓝牙',
content: '确定要断开蓝牙连接吗?',
cancelText: '取消',
confirmText: '确定',
success(res) {
if (res.confirm) {
uni.setStorageSync("connectNum",4);
closeBlue().then(() => {
that.getDevInfo();
});
}
}
})
}
},
//开启录音/关闭录音
onOffRec() {
var that = this
uni.showModal({
title: '提示',
content: this.detail.rec == 1?'确定要关闭录音吗?':'确定要开启录音吗?',
cancelText: '取消',
confirmText: '确定',
success(res) {
if (res.confirm) {
uni.showLoading({
title:"操作中...",
icon: "none"
})
if (that.detail.rec == 1) {
sendData([0xA0,0x59,0x00])
} else {
sendData([0xA0,0x5A,0x00])
}
}
}
})
},
//获取设备/wifi信息
getDevInfo() {
uni.showLoading({
title:"获取中...",
icon: "none"
})
sendData([0xA0,0x80,0x00]);
},
notiInit() {
var that = this;
if (this.connectDev && this.connectDev.deviceId == this.info.deviceId) {
setNotification().then(() => {
that.getDevInfo();
uni.onBLECharacteristicValueChange((res) => {
let data = ab2hex(res.value);
if (data.pre[1] == "80") {
that.detail = JSON.parse(data.value)
sendData([0xA0,0x81,0x00]);
}
if (data.pre[1] == "81") {
that.wifiDetail = JSON.parse(data.value)
}
if (data.pre[1] == "5a" || data.pre[1] == "59") {
sendData([0xA0,0x80,0x00]);
}
try{
uni.hideLoading();
}catch(e){
console.log(e.message)
}
console.log('特性值改变:',data); // 打印接收到的数据
});
})
}
},
//详情
goWdetial() {
if (this.wifiDetail && this.wifiDetail.connect == 1) {
uni.setStorageSync("wifiDetail",this.wifiDetail);
uni.navigateTo({
url:"/pages/bluetooth/wdetail"
})
}
},
goWifi(){
uni.navigateTo({
url:"/pages/bluetooth/wifi"
})
},
dkBlue() {
closeBlue();
}
}
}
</script>

<style scoped lang="scss">
.detail {
background-color: #F1F2F4;
min-height: 100vh;
width: 100%;
box-sizing: border-box;
padding: 40rpx 28rpx 0;
.de-t1 {
background: #FFFFFF;
border-radius: 12rpx;
padding: 28rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #333333;
box-sizing: border-box;
}
.de-input {
box-sizing: border-box;
padding: 28rpx;
background: #FFFFFF;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;
.de-input-t1 {
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.de-input-t2 {
font-weight: 400;
font-size: 28rpx;
color: #666666;
margin-left: auto;
}
image {
width: 12rpx;
height: 28rpx;
margin-left: 16rpx;
}
}
.de-label {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 40rpx;
font-weight: 400;
font-size: 26rpx;
color: #666666;
text {
font-weight: 400;
font-size: 28rpx;
color: #2671E2;
margin-left: auto;
transform: translateY(2rpx);
}
}
.de-lic {
box-sizing: border-box;
padding: 0 28rpx;
background: #FFFFFF;
border-radius: 12rpx;
margin-top: 20rpx;
.de-lic-li {
height: 84rpx;
display: flex;
align-items: center;
justify-content: space-between;
.de-lic-1 {
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.de-lic-2 {
font-weight: 400;
font-size: 26rpx;
color: #666;
margin-left: auto;
}
image {
width: 28rpx;
height: 28rpx;
margin-left: 8rpx;
}
}
.line {
border-bottom: 1rpx dashed #f5f5f5;
}
}
.empty {
margin-top: 16rpx;
height: 275rpx;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #fff;
border-radius: 12rpx;
image {
width: 180rpx;
}
.empty-l {
font-weight: 400;
font-size: 26rpx;
color: #999999;
margin-top: 16rpx;
}
}
}
</style>

+ 123
- 0
pages/bluetooth/wdetail.vue ファイルの表示

@@ -0,0 +1,123 @@
<template>
<view class="detail">
<view class="de-t1">{{wifiDetail.ssid?wifiDetail.ssid:"未知"}}</view>
<!-- 设备状态 -->
<view class="de-label">
wifi基本信息
</view>
<view class="de-lic" style="margin-bottom: 60rpx;">
<view class="de-lic-li line">
<view class="de-lic-1">网络名称</view>
<view class="de-lic-2">{{wifiDetail.ssid?wifiDetail.ssid:"未知"}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">信号强度</view>
<view class="de-lic-2">{{wifiDetail.rssi+"dbm"}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">互联网访问</view>
<view class="de-lic-2">{{wifiDetail.connect==1?'是':'否'}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">ip地址</view>
<view class="de-lic-2">{{wifiDetail.ip}}</view>
</view>
<view class="de-lic-li line">
<view class="de-lic-1">本机MAC</view>
<view class="de-lic-2">{{wifiDetail.mac}}</view>
</view>
</view>
</view>
</template>

<script>
export default {
data() {
return {
wifiDetail : "",//{"on":1,"ssid":"","connect":0,"rssi":-128,"ip":"","mac":"08f80d201958"}
}
},
onLoad() {
this.wifiDetail = uni.getStorageSync("wifiDetail")
},
methods: {
}
}
</script>

<style scoped lang="scss">
.detail {
background-color: #F1F2F4;
min-height: 100vh;
width: 100%;
box-sizing: border-box;
padding: 40rpx 28rpx 0;
.de-t1 {
background: #FFFFFF;
border-radius: 12rpx;
padding: 24rpx 28rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #333333;
box-sizing: border-box;
}
.de-label {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 40rpx;
font-weight: 400;
font-size: 24rpx;
color: #666666;
text {
font-weight: 400;
font-size: 28rpx;
color: #2671E2;
margin-left: auto;
transform: translateY(2rpx);
}
}
.de-lic {
box-sizing: border-box;
padding: 0 28rpx;
background: #FFFFFF;
border-radius: 12rpx;
margin-top: 20rpx;
.de-lic-li {
height: 84rpx;
display: flex;
align-items: center;
justify-content: space-between;
.de-lic-1 {
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.de-lic-2 {
font-weight: 400;
font-size: 26rpx;
color: #666;
margin-left: auto;
}
image {
width: 28rpx;
height: 28rpx;
margin-left: 8rpx;
}
}
.line {
border-bottom: 1rpx dashed #f5f5f5;
}
}
}
</style>

+ 544
- 0
pages/bluetooth/wifi.vue ファイルの表示

@@ -0,0 +1,544 @@
<template>
<view class="wifi">
<!-- 可用的WIFI -->
<view @click="refreshList" class="wi-label">
附近可用的WIFI <text>刷新</text>
</view>
<scroll-view scroll-y style="height: 500rpx;" class="wi-lic">
<view v-for="(item,index) in wifiList" :key="index" @click="tanShow(item)" class="wi-lic-li line">
<image class="wi-wifi" src="/static/images/bluetooth-wifi.png" />
<view class="wi-lic-1">{{item.ssid}}</view>
<image class="wi-ri" src="/static/images/jiantop.png" />
</view>
</scroll-view>
<!-- 可用的WIFI -->
<view style="margin-top: 40rpx;" class="wi-label">
手动设定WIFI
</view>
<view class="wi-lic" @click="tanShow({ssid : '', key : ''})" style="margin-bottom: 60rpx;">
<view class="wi-lic-li">
<view class="wi-lic-1">自定义</view>
<image class="wi-ri" src="/static/images/jiantop.png" />
</view>
</view>
<view style="margin-top: 40rpx;" class="wi-label">
主wifi配置
</view>
<view class="wi-lic" @click="tanShow({ssid : setInfo.wifi.ssid,key : setInfo.wifi.key})">
<view class="wi-lic-li line">
<view class="wi-lic-1">wifi名称:{{setInfo.wifi.ssid}}</view>
</view>
<view class="wi-lic-li">
<view class="wi-lic-1">wifi密码:{{setInfo.wifi.key}}</view>
</view>
</view>
<view style="margin-top: 40rpx;" class="wi-label">
副wifi配置
</view>
<view class="wi-lic" style="margin-bottom: 80rpx;">
<view v-for="(item,index) in setInfo.wifi.aps" @click="tanShow(item)" class="wi-lic-li line">
<view class="wi-lic-1">wifi名称:{{item.ssid}}</view>
<image class="wi-ri" @click.stop="apsDel(index)" mode="widthFix" style="width: 36rpx;" src="/static/images/bluetooth-del.png" />
</view>
</view>
<uni-popup ref="tan">
<view class="tan">
<view class="tan-t1">配置WIFI</view>
<view class="tan-c1">
<view class="tan-inp">
<view class="tan-inp-t1"><text>*</text>WIFI名称</view>
<input placeholder="请输入wifi名称" v-model="form.ssid" />
</view>
<view class="tan-inp">
<view class="tan-inp-t1">WIFI密码</view>
<input placeholder="请输入wifi密码" v-model="form.key" />
</view>
<view class="tan-btn">
<view @click="tanHide()" class="tan-w">取消</view>
<view @click="tanSub()" class="tan-b">确定</view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>

<script>
import { connectBlue,sendData,setNotification,ab2hex,strToHex,closeBlue,changeIsModalShown } from "@/utils/blue.js";
import { mapState, mapMutations } from 'vuex';
export default {
data() {
return {
type : 1,
setInfo : "",
setNum : 0,
setZl : [] ,
info : "",
form : {
ssid : '',
key : ''
},
strJson : "",
initWifiXl : [["0xA0","0x82","0x00"],["0xA0","0x87","0x00"]], //指令合集
wifiList : "",
isConnectTimer : ""
}
},
computed: {
...mapState(['connectDev','connectState']),
},
onShow() {
var that = this
this.info = uni.getStorageSync("lyDetail")
if (that.connectDev) {
that.init();
that.notifiInit();
} else {
uni.showModal({
title: '提示',
content: '蓝牙连接失败',
cancelText: '取消',
confirmText: '重新连接',
success(res) {
if (res.confirm) that.connectTO();
}
})
}
},
onHide() {
if (this.isConnectTimer) clearInterval(this.isConnectTimer);
},
onUnload() {
if (this.isConnectTimer) clearInterval(this.isConnectTimer);
},
methods: {
init() {
uni.showLoading({
title:"获取中...",
icon: "none"
})
sendData(this.initWifiXl[0])
},
//刷新wifi
refreshList() {
uni.showLoading({
title:"获取中...",
icon: "none"
})
this.wifiList = [];
sendData(this.initWifiXl[1])
},
tanSub() {
if (!this.connectState || !this.connectDev) {
uni.showToast({
title: "请先连接设备",
icon: "none"
})
return ;
}

uni.showLoading({
title:"更新中...",
icon: "none"
})
var that = this
this.tanHide();
//判断主wifi是否存在如果是主wifi进行更新
if (!this.setInfo.wifi.ssid || this.setInfo.wifi.ssid == this.form.ssid) {
this.setInfo.wifi.ssid = this.form.ssid
this.setInfo.wifi.key = this.form.key
} else {
//判断副wifi
let isHav = false;
this.setInfo.wifi.aps = this.setInfo.wifi.aps.filter(v => {
if (v.ssid == this.form.ssid) {
v.ssid = this.form.ssid
v.key = this.form.key
isHav = true
}
return v;
})
if (!isHav) {
if (this.setInfo.wifi.aps.length > 3) {
uni.hideLoading();
uni.showToast({
title: "副wifi最多添加4个",
icon: "none"
})
return ;
}
this.setInfo.wifi.aps.push(this.form);
}
}
//分割
this.syncSet();
},
tanShow(item) {
this.form = {...item};

try {
if (this.setInfo.wifi.ssid == item.ssid) {
this.form.ssid = item.ssid
this.form.key = this.setInfo.wifi.key
}

this.setInfo.wifi.aps.filter(v => {
if (v.ssid == item.ssid) {
this.form.ssid = item.ssid
this.form.key = v.key
}
})

this.$refs.tan.open();
} catch (e) {
uni.showModal({
title: '提示',
content: '数据解析错误'+JSON.stringify(this.setInfo),
showCancel: false,
})
}
},
tanHide() {
this.$refs.tan.close();
},
//副wifi删除
apsDel(index) {
var that = this;
uni.showModal({
title: '提示',
content: '确定删除此wifi吗?',
cancelText: '取消',
confirmText: '确定',
success(res) {
if (res.confirm) {
uni.showLoading({
title:"更新中...",
icon: "none"
})
that.setInfo.wifi.aps.splice(index,1)
that.syncSet();
};
}
})
},
//同步数据
syncSet() {
var that = this
let strArray = strToHex(JSON.stringify(this.setInfo));
let setZl = Array.from(
{ length: Math.ceil(strArray.length / 100) },
(_, index) => strArray.slice(index * 100, (index + 1) * 100)
);
uni.showLoading({
title:"更新中...",
mask: true,
icon: "none"
})

this.lxSendData(setZl,0);
},
//循环发送
lxSendData(setZl,i) {
var that = this
let v = setZl[i]
const hexNumber = (v.length + 1).toString(16).toUpperCase();
let end = "0x00";
if (i + 1 == setZl.length) end = "0x01";
sendData([...["0xA0","0x83","0x"+hexNumber,end],...v]).then(() => {
if (i + 1 < setZl.length) {
that.lxSendData(setZl, i + 1);
}
})
},
//连接设备
connectTO() {
var that = this;
connectBlue(this.info).then(() => {
//设置设置通知
setTimeout(() => {
setNotification().then(() => {
that.init();
that.notifiInit();
})
},1000)
});
},
notifiInit() {
var that = this
uni.onBLECharacteristicValueChange((res) => {
let data = ab2hex(res.value,3);
//基本设置信息
if (data.pre[1] == "82") {
that.strJson += data.value
if (data.pre[3] == "01") {
uni.hideLoading();
that.setInfo = JSON.parse(that.strJson)
that.strJson = "";
//发送第二条数据
sendData(that.initWifiXl[1])
uni.showLoading({
title:"扫描wifi中...",
icon: "none"
})
}
}
//wifi扫描信息
if (data.pre[1] == "87") {
if (data.pre[3] == "00") {
that.strJson += data.value
}
if (data.pre[3] == "01") {
uni.hideLoading();
that.strJson += data.value
console.log("当前返回所有wifi列表",that.strJson);
let rdd = JSON.parse(that.strJson);
that.wifiList = rdd.Results;
that.strJson = "";
}
}
//命令重启
if (data.pre[1] == "88") {
if (data.pre[3] == "01") {
uni.showModal({
title: '提示',
content: '重启失败,请手动重启设备并前往蓝牙页面重新连接',
showCancel:false,
confirmText: '确定',
success(res) {
if (res.confirm) {
uni.redirectTo({
url: "/pages/bluetooth/connect"
})
}
}
})
}

//禁止弹窗
changeIsModalShown();
//循环判断是否链接成功
uni.showLoading({
title:"正在连接设备",
mask: true,
icon: "none"
})
if (that.isConnectTimer) clearInterval(that.isConnectTimer);
let num = 0
closeBlue().then(() => {
that.connectTO();
that.isConnectTimer = setInterval(() => {
console.log("循环判断是否链接成功",that.connectDev,1222);
if (that.connectDev) {
clearInterval(that.isConnectTimer);
} else {
num++;
if (num <= 5) {
uni.hideLoading();
uni.showLoading({
title:"正在连接设备",
mask: true,
icon: "none"
})
} else {
uni.showModal({
title: '提示',
content: '蓝牙连接失败,前往手动连接',
showCancel: false,
confirmText: '前往',
success(res) {
uni.redirectTo({
url: "/pages/bluetooth/detail"
})
}
})
clearInterval(that.isConnectTimer);
}
}
},2000)
})
}
//配置修改
if (data.pre[1] == "83") {
if (data.pre[3] == "00") {
uni.hideLoading();
uni.showLoading({
title:"更新成功,工牌重启中",
mask: true,
icon: "none"
})
sendData([0xA0,0x88,0x00])
}
}
console.log('特性值改变:',data); // 打印接收到的数据
});
}
}
}
</script>

<style scoped lang="scss">
.wifi {
background-color: #F1F2F4;
min-height: 100vh;
width: 100%;
box-sizing: border-box;
padding: 40rpx 28rpx 0;
.wi-label {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 400;
font-size: 26rpx;
color: #666666;
text {
font-weight: 400;
font-size: 28rpx;
color: #2671E2;
margin-left: auto;
}
}
.wi-lic {
box-sizing: border-box;
padding: 0 28rpx;
background: #FFFFFF;
border-radius: 12rpx;
margin-top: 20rpx;
.wi-lic-li {
height: 84rpx;
display: flex;
align-items: center;
justify-content: space-between;
.wi-lic-1 {
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
image {
width: 28rpx;
height: 28rpx;
}
.wi-wifi {
margin-right: 14rpx;
}
.wi-ri {
margin-left: auto;
width: 14rpx;
}
}
.line {
border-bottom: 1rpx dashed #f5f5f5;
}
}
}

.tan {
width: 86vw;
background: #FFFFFF;
border-radius: 24rpx;
}

.tan-t1 {
font-weight: 500;
font-size: 32rpx;
color: #333333;
height: 116rpx;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1rpx dashed #f5f5f5;
}

.tan-c1 {
box-sizing: border-box;
padding: 48rpx 28rpx;
.tan-inp {
display: flex;
align-items: center;
margin-bottom: 45rpx;
.tan-inp-t1 {
flex-shrink: 0;
width: 136rpx;
font-weight: 400;
font-size: 30rpx;
color: #333333;
text-align: right;
margin-right: 48rpx;
text {
color: #C83429;
}
}
input {
width: 100%;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
}
}

.tan-btn {
display: flex;
justify-content: center;
margin-top: 70rpx;
.tan-w {
width: 191rpx;
height: 72rpx;
background: #FFFFFF;
border-radius: 38rpx;
border: 1rpx solid #333333;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
color: #333333;
margin-right: 24rpx;
}
.tan-b {
width: 191rpx;
height: 72rpx;
background: #2671E2;
border-radius: 38rpx;
font-weight: 400;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
color: #FFFFFF;
margin-left: 24rpx;
}
}

</style>

+ 1
- 1
pages/center/RuleEditing/RuleEditing.vue ファイルの表示

@@ -173,7 +173,7 @@
})
params['index' + (index + 1)] = arr.join((',')) || ''
})
console.log(params)
// this.stayPendingProcessingArr
this.$u.post('/customer/bisave', params).then(res => {
console.log(res)


+ 86
- 1
pages/index/customer.vue ファイルの表示

@@ -10,7 +10,7 @@
<view style="text-align: center;width: 100%;margin-top: 20rpx;color: #999999;">暂无数据</view>
</view>
</view>
<view class="customer" v-if="waitCustomList.length!=0" v-for="(item,index) in waitCustomList" :key='index'
@click="tapThevisiting(item)">
<view class="title">
@@ -94,10 +94,14 @@
</image>
<image class="add2" @click="reshCustom()" src="https://static.quhouse.com/zhikong_xcx_img/refresh.png" mode="">
</image>
<image class="add3" v-if="blueDetail.rec == 1 && equipmentType == 3" @click="closeRec()" src="/static/images/ly-ac.png" mode=""></image>
</view>
</template>

<script>
import { sendData, setNotification,ab2hex } from "@/utils/blue.js";
import { mapState, mapMutations } from 'vuex';
var config = require("../../config");
export default {
data() {
@@ -110,9 +114,13 @@
waitCustomList: [],
dataCode: '',
addAccount: '',
//蓝牙状态
blueDetail: '',
equipmentType: uni.getStorageSync('equipmentType')
};
},
computed: {
...mapState(['connectDev','connectState']),
timestamp() {
return (e) => {
if (!e) return
@@ -133,6 +141,7 @@
this.dataCode = dataCode;
this.init()
this.updateInit()
},

onPullDownRefresh() {
@@ -153,6 +162,16 @@
if (!res) {
this.init()
}
//停止录音
if (this.connectDev && this.connectState) {
sendData([0xA0,0x59,0x00]).catch(e => {
uni.showToast({
title: '关闭录音失败,请手动点击关闭录音',
icon: 'none'
});
})
}
this.getTabBarBadge()
}).catch(e => {
console.log(e)
@@ -166,6 +185,24 @@
}
})
},
closeRec() {
uni.showModal({
content: "确认关闭录音?",
cancelColor: "#999999",
success: res => {
if (res.confirm) {
sendData([0xA0,0x59,0x00]).then(() => {
this.init()
}).catch(e => {
uni.showToast({
title: '关闭录音失败,请前往个人中心蓝牙设置关闭录音',
icon: 'none'
});
})
}
}
})
},
// 未读消息数量
updateInit() {
@@ -252,6 +289,13 @@
this.$u.post("/customer/reception", parames).then(data => {
this.waitCustomList = data;
});
//蓝牙获取信息
this.notiInit();
setTimeout(() => {
if (this.connectDev)sendData([0xA0,0x80,0x00]);
},1000)
},
//延时接待
addTime(item) {
@@ -274,6 +318,22 @@
},
//结束接待
changeEnd(id) {
if (uni.getStorageSync('equipmentType') == 3 && (!this.connectDev || !this.connectState)) {
uni.showModal({
title: "提示",
content: "请先链接蓝牙,再执行结束接待的操作,是否前往链接?",
confirmText: "前往",
success(res) {
if (res.confirm) {
uni.navigateTo({
url: "/pages/bluetooth/connect"
})
}
}
})
return;
}
uni.showModal({
content: "确定更改当前客户接待状态为结束?",
cancelColor: "#999999",
@@ -285,6 +345,10 @@
id: id,
houseId: this.buildingID
}).then(res => {
//停止录音
if (this.connectDev && this.connectState && uni.getStorageSync('equipmentType') == 3) {
sendData([...[0xA0,0x59,0x00]])
}
uni.showToast({
icon: "none",
title: "操作成功"
@@ -317,6 +381,19 @@
url: url
})
},
notiInit() {
var that = this;
if (this.connectDev) {
setNotification().then(() => {
uni.onBLECharacteristicValueChange((res) => {
let data = ab2hex(res.value);
if (data.pre[1] == "80") {
that.blueDetail = JSON.parse(data.value)
}
});
})
}
},

},

@@ -515,6 +592,14 @@
bottom: 150rpx;
right: 44rpx;
}
.add3 {
width: 90rpx;
height: 90rpx;
position: fixed;
bottom: 390rpx;
right: 44rpx;
}

.content-sec {
padding: 28rpx 30rpx 32rpx;


+ 266
- 17
pages/index/index.vue ファイルの表示

@@ -27,7 +27,8 @@
</view>
<view class="Workcardtext">电量:{{percentage}}%</view>
</view>
<view class="Workcard-box">

<view v-if="equipmentType != 3" class="Workcard-box">
<view class="Workcardimg">
<image v-if="signalDevice==''" class="Workcardimg2" src="../../static/images/signal0.png"
mode=""></image>
@@ -44,6 +45,17 @@
</view>
<view class="Workcardtext">信号:{{signalDevicetext}}</view>
</view>

<view v-else class="Workcard-box">
<view class="Workcardimg">
<image v-if="bsignalDevice<90 && bsignalDevice>0" class="Workcardimg2"
src="../../static/images/signal5.png" mode=""></image>
<image v-else class="Workcardimg2" src="../../static/images/signal0.png"
mode=""></image>
</view>
<view class="Workcardtext">信号:{{bsignalDevice<90 && bsignalDevice>0?'正常':'无'}}</view>
</view>

<view class="Workcard-box">
<view class="Workcardimg">
<image v-if="audioStatus=='true'" class="Workcardimg3"
@@ -512,13 +524,32 @@
@click="tabtimetap(7,'自定义')">自定义</view>
</u-popup>

<!-- 弹窗显示蓝牙列表,链接按钮 -->
<u-popup v-model="bluetoothShow" mode="bottom">
<view class="bluetoothBox">
<view class="bluetoothTitle">
<view class="bluetoothTitleText">蓝牙列表</view>
</view>
<view class="bluetoothList">
<view class="bluetoothItem" v-for="item in blist" :key="item.deviceId">
{{item.name}}
<view @click="connectDevice(item)" class="bluetoothBtn">链接</view>
</view>
</view>
</view>
</u-popup>

<!-- 加载组件 -->
<u-loadings v-model="LOADING"></u-loadings>
</view>
</template>

<script>
import { sendData, setNotification,ab2hex,connectBlue } from "@/utils/blue.js";
import { mapState, mapMutations } from 'vuex';

var config = require("../../config");

export default {
data() {
return {
@@ -542,6 +573,7 @@
percentage: '', //设备电量
Whetheroffline: false, //是否离线
signalDevice: 0, //信号
bsignalDevice: 0,
signalDevicetext: "",
imeiCode: '', //设备号
openFlag: '', //接待是否
@@ -590,12 +622,18 @@
visitRecord1: null,
permissions: {}, // 权限菜单
paraphraseObj: {}, // 转写消费

blist: [],
bluetoothShow: false,
equipmentType: 0,

//蓝牙状态
wifiDetail: '' //wifi信号
};
},

components: {},

computed: {
...mapState(['connectDev','connectState']),
// 团队管理
teamManagementShow() {
let permissions = this.permissions
@@ -616,6 +654,14 @@
},
},

watch: {
connectDev(newVal) {
if (newVal) {
this.notiInit();
}
}
},

onLoad() {
console.log(this.$domain, 'this.$domain')
if (this.$domain == 'zh.aihxz.com') {
@@ -623,13 +669,12 @@
title: '云筑数智助手',
})
}
this.equipmentType = uni.getStorageSync('equipmentType') || 0;
this.LOADING = true
this.sendLog({
houseId: uni.getStorageSync(
'buildingID').id,
houseName: uni.getStorageSync(
'buildingID').name
houseId: uni.getStorageSync('buildingID').id,
houseName: uni.getStorageSync('buildingID').name
})
},

@@ -661,6 +706,9 @@
this.equipmentisshow = false;
this.iniodianloang()
} else {
//蓝牙获取信息
if (this.equipmentType == 3) this.notiInit();
uni.setStorageSync("equipmentType", 0)
this.equipmentisshow = true;
// this.Myworkcard = false;
this.initequipment()
@@ -671,6 +719,8 @@
setTimeout(() => {
uni.stopPullDownRefresh()
}, 3000)

},

onShow() {
@@ -705,6 +755,8 @@
this.equipmentisshow = false;
this.iniodianloang()
} else {
if (this.equipmentType == 3) this.notiInit();
uni.setStorageSync("equipmentType", 0)
this.equipmentisshow = true;
// this.Myworkcard = false;
this.initequipment()
@@ -714,8 +766,33 @@
this.initrealTimeStatistics()
this.updateInit()
this.findByHouseIdForRecharge()

//蓝牙获取信息
this.notiInit();
},
methods: {
notiInit() {
var that = this;
if (this.connectDev) {
setNotification().then(() => {
uni.onBLECharacteristicValueChange((res) => {
let data = ab2hex(res.value);
if (data.pre[1] == "81") {
that.wifiDetail = JSON.parse(data.value)
console.log(1112,that.wifiDetail)
//获取绝对值
that.bsignalDevice = that.wifiDetail?Math.abs(that.wifiDetail.rssi):0
console.log(1113,that.bsignalDevice)
}
});
})

setTimeout(() => {
sendData([0xA0,0x81,0x00]);
},1000)
}
},
// 跳转客户详情
toCustomerManagement(str) {
console.log(str)
@@ -740,7 +817,6 @@
}
},


// 数据看板
toDataBoard() {
uni.navigateTo({
@@ -766,7 +842,6 @@
id: uni.getStorageSync('weapp_session_userInfo_data').accountId,
projectId: uni.getStorageSync('buildingID').id
}).then(res => {
console.log(res)
if (res > 0) {
uni.setTabBarBadge({ //显示数字
index: 4, //tabbar下标
@@ -1001,6 +1076,13 @@
} else {
this.imeiCode = data.data.data.imei
this.openFlag = data.data.data.recCmd
this.equipmentType = data.data.data.equipmentType;
uni.setStorageSync("equipmentType", this.equipmentType);
uni.setStorageSync("imeiCode", this.imeiCode);
if (this.equipmentType == 3) {
this.bluetooth();
}

if (data.data.data > 100) {
this.percentage = 100;
} else {
@@ -1009,18 +1091,21 @@
} else {
this.Whetheroffline = true;
this.percentage = data.data.data.electricity;
this.signalDevice = data.data.data.signalDevice / 1;
console.log(this.signalDevice)
this.audioStatus = data.data.data.simAudioStatus;
if (this.signalDevice > 80) {
this.signalDevicetext = '高';
} else {
if (this.signalDevice == 0) {
this.signalDevicetext = '';

if (this.equipmentType != 3) {
this.signalDevice = data.data.data.signalDevice / 1;
if (this.signalDevice > 80) {
this.signalDevicetext = '';
} else {
this.signalDevicetext = '低';
if (this.signalDevice == 0) {
this.signalDevicetext = '无';
} else {
this.signalDevicetext = '低';
}
}
}
}

}
@@ -1303,9 +1388,133 @@
url: '/pages/center/consumer/index?refresh=refresh'
});
}
},

//蓝牙相关
bluetooth() {
//判断如果是意外断开直接提示
if(!this.$store.state.connectState || !this.$store.state.connectDev){
var that = this;
uni.authorize({
scope: 'scope.bluetooth',
success: () => {
uni.openBluetoothAdapter({
success: (res) => {
uni.hideLoading();
that.$store.commit('setConnectState', true);
that.getBluetoothAdapterState();
},
fail: () => {
// uni.showModal({
// title: '提示',
// content: '请打开蓝牙后再重新连接',
// confirmText: '前往连接',
// success: (res) => {
// if (res.confirm) {
// uni.redirectTo({
// url:"/pages/bluetooth/connect"
// })
// }
// }
// })
}
});
},
fail: () => {
uni.hideLoading();
uni.showModal({
title: '提示',
content: '需要使用蓝牙功能,请授权使用',
showCancel: false,
success: () => {
uni.openSetting();
}
})
}
})
}
},
//搜索蓝牙
getBluetoothAdapterState() {
var that = this;
that.blist = [];
uni.getBluetoothAdapterState({
success: function(res) {
if (!res.discovering) {
that.startBluetoothDevicesDiscovery();
}
},
fail: function(res) {
uni.showToast({
title: '适配蓝牙失败',
icon: "none"
})
}
});
},
//搜索蓝牙
startBluetoothDevicesDiscovery() {
var that = this;
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: function(res) {
setTimeout(() => {
that.lanya5()
}, 3000)
that.onBluetoothDeviceFound();
},
fail: function(res) {
uni.showToast({
title: '搜索蓝牙设备失败',
icon: "none"
})
}
})
},
// 获取所有已发现的设备
onBluetoothDeviceFound() {
var that = this;
let blist = uni.getStorageSync("connectDevList");
let names = [];
blist.filter(v => {
names.push(v.name);
})
let connectBloo = false;
uni.onBluetoothDeviceFound((res) => {
res.devices.filter(v => {
if ( names.indexOf(v.name) > -1 && !connectBloo) {
connectBloo = true;
let item = {deviceId:v.deviceId,name:v.name};
uni.setStorageSync("lyDetail",item)
connectBlue(item).then(() => {
that.notiInit();
})
}
})
})
},

//停止搜索周边设备
lanya5() {
uni.getBluetoothAdapterState({
success: function(res) {
if (res.discovering) {
uni.stopBluetoothDevicesDiscovery({
success: function(res) {
console.log("蓝牙停止搜索")
}
})
}
}
})
},
connectDevice(item) {
this.bluetoothShow = false;
//connectBlue(item)
}
},

};
@@ -1657,4 +1866,44 @@
background-color: #F9C8C8;
color: #ff0000;
}

.bluetoothBox {
background-color: #fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
box-sizing: border-box;
padding: 32rpx 32rpx 100rpx;

.bluetoothTitle {
text-align: center;
font-size: 32rpx;
font-weight: 600;
margin-bottom: 20rpx;
}
.bluetoothList {
width: 100%;
padding:0 20rpx;
.bluetoothItem {
box-sizing: border-box;
padding: 0 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 90rpx;
line-height: 90rpx;
border-bottom: 1rpx solid #f8f8f8;
.bluetoothBtn {
width: 120rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
background-color: #2671E2;
color: #fff;
border-radius: 10rpx;
font-size: 24rpx;
}
}
}
}
</style>

+ 15
- 3
pages/index/personal.vue ファイルの表示

@@ -56,6 +56,15 @@
<image src="/static/images/right-arrow.png" mode=""></image>
</view>
</view>
<navigator v-if="equipmentType == 3" class="line" url="/pages/bluetooth/connect">
<view class="title">
<image src="/static/images/bluetooth.png" mode=""></image>
蓝牙配置
</view>
<view class="right">
<image src="/static/images/right-arrow.png" mode=""></image>
</view>
</navigator>
<!-- <view class="line" @click="help">
<view class="title">
<image src="/static/images/help-icon.png" mode=""></image>
@@ -102,15 +111,18 @@
photo: "",
mobile: "",
count: 0, //
equipmentType: 0
};
},
onShow() {
this.getTabBarBadge()
var userInfos = uni.getStorageSync('weapp_session_userInfo_data');
this.name = userInfos.name,
this.photo = userInfos.avatar,
this.mobile = userInfos.username
this.name = userInfos.name
this.photo = userInfos.avatar
this.mobile = userInfos.username
this.updateInit()
this.equipmentType = uni.getStorageSync("equipmentType");

},
methods: {
updateInit() {


+ 54
- 1
pages/mine/reception/addreception.vue ファイルの表示

@@ -99,6 +99,9 @@
</template>

<script>
import { sendData } from "@/utils/blue.js";
import { mapState, mapMutations } from 'vuex';
var app = getApp();
var config = require("../../../config");

@@ -139,6 +142,7 @@
isShow: false, // 默认隐藏该权限
isPass: false, // 当前顾问是否正在接待
fromBack: false, // 从选择顾问页面跳回
equipmentType: 0,


templateList: [], // 销讲业务
@@ -148,6 +152,7 @@
},

computed: {
...mapState(['connectDev','connectState']),
// 用户详情
userInfo() {
return uni.getStorageSync("weapp_session_userInfo_data")
@@ -234,6 +239,9 @@
save() {
// 校验当前登录人是否是顾问
let obj = this.freeList.find(item => {
if(item.agentId == this.parames.agentId) {
this.equipmentType = item.equipmentType?item.equipmentType:0;
}
return item.agentId == this.userInfo.accountId
}) || null
if (!obj && this.userInfo.userRoleType == 6) {
@@ -271,6 +279,9 @@
})
return;
}
const that = this;
this.$u.post("customer/daitiReception", {
phone: that.parames.phone,
@@ -312,30 +323,72 @@
const {
dataCode
} = uni.getStorageSync("weapp_session_userInfo_data");
if (this.parames.phone.length == 0) {
if (!this.parames.phone || this.parames.phone.length == 0) {
this.parames.phone = null
}
if (uni.getStorageSync("equipmentType") == 3) {
if (!this.connectState || !this.connectDev) {
uni.showModal({
title: "提示",
content: "当前顾问需要链接蓝牙工牌,是否前往?",
confirmText: "前往",
success(res) {
if (res.confirm) {
uni.navigateTo({
url: "/pages/bluetooth/connect"
})
}
}
})
return ;
} else {
this.parames.equipmentRecordStatus = "start";
}
}
uni.showLoading({
title: "保存中",
mask: true
})
if (dataCode == 6) {
this.$u.post("/customer/gwAdd", this.parames).then(res => {
uni.hideLoading();
uni.showToast({
icon: "none",
title: "保存成功"
})
//如果需要录音
if (uni.getStorageSync("equipmentType") == 3) {
if (this.connectState && this.connectDev) {
sendData([0xA0,0x5A,0x00]) //开启录音
}
}
uni.navigateBack()
})
} else {
this.$u.post("/customer/add", this.parames).then(res => {
uni.hideLoading();
uni.showToast({
icon: "none",
title: "保存成功"
})
//如果需要录音
if (uni.getStorageSync("equipmentType") == 3) {
if (this.connectState && this.connectDev) { //开启录音
sendData([0xA0,0x5A,0x00])
}
}
uni.navigateBack()
}).catch(res => {
console.log(res,"数据添加失败")
})
}
},


バイナリ
static/images/bluetooth-con.png ファイルの表示

変更前 変更後
幅: 64  |  高さ: 64  |  サイズ: 1.7 KiB

バイナリ
static/images/bluetooth-del.png ファイルの表示

変更前 変更後
幅: 64  |  高さ: 64  |  サイズ: 2.3 KiB

バイナリ
static/images/bluetooth-empty.png ファイルの表示

変更前 変更後
幅: 360  |  高さ: 228  |  サイズ: 20 KiB

バイナリ
static/images/bluetooth-ghh-ac.png ファイルの表示

変更前 変更後
幅: 48  |  高さ: 48  |  サイズ: 1.6 KiB

バイナリ
static/images/bluetooth-ghh.png ファイルの表示

変更前 変更後
幅: 56  |  高さ: 56  |  サイズ: 1.5 KiB

バイナリ
static/images/bluetooth-scan.png ファイルの表示

変更前 変更後
幅: 60  |  高さ: 60  |  サイズ: 926 B

バイナリ
static/images/bluetooth-search.png ファイルの表示

変更前 変更後
幅: 72  |  高さ: 72  |  サイズ: 2.6 KiB

バイナリ
static/images/bluetooth-sx.png ファイルの表示

変更前 変更後
幅: 64  |  高さ: 64  |  サイズ: 2.1 KiB

バイナリ
static/images/bluetooth-wifi.png ファイルの表示

変更前 変更後
幅: 60  |  高さ: 60  |  サイズ: 2.2 KiB

バイナリ
static/images/bluetooth.png ファイルの表示

変更前 変更後
幅: 40  |  高さ: 40  |  サイズ: 1.3 KiB

バイナリ
static/images/ly-ac.png ファイルの表示

変更前 変更後
幅: 64  |  高さ: 64  |  サイズ: 2.1 KiB

バイナリ
static/images/ly.png ファイルの表示

変更前 変更後
幅: 64  |  高さ: 64  |  サイズ: 2.3 KiB

+ 11
- 0
store/index.js ファイルの表示

@@ -8,9 +8,20 @@ export default new Vuex.Store({
bgAudioMannager: null, // 背景音频播放对象
isBgPlay: false, // 是否后台播放
messageObj: {}, //
connectDev: "", //当前蓝牙设备
connectState: false
},

mutations: {
// 设置蓝牙开启状态
setConnectState(state,obj) {
state.connectState = obj
},
// 设置蓝牙
setConnectDev(state,obj) {
state.connectDev = obj
},

// 日报详情
setMessageObj(state, obj) {


+ 345
- 0
utils/blue.js ファイルの表示

@@ -0,0 +1,345 @@
import store from '../store/index.js';

export const serviceId = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"; //6E400001-0000-1000-8000-00805F9B34FB
export const writeCharacteristicId = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"; //
export const readCharacteristicId = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"; //

//循环获取当前蓝牙状态
let timer = uni.getStorageSync("blueStateTime");
let maxConnectNum = 3;
let isModalShown = false;
let oneMac = "";

//蓝牙连接状态
export const blueConnectState = () => {
uni.getConnectedBluetoothDevices({
services: [serviceId],
success(res) {
//console.log('获取链接状态成功:', res.devices);
store.commit('setConnectState', true);
// if (res.devices.length > 0) {
// store.commit('setConnectDev', res.devices[0]);
// }
},
fail(res) {
//console.log('获取连接状态失败:', res);
store.commit('setConnectDev', "");
store.commit("setConnectState", false);
}
});
}

blueConnectState();
if (timer) clearInterval(timer)
timer = setInterval(() => {
blueConnectState();
}, 5000);
uni.setStorageSync("blueStateTime", timer)

//结束循环
export const blueStopConnectState = () => {
if (timer) {
clearInterval(timer)
uni.setStorageSync("blueStateTime", "")
}
}

let isConnecting = false;
const CONNECT_TIMEOUT = 10000; // 10秒超时
let connectTimeout = null;
//链接蓝牙
export const connectBlue = (mac) => {
return new Promise((resolve, reject) => {
if (isConnecting) {
uni.showToast({
title: '已有连接正在进行中',
icon: 'none'
});
return reject(new Error('已有连接正在进行中'));
}
isConnecting = true;
connectTimeout = setTimeout(() => {
handleConnectError(new Error('连接超时'), 'timeout');
}, CONNECT_TIMEOUT);

uni.showLoading({
title: '连接中'
});
oneMac = mac;
maxConnectNum = 3;

const tryConnect = () => {
closeBlue().then(() => {
console.log("尝试连接", uni.getStorageSync('connectNum'), oneMac);
uni.createBLEConnection({
deviceId: mac.deviceId,
success: function(res) {
uni.setStorageSync('otherUnconnect',false)
clearTimeout(connectTimeout);
handleConnectionSuccess(resolve);
},
fail: function(err) {
handleConnectError(err, 1);
}
});
// 监听蓝牙连接状态变化
uni.onBLEConnectionStateChange(function(res) {
if (!res.connected && !isConnecting && uni.getStorageSync('connectNum') == 0) {
uni.setStorageSync('otherUnconnect',true)
store.commit('setConnectDev', "");
uni.setStorageSync('connectNum', 1);
handleConnectError({errMsg: "蓝牙连接断开"}, 2);
}
});
});
}

const handleConnectionSuccess = (resolve) => {
isConnecting = false;
uni.hideLoading();
if (uni.getSystemInfoSync().platform === "ios") {
setupIOSConnection(resolve);
} else {
completeConnection(resolve);
}
}

const setupIOSConnection = (resolve) => {
uni.getBLEDeviceServices({
deviceId: oneMac.deviceId,
success(res) {
uni.getBLEDeviceCharacteristics({
deviceId: oneMac.deviceId,
serviceId: serviceId,
success() {
completeConnection(resolve);
},
fail(err) {
handleConnectError(err, 4);
}
});
},
fail(err) {
handleConnectError(err, 3);
}
});
}

const completeConnection = (resolve) => {
isModalShown = false;
uni.setStorageSync('connectNum', 0);
setNotification();
store.commit('setConnectDev', oneMac);
store.commit('setConnectState', true);
resolve();
}
const handleConnectError = (err, type) => {
clearTimeout(connectTimeout);
uni.hideLoading();
if (uni.getStorageSync('connectNum') <= maxConnectNum && uni.getStorageSync('connectNum') > 0) {
console.log(`第${uni.getStorageSync('connectNum')}次重试`);
if (!store.state.connectDev) {
uni.setStorageSync('connectNum', uni.getStorageSync('connectNum') + 1);
tryConnect();
}
} else {
isConnecting = false;
showReconnectModal();
}
}

tryConnect();
});
}

const showReconnectModal = () => {
if (isModalShown) return;
isModalShown = true;
uni.hideLoading();
uni.showModal({
title: '连接失败',
content: '蓝牙连接失败,前往手动连接?',
success: (res) => {
isModalShown = false;
if (res.confirm) {
uni.redirectTo({
url: '/pages/bluetooth/detail'
})
} else {
isConnecting = false;
uni.setStorageSync('connectNum', 4);
store.commit('setConnectDev', '');
store.commit('setConnectState', false);
}
},
fail: () => {
isModalShown = false;
isConnecting = false;
}
});
}

//通知消息检测
export const setNotification = () => {
return new Promise((reslove, rejcts) => {
let mac = store.state.connectDev

/*保存本地*/
let list = uni.getStorageSync("connectDevList") ? uni.getStorageSync("connectDevList") : []
let isHav = false;
list.filter(v => {
if (v.deviceId == mac.deviceId) isHav = true;
})
if (!isHav) {
list.push({name : mac.name,deviceId : mac.deviceId});
uni.setStorageSync("connectDevList", list);
}

/*保存本地结束*/
uni.notifyBLECharacteristicValueChange({
deviceId: oneMac.deviceId,
serviceId: serviceId,
characteristicId: readCharacteristicId,
state: true,
success(res) {
uni.setStorageSync('connectNum', 0);
console.log("接收通知成功", res);
reslove()
},
fail(res) {
console.log("接收通知失败", res);
closeBlue();
rejcts();
}
});
})

}

export const closeBlue = () => {
return new Promise((reslove, rejcts) => {
let connectDev = store.state.connectDev
if (connectDev) {
uni.closeBLEConnection({
deviceId: connectDev.deviceId,
success(res) {
console.log('蓝牙关闭成功:', res);
reslove();
},
fail(res) {
console.log('蓝牙关闭失败:', res);
reslove();
}
})
} else {
reslove();
}
})
}

//发送数据
export const sendData = (dataArray) => {
return new Promise((reslove, rejcts) => {
let connectDev = store.state.connectDev
if (!connectDev) {
uni.showModal({
title: "提示",
content: "蓝牙未连接"
})
rejcts()
}
console.log("数据发送", dataArray);
let uint8Array = new Uint8Array(dataArray);
wx.writeBLECharacteristicValue({
deviceId: connectDev.deviceId,
serviceId: serviceId,
characteristicId: writeCharacteristicId,
value: uint8Array.buffer,
success(res) {
console.log('数据发送成功:', res);
setTimeout(() => {
reslove();
}, 200)
},
fail(res) {
console.log('数据发送失败:', res);
uni.hideLoading();
if (res.errCode == 10006) {
store.commit('setConnectDev', "");
store.commit("setConnectState", false);
}
rejcts()
}
});
})
}

//关闭蓝牙
export const closeBlueAdapter = () => {
isModalShown = true;
uni.closeBluetoothAdapter({
success: (res) => {
blueConnectState();
isModalShown = false;
},
fail: (error) => {
isModalShown = false;
console.log("关闭蓝牙模块失败", error);
}
});
}
//返回数据反解析
export const ab2hex = (buffer, num = 2) => {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)

var hexString = "";
var hexResArr = [];
hexArr.filter((v, i) => {
if (i > num) {
hexString += v;
} else {
hexResArr.push(v);
}
});

let string = hexToString(hexString);
var data = {
pre: hexResArr,
value: string
};
return data;
}

//不弹弹窗
export const changeIsModalShown = () => {
isModalShown = true;
}

export const strToHex = (str) => {
var result = [];
for (var i = 0; i < str.length; i++) {
result.push("0x" + str.charCodeAt(i).toString(16));
}
return result;
}

function hexToString(hex) {
var rawString = "";
for (var i = 0; i < hex.length; i += 2) {
rawString += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
}
return rawString;
}

||||||
x
 
000:0
読み込み中…
キャンセル
保存