congming_huose-apk/pages/device/addhubwifi.vue

801 lines
17 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="device-detail">
<view class="bj"></view>
<!-- 头部保持原样 -->
<view class="tabback">
<view style="font-size: 36rpx;font-weight: 600;" class="" @click="onCancel">
</view>
<view class="name">{{ $t('addWifiTitle') }}</view>
<view class="add-btn" style="width: 50rpx;"></view>
</view>
<view class="ly">
<view class="cu" style="margin-right: 10rpx;">
<text v-if="ver_dataflag == 1"></text><text v-if="ver_dataflag == 2" style="background-color: #2788f7;"></text><text v-if="ver_dataflag == 3" style="background-color: #61e24f;"></text>
<view v-if="ver_dataflag == 1" style="color: red;" class="">{{ $t('bluetoothConnectionStatus') }}</view>
<view v-if="ver_dataflag == 2" style="color: #2788f7;" class="">{{ $t('bluetoothStatus') }}</view>
<view v-if="ver_dataflag == 3" style="color: #61e24f;" class="">{{ $t('bluetoothStatus') }}</view>
</view>
<view class="xi" style="color: red;border: 1px solid red;" @click="getlj" v-if="ver_dataflag == 1">
{{ $t('clickToConnect') }}
</view>
<view class="xi" v-if="ver_dataflag == 2" style="color: #2788f7;">
{{ $t('connecting') }}
</view>
<view class="xi" v-if="ver_dataflag == 3" style="color: #61e24f;">
{{ $t('connected') }}
</view>
</view>
<view class="content-container" style="background-color: #F3F5F6;">
<view class="peiwang">
<view class="wifi" style="border-bottom: 1px solid #D8D8D8;">
<view class="">
<image src="https://api.ccttiot.com/smartmeter/img/static/ukxdSJmKDJ8YxvaHcfEb" mode=""></image>
{{ $t('wifiNameLabel') }}
</view>
<input type="text" v-model="wifiname" :placeholder="$t('wifiNamePlaceholder')" />
</view>
<view class="wifi">
<view class="">
<image src="https://api.ccttiot.com/smartmeter/img/static/uibUVxsJvMdNRMXi0TWw" mode=""></image>
{{ $t('wifiPasswordLabel') }}
</view>
<input type="text" v-model="wifipwd" :placeholder="$t('wifiPasswordPlaceholder')" />
</view>
</view>
<view class="sm">
{{ $t('wifiFrequencyWarning') }}
</view>
</view>
<view class="anniu">
<view class="btnan" @click="btnjx">
{{ $t('completeText') }}
</view>
</view>
<view class="loading-overlay" v-if="tcflag">
<view class="" v-if="ver_dataflag == 2">
<view class="spinner"></view>
<text class="loading-text">{{ $t('bluetoothConnectingWait') }}</text>
</view>
<view class="shibai" v-if="ver_dataflag == 1">
<view class="titda">
{{ $t('bluetoothConnectionFailed') }}
</view>
<view class="loading-text">{{shibaitxt}}</view>
<view class="anniu">
<view class="" @click="btnqx">
{{ $t('cancelConnection') }}
</view>
<view class="" style="background-color: #000;color: #fff;" @click="getlj">
{{ $t('clickToRetry') }}
</view>
</view>
</view>
</view>
<view class="loading-overlay" v-if="wififlag">
<view class="">
<view class="spinner"></view>
<text class="loading-text">{{ $t('hubConfiguringWait') }}</text>
</view>
</view>
</view>
</template>
<script>
import i18n from '@/common/i18n/index.js';
var xBlufi = require("@/common/blufi/xBlufi.js")
export default {
data() {
return {
deviceid: '',
type: '',
ver_dataflag: 1,
devicesarr: [],
deviceid: '',
devicename: '',
mac: '',
shibaitxt:'',
tcflag:false,
shibainum:0,
wifiname:'',
wifipwd:'',
wififlag:false
}
},
computed: {
$t() {
return i18n.t;
}
},
onLoad(option) {
console.log(option);
xBlufi.initXBlufi(1)
xBlufi.notifyStartDiscoverBle({
'isStart': true
})
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
if (option.mac) {
this.mac = option.mac
this.getlj()
}
},
methods: {
// 点击取消连接
btnqx(){
this.ver_dataflag = 1
this.tcflag = false
},
// 点击返回上一级
onCancel() {
uni.navigateBack({
delta: 1
})
},
// 点击继续下一步
btnjx() {
if(this.ver_dataflag == 3){
if(this.wifiname == ''){
uni.showModal({
title: this.$t('warmPrompt'),
content: this.$t('wifiNameCannotBeEmpty'),
showCancel: false,
success: function(res) {
}
})
}else if(this.wifipwd == ''){
uni.showModal({
title: this.$t('warmPrompt'),
content: this.$t('wifiPasswordCannotBeEmpty'),
showCancel: false,
success: function(res) {
}
})
}else{
this.wififlag = true
xBlufi.notifySendCustomData({
      customData: "ssid@" + this.wifiname + "pass@" + this.wifipwd
 })
}
}else{
uni.showModal({
title: this.$t('warmPrompt'),
content: this.$t('pleaseConnectDeviceFirst'),
showCancel: false,
success: function(res) {
}
})
}
},
// 进行蓝牙连接
getlj() {
console.log('蓝牙连接开始');
let that = this
const findDevice = () => {
that.ver_dataflag = 2
that.tcflag = true
const matchedDevice = that.devicesarr.find(device => {
return device.name.slice(-12) == that.mac.slice(-12)
})
if (matchedDevice) {
xBlufi.notifyStartDiscoverBle({
'isStart': false
})
xBlufi.notifyConnectBle({
isStart: true,
deviceId: matchedDevice.deviceId,
name: matchedDevice.name
})
that.deviceid = matchedDevice.deviceId
that.devicename = matchedDevice.name
setTimeout(() => {
if (that.ver_dataflag == 3) {
that.tcflag = false
uni.showToast({ title: this.$t('connectionSuccess'), icon: 'success', duration: 3000})
} else {
that.ver_dataflag = 1
that.shibainum = 0
that.getztm()
}
}, 4000)
} else {
if (that.shibainum < 7) {
that.shibainum++
that.findDeviceTimer = setTimeout(findDevice.bind(that), 1000) // 使用 bind 保持 this 上下文
} else {
that.ver_dataflag = 1
that.shibainum = 0
that.getztm()
}
}
}
findDevice()
},
// 获取蓝牙失败状态码
getztm(){
let that = this
uni.openBluetoothAdapter({
success: function (res) {
console.log('蓝牙适配器正常,但未发现设备');
that.shibaitxt = that.$t('deviceNotFoundCheck')
},
fail: function (err) {
console.error('蓝牙适配器初始化失败', err)
console.log('错误码:', err.errCode, '错误信息:', err.errMsg)
const errMsg = err.errMsg || ''
if(errMsg.includes('auth deny') || errMsg.includes('authorize')){
that.shibaitxt = that.$t('bluetoothAuthDenied')
}else if(errMsg.includes('not available') || errMsg.includes('unavailable')){
that.shibaitxt = that.$t('bluetoothUnavailable')
}else if(errMsg.includes('open fail')){
that.shibaitxt = that.$t('bluetoothOpenFailed')
}else if(errMsg.includes('already opened')){
console.log('蓝牙适配器已打开,但未找到设备')
that.shibaitxt = that.$t('deviceNotFoundCheck')
}else if(errMsg.includes('system permission denied')){
that.shibaitxt = that.$t('systemBluetoothPermissionDenied')
}else if(errMsg.includes('bluetooth service unavailable')){
that.shibaitxt = that.$t('bluetoothServiceUnavailable')
}else{
that.shibaitxt = that.$t('bluetoothInitFailed') + (err.errMsg || '未知错误,请重试')
}
}
})
},
// 获取附近蓝牙设备列表
funListenDeviceMsgEvent: function(options) {
switch (options.type) {
case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED:
if (!options.result) {
this.ver_dataflag = 1
this.tcflag = true
console.log(this.ver_dataflag, '断开断开');
}
break;
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS:
if (options.result) {
this.devicesarr = options.data
}
break;
case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED:
console.log("连接回调:" + JSON.stringify(options))
if (options.result == true) {
setTimeout(() => {
this.ver_dataflag = 3
}, 2000)
xBlufi.notifyInitBleEsp32({
deviceId: this.deviceid
})
this.deviceid = options.data.deviceId
} else {
this.ver_dataflag = 1
}
break;
case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA:
console.log("1收到设备发来的自定义数据结果", options.data)
break;
case xBlufi.XBLUFI_TYPE.TYPE_CONNECT_ROUTER_RESULT:
uni.hideLoading();
if (!options.result) {
this.wififlag = false
let that = this;
uni.showModal({
title: this.$t('warmPrompt'),
content: this.$t('configFailedCheckWifi'),
showCancel: false,
success: function(res) {
}
})
} else {
if (options.data.progress == 100) {
this.wififlag = false
let that = this
uni.showModal({
title: this.$t('warmPrompt'),
content: this.$t('wifiConfigSuccess').replace('{wifiName}', that.wifiname),
showCancel: false,
success: function(res) {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
}
}
break;
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START:
if (!options.result) {
console.log('蓝牙未开启')
this.tcflag = true
this.getztm()
return
}
break;
}
},
}
}
</script>
<style scoped lang="less">
.ly{
width: 100%;
height: 100%;
background-color: #fff;
display: flex;
align-items: center;
padding: 30rpx 30rpx;
.cu{
display: flex;
align-items: center;
font-size: 32rpx;
font-weight: 600;
text{
display: block;
width: 8rpx;
height: 8rpx;
border-radius: 50%;
background-color: red;
margin-right: 10rpx;
}
}
.xi{
font-size: 28rpx;
padding: 10rpx 20rpx;
border-radius: 10rpx;
}
}
/* 加载遮罩层样式 */
.loading-overlay {
position: fixed;
bottom: 0;
left: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 400rpx;
z-index: 1000;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 30rpx;
padding-top: 100rpx;
z-index: 999;
.shibai{
.titda{
font-size: 32rpx;
font-weight: 600;
margin-bottom: 50rpx;
padding-left: 20rpx;
color: red;
}
.loading-text {
font-size: 28rpx;
color: #4caf50;
display: block;
width: 680rpx;
padding: 0 30rpx;
}
.anniu{
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0 20rpx;
padding-bottom: 50rpx;
view{
width: 48%;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 10rpx;
border: 1px solid #8d8d8d;
}
}
}
}
.spinner {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
border: 6rpx solid #e0e0e0;
border-top-color: #4caf50;
animation: spin 1s linear infinite;
margin-bottom: 24rpx;
margin: auto;
margin-bottom: 30rpx;
}
.loading-text {
font-size: 28rpx;
color: #4caf50;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.sm {
width: 100%;
text-align: center;
font-size: 28rpx;
color: #727272;
margin-top: 68rpx;
padding: 0 70rpx;
box-sizing: border-box;
}
.peiwang {
width: 750rpx;
height: 320rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
margin-top: 34rpx;
.wifi {
padding: 30rpx 38rpx;
box-sizing: border-box;
input {
font-size: 30rpx;
color: #000;
border-bottom: 1px solid #9E9E9E;
padding-bottom: 14rpx;
margin-top: 12rpx;
}
view {
display: flex;
align-items: center;
image {
width: 32rpx;
height: 32rpx;
margin-right: 10rpx;
}
font-size: 26rpx;
color: #7F7F7F;
}
}
}
.saoma {
width: 750rpx;
height: 128rpx;
background: #FFFFFF;
margin-top: 26rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
box-sizing: border-box;
.lt {
display: flex;
align-items: center;
font-size: 30rpx;
color: #3D3D3D;
image {
width: 80rpx;
height: 80rpx;
margin-right: 46rpx;
}
}
.rt {
width: 56rpx;
height: 56rpx;
image {
width: 56rpx;
height: 56rpx;
}
}
}
.centxt {
font-size: 28rpx;
color: #727272;
margin-top: 90rpx;
width: 100%;
text-align: center;
}
.names {
width: 750rpx;
height: 200rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
margin-top: 54rpx;
padding: 34rpx 48rpx;
box-sizing: border-box;
.tit {
font-size: 28rpx;
color: #7F7F7F;
}
input {
font-size: 32rpx;
color: #B9B9B9;
margin-top: 22rpx;
border-bottom: 1px solid #9E9E9E;
padding-bottom: 26rpx;
}
}
.anniu {
width: 750rpx;
height: 126rpx;
padding-top: 24rpx;
box-sizing: border-box;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
position: fixed;
left: 0;
bottom: 0;
.btnan {
width: 674rpx;
height: 80rpx;
background: #0F0F0F;
font-size: 32rpx;
color: #FFFFFF;
text-align: center;
line-height: 80rpx;
border-radius: 50rpx;
margin: auto;
}
}
.crop-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: #000;
}
.bj {
width: 100%;
height: 50vh;
position: fixed;
top: 0;
z-index: -1;
background-color: #0F0F0F;
}
.tabback {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 126rpx;
padding: 0 20rpx;
box-sizing: border-box;
background-color: #fff;
margin-top: 102rpx;
border-radius: 30rpx 30rpx 0 0;
.rtjt {
font-size: 36rpx;
color: #333;
}
.name {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin: 0 auto;
}
.add-btn {
font-size: 32rpx;
color: #ccc;
transition: color 0.3s;
&.active {
color: #333;
}
}
}
.device-detail {
// min-height: 100vh;
}
.content-container {
display: flex;
flex-direction: column;
min-height: calc(100vh - 228rpx);
.tit {
font-weight: 500;
font-size: 36rpx;
color: #0F0F0F;
width: 100%;
text-align: center;
margin-top: 110rpx;
}
.img {
width: 100%;
height: 410rpx;
text-align: center;
margin-top: 136rpx;
image {
width: 410rpx;
height: 410rpx;
}
}
.wgname {
font-size: 32rpx;
color: #727272;
margin-top: 86rpx;
width: 100%;
text-align: left;
padding-left: 228rpx;
box-sizing: border-box;
}
.xinghao {
font-size: 32rpx;
color: #727272;
margin-top: 36rpx;
width: 100%;
text-align: left;
padding-left: 228rpx;
box-sizing: border-box;
}
.banben {
font-size: 32rpx;
color: #727272;
margin-top: 36rpx;
width: 100%;
text-align: left;
padding-left: 228rpx;
box-sizing: border-box;
}
}
.instruction-section {
background: #f3f5f6;
text-align: center;
width: 100%;
height: 448rpx;
view {
position: relative;
left: 50%;
transform: translateX(-50%);
width: 272rpx;
margin-top: 88rpx;
}
.da {
width: 272rpx;
height: 272rpx;
border-radius: 50%;
}
.xiao {
width: 116rpx;
height: 72rpx;
position: absolute;
right: 0;
bottom: 0;
}
.instruction-text {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-top: 30rpx;
}
}
.input-section {
background: #fff;
padding: 40rpx 32rpx;
margin-top: 40rpx;
.input-group {
margin-bottom: 40rpx;
}
.input-label {
display: block;
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.code-input {
width: 100%;
height: 80rpx;
border: none;
border-bottom: 2rpx solid #e5e5e5;
font-size: 32rpx;
color: #333;
background: transparent;
padding: 0;
&::placeholder {
color: #bbb;
letter-spacing: 8rpx;
}
&:focus {
border-bottom-color: #000;
outline: none;
}
}
}
.help-section {
background: #f3f5f6;
padding: 40rpx 0;
padding-top: 20rpx;
padding-left: 48rpx;
}
.help-text {
font-size: 28rpx;
color: #727272;
}
.button-section {
margin-top: auto;
padding-top: 42rpx;
display: flex;
flex-direction: column;
align-items: center;
width: 750rpx;
height: 220rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
position: fixed;
left: 50%;
transform: translateX(-50%);
bottom: 0;
.continue-btn {
width: 674rpx;
height: 80rpx;
line-height: 80rpx;
background: #BBBBBB;
color: #fff;
border: none;
border-radius: 50rpx;
font-size: 32rpx;
font-weight: 600;
}
.continue-btn.active {
background: #000;
}
.cancel-btn {
margin-top: 34rpx;
font-size: 28rpx;
color: #000;
}
}
</style>