Sprinkler-app/page_user/dingshi.vue
2026-03-26 17:48:21 +08:00

1229 lines
34 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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>
<u-navbar :is-back="true" :title="$t('dingshi.title')" title-color="#000" :border-bottom="false" :background="bgc" id="navbar">
</u-navbar>
<image class="bj" src="https://api.ccttiot.com/smartmeter/img/static/urqUoIyCCEBykZ2oG8eO" mode=""></image>
<!-- 加载提示 -->
<u-loading-page :loading="isLoading" :loading-text="$t('dingshi.loadingSync')"></u-loading-page>
<view class="" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)">
<!-- SATER双通道A/B切换 -->
<view class="channel-switch" v-if="pre === 'SATER'">
<view class="channel-btn" :class="{ active: stareChannel === 'A' }" @click="setStareChannel('A')">A</view>
<view class="channel-btn" :class="{ active: stareChannel === 'B' }" @click="setStareChannel('B')">B</view>
</view>
<view class="list" v-if="list.length > 0 || list != null">
<view class="list_val" v-for="(values, key, index) in list" :key="key">
<view class="lt" @click="btnitem(key,index,values)">
<view class="one">{{ formattedTime(values[0], values[1]) }}</view>
<view class="two">P{{ index + 1 }} <text></text> {{ formatTime(values[2]) }}</view>
<view class="two">{{ formatInterval(values[4]) }}</view>
</view>
<view class="rt">
<u-switch v-model="values[3]" @change="btnchange(key,index,values)" active-color="#48893B"
inactive-color="#BDBCBC"></u-switch>
</view>
</view>
</view>
<!-- 设置浇水时间弹窗 -->
<view class="jiaoshui" v-if="timeflag">
<view class="top">
{{ $t('dingshi.setWater') }}
</view>
<view class="jssc">
{{ $t('dingshi.setWaterHint') }}
</view>
<view class="shifen" @click="btnshowone">
<text>{{hour}}{{ $t('dingshi.hourUnit') }}</text> <text>{{minutekq}}{{ $t('dingshi.clockMinUnit') }}</text>
</view>
<view class="jssc">
{{ $t('dingshi.waterDur') }}
</view>
<view class="shifen" @click="btnshowtwo">
<text>{{minute}}{{ $t('common.min') }}</text> <text>{{second}}{{ $t('common.sec') }}</text>
</view>
<view class="jiange">
<text>{{ $t('dingshi.everyNDaysWater') }}</text>
<view class="number-input">
<text class="btn-minus" @click="changeDays(-1)">-</text>
<text class="days">{{jgtian || 1}}</text>
<text class="btn-plus" @click="changeDays(1)">+</text>
</view>
</view>
<view class="anniu">
<view class="qx" @click="btnqx">
{{ $t('common.cancel') }}
</view>
<view class="qd" @click="btnqd">
{{ $t('common.confirm') }}
</view>
</view>
</view>
<view class="mask" v-if="timeflag"></view>
<!-- 定时时间 -->
<u-picker v-model="show" mode="time" :params="paramss" :defaultTime="defaultTime" @confirm="confirm"></u-picker>
<!-- 定时时长 -->
<u-picker v-model="shows" mode="time" :params="params" :defaultTime="defaultTimeLength" @confirm="confirms"></u-picker>
<view class="mask" style="z-index: 9999;" v-if="kgflag"></view>
</view>
<view class="choushuiben" v-else>
<view class="tit">
{{ $t('dingshi.pumpSettings') }}
</view>
<view class="name" @click="showtime = true">
<text>{{ $t('dingshi.startTime') }}</text>
<view class="">
{{formatStartTime(shi, fen)}} <u-icon name="arrow-right" color="#7C7C7C" size="28"></u-icon>
</view>
</view>
<view class="name">
<text>{{ $t('dingshi.workDur') }}</text>
<view class="">
<input type="number" v-model="miao" @input="handleMiaoInput" @blur="handleMiaoBlur"/>
{{ $t('common.sec') }}
</view>
</view>
<view class="name" style="border: 0;">
<text>{{ $t('dingshi.interval') }}</text>
<view class="">
<input type="number" v-model="tian"/>
{{ $t('common.day') }}
</view>
</view>
</view>
<view class="baocun" v-if="pre == 'SMSJ:'" @click="btnbc">
{{ $t('dingshi.save') }}
</view>
<u-picker v-model="showtime" mode="time" :params="paramstime" :default-time="'00:00'" @confirm="confirmtime"></u-picker>
<view class="" v-if="['WATER', 'DATER', 'TATER', 'SATER'].includes(pre)" style="width: 100%;padding-top: 80rpx;text-align: center;color: #000;font-size: 36rpx;">
{{ $t('dingshi.noMore') }}
</view>
</view>
</template>
<script>
var xBlufi = require("@/components/blufi/xBlufi.js")
export default {
data() {
return {
showtime: false,
paramstime: {
year: false,
month: false,
day: false,
hour: true,
minute: true,
second: false
},
bgc: {
backgroundColor: "#fff",
},
active: 1,
flag: false,
checked: false,
timeflag: false,
show: false,
params: {
year: false,
month: false,
day: false,
hour: false,
minute: true,
second: true,
},
shows: false,
paramss: {
year: false,
month: false,
day: false,
hour: true,
minute: true,
second: false,
},
minute: '--',
second: '--',
hour: '--',
minutekq: '--',
list: {},
checkedStatus: {},
deviceindex: '',
devicemiao: '',
deviceflag: '',
devicehour: '',
deviceminute: '',
kgflag: false,
xctime: '',
csbobj:{},
pre:'',
shi:'',
fen:'',
miao:'',
tian: '',
isLoading: false, // 加载状态
retryCount: 0, // 重试次数
maxRetries: 3, // 最大重试次数
lastOperation: null, // 最后一次操作
// 添加默认时间设置
defaultTime:'',
defaultTimeLength: '',
jgtian: '',
shebid:'',
zaixianobj:{},
mac:''
,
// SATER 双通道A/B
stareChannel: 'A',
saterListA: {},
saterListB: {},
saterRawPayload: '',
// SATER 按类型缓存pA/pB/ver 三组数据不定序到达,存各自最新值
saterDataByType: { pA: '', pB: '', ver: '' }
}
},
// 分享到好友(会话)
onShareAppMessage: function() {
return {
title: this.$t('app.name'),
path: '/pages/index/index'
}
},
// 分享到朋友圈
onShareTimeline: function() {
return {
title: this.$t('app.name'),
query: '',
path: '/pages/index/index'
}
},
onLoad(option) {
this.pre = option.pre
if (option.channel) {
this.stareChannel = option.channel === 'B' ? 'B' : 'A'
}
if(option.shebid){
this.shebid = option.shebid
this.getxq()
}else{
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
xBlufi.notifySendCustomData({
customData: "11get"
})
if (option.list && option.list.length > 0) { //判断有无数据 有数据直接拿 无数据则发送命令获取数据
if (option.pre == 'WATER' || option.pre == 'TATER' || option.pre == 'DATER' || option.pre == 'SATER') {
let listStr = option.list
try { listStr = decodeURIComponent(option.list) } catch(e) {}
const parsedList = JSON.parse(listStr)
if (option.pre === 'SATER') {
if (option.raw) {
try {
this.saterRawPayload = decodeURIComponent(option.raw)
} catch (e) {
this.saterRawPayload = option.raw
}
} else {
this.saterRawPayload = ''
}
if (this.saterRawPayload) {
const parsedAB = this.parseSaterRawToAB(this.saterRawPayload)
this.saterListA = parsedAB.A
this.saterListB = parsedAB.B
this.applySaterChannelList()
} else {
// 兼容没有 raw 时至少展示当前通道列表
const normalized = this.normalizeListSwitch(parsedList)
if (this.stareChannel === 'B') {
this.saterListB = normalized
} else {
this.saterListA = normalized
}
this.applySaterChannelList()
}
} else {
this.list = this.normalizeListSwitch(parsedList)
}
console.log(this.list,'listlistlist')
} else {
this.csbobj = JSON.parse(option.list)
console.log(this.csbobj,'chobjchobj')
this.shi = this.csbobj.hour
this.fen = this.csbobj.minute
this.miao = this.csbobj.second
this.tian = this.csbobj.day
}
} else {
xBlufi.notifySendCustomData({
customData: "11get"
})
}
}
},
onShow() {
},
onUnload() {
// 离开页面前取消蓝牙监听,避免重复回调;首页 onShow 会重新注册并同步 store 中的数据
xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent)
if (this.pre === 'SATER') {
this.saterDataByType = { pA: '', pB: '', ver: '' }
}
},
methods: {
normalizeListSwitch(obj){
const out = {}
if (!obj || typeof obj !== 'object') return out
Object.keys(obj).forEach((k) => {
const arr = Array.isArray(obj[k]) ? [...obj[k]] : [0, 0, 0, 0, 0]
while (arr.length < 5) arr.push(0)
arr[3] = arr[3] === 1 || arr[3] === true
out[k] = arr
})
return out
},
parseSaterRawToAB(rawInput){
const raw = String(rawInput || '')
const src = raw.replace(/@/g, ';')
const resultA = {}
const resultB = {}
for(let i = 1; i <= 6; i++){
resultA[`p_set${i}`] = [0, 0, 0, false, 0]
resultB[`p_set${i}`] = [0, 0, 0, false, 0]
}
const reg = /p([AB])(\d+):([^;]+)/g
let m
while((m = reg.exec(src)) !== null){
const ch = m[1]
const idx = Number(m[2])
if (!idx || idx < 1 || idx > 6) continue
const nums = m[3].split(',').map(v => {
const n = parseInt(v, 10)
return isNaN(n) ? 0 : n
})
while (nums.length < 5) nums.push(0)
nums[3] = nums[3] === 1
const key = `p_set${idx}`
if (ch === 'A') resultA[key] = nums
if (ch === 'B') resultB[key] = nums
}
return { A: resultA, B: resultB }
},
applySaterChannelList(){
if (this.pre !== 'SATER') return
const target = this.stareChannel === 'B' ? this.saterListB : this.saterListA
this.list = this.normalizeListSwitch(target)
},
buildBleTimerCmd(index1Based, hour, minute, second, enabled, intervalDays){
if (this.pre === 'SATER') {
const ch = this.stareChannel === 'B' ? 'B' : 'A'
return `11p${ch}${index1Based}:${hour},${minute},${second},${enabled},${intervalDays};`
}
return `11p_set${index1Based}:${hour},${minute},${second},${enabled},${intervalDays};`
},
formatStartTime(h, m){
if (h == null || h === '') return ''
const hh = String(h).length < 2 ? ('0' + h) : String(h)
const mm = String(m).length < 2 ? ('0' + m) : String(m)
return `${hh}:${mm}`
},
setStareChannel(ch){
this.stareChannel = ch === 'B' ? 'B' : 'A'
this.applySaterChannelList()
},
// SATER给 BLE 定时命令追加 A/B如 11p_set1A:... 或 11psetA,...
applyChannelToBleCmd(cmd){
if (this.pre !== 'SATER') return cmd
const s = String(cmd || '')
if (s.startsWith('11p_set')) {
return s.replace(/^11p_set(\d+):/, `11p_set$1${this.stareChannel}:`)
}
if (s.startsWith('11pset,')) {
return s.replace(/^11pset,/, `11pset${this.stareChannel},`)
}
return cmd
},
// 请求浇花器数据
getxq(){
this.$u.get(`/app/device/getDetail?deviceId=${this.shebid}`).then(res => {
if (res.code == 200) {
if(this.pre == 'SMSJ:'){
this.shi = res.data.iotData.h.length < 10 ? '0' + res.data.iotData.h.value : res.data.iotData.h.value
this.fen = res.data.iotData.m.length < 10 ? '0' + res.data.iotData.m.value : res.data.iotData.m.value
this.miao = res.data.iotData.t.value
this.tian = res.data.iotData.d.value
} else {
this.mac = res.data.mac
const params = res.data.iotData
if (this.pre === 'SATER' && (params.pA || params.pB)) {
// SATER 双阀:从 pA、pB 解析六组定时
const parsed = this.parseSaterFromApiParams(params)
this.saterListA = parsed.A
this.saterListB = parsed.B
this.applySaterChannelList()
} else {
// 单阀 WATER从后台字段 h1/m1/s1/o1...(以及可选 d1..d6) 组装展示结构
const mapped = this.buildListFromBackend(params)
this.list = mapped
}
}
}
})
},
// SATER从 getDetail 的 pA、pB 解析为六组定时 { A: {p_set1..p_set6}, B: {...} }
parseSaterFromApiParams(params){
const getVal = (obj) => {
if (!obj) return ''
const v = (obj && typeof obj === 'object' && 'value' in obj) ? obj.value : obj
return String(v == null ? '' : v).replace(/^["\s]+|["\s]+$/g, '')
}
const pAStr = getVal(params.pA)
const pBStr = getVal(params.pB)
const raw = (pAStr ? pAStr + ';' : '') + (pBStr || '')
return this.parseSaterRawToAB(raw)
},
// 后台 -> 定时列表结构(与蓝牙解析一致)
buildListFromBackend(params){
const result = {}
for(let i = 1; i <= 6; i++){
const h = Number(params?.[`h${i}`]?.value)
const m = Number(params?.[`m${i}`]?.value)
const s = Number(params?.[`s${i}`]?.value)
const o = Number(params?.[`o${i}`]?.value)
const d = Number(params?.[`d${i}`]?.value)
const hour = isNaN(h) ? 0 : h
const minute = isNaN(m) ? 0 : m
const second = isNaN(s) ? 0 : s
const onoff = !isNaN(o) && o === 1
const interval = isNaN(d) || d <= 0 ? 1 : d
result[`p_set${i}`] = [hour, minute, second, onoff, interval]
}
return result
},
// 选择启动时间
confirmtime(e){
console.log(e);
this.shi = e.hour
this.fen = e.minute
},
// 点击选择浇水时间
btnshowone(){
this.defaultTime = (this.hour.length < 10 ? '0' + this.hour : this.hour) + ':' + (this.minutekq.length < 10 ? '0' + this.minutekq : this.minutekq)
this.show = true
},
// 点击选择浇水时长
btnshowtwo(){
console.log(this.defaultTimeLength,this.minute,this.second,'111')
this.defaultTimeLength = '00' + ':' + this.minute + ':' + this.second
console.log(this.defaultTimeLength,this.minute,this.second,'222')
this.shows = true
},
// 显示加载
showLoading() {
this.isLoading = true
},
// 格式化间隔天数显示
formatInterval(days) {
const d = Number(days) || 0
return d <= 1 ? this.$t('dingshi.waterDaily') : this.$t('dingshi.waterEvery', { n: days })
},
// 隐藏加载
hideLoading() {
this.isLoading = false
setTimeout(() => {
this.isLoading = false
}, 500)
},
// 重试机制
async retryOperation() {
if (this.retryCount < this.maxRetries) {
this.retryCount++
await this.delay(1000)
if (this.lastOperation) {
this.lastOperation()
}
} else {
this.hideLoading()
uni.showToast({
title: this.$t('dingshi.opFail'),
icon: 'none'
})
this.retryCount = 0
}
},
// 延时函数
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},
// 点击开关是否开启
async btnchange(key, index, values) {
uni.showLoading({
title: this.$t('dingshi.operating')
})
try {
this.showLoading()
// 保持 UI 不变,等待请求成功后再更新
this.deviceindex = index
this.devicehour = values[0] || 0
this.deviceminute = values[1] || 0
this.devicemiao = values[2] || 0
const prevSwitch = !!values[3]
const nextSwitch = !prevSwitch
const intervalDays = parseInt(this.jgtian) || 1
const flag = nextSwitch ? 1 : 0
const cmdIndex = Number(this.deviceindex) + 1
let cucun = this.buildBleTimerCmd(cmdIndex, this.devicehour, this.deviceminute, this.devicemiao, flag, intervalDays)
if(this.shebid == ''){
this.lastOperation = () => {
xBlufi.notifySendCustomData({
customData: cucun
})
}
this.lastOperation()
await this.delay(1000)
xBlufi.notifySendCustomData({
customData: "11get"
})
// BLE 下不立即改 UI等待设备返回数据刷新
setTimeout(() => {
uni.hideLoading()
this.hideLoading()
}, 1000)
}else{
let parameters = {
date:cucun
}
const deviceTime = (String(this.devicehour).length < 2 ? '0' + this.devicehour : this.devicehour) + ':' + (String(this.deviceminute).length < 2 ? '0' + this.deviceminute : this.deviceminute);
let data = {
deviceId:this.shebid,
index:(Number(this.deviceindex) + 1),
enabled:flag,
wateringTime:deviceTime,
duration:this.devicemiao,
interval:intervalDays
// instructionKey:'date',
// parameters:parameters
}
this.$u.post(`/app/device/timedWatering`,data).then(res => {
if (res.code == 200) {
// 网关成功:仅本地更新开关状态
const keyName = `p_set${Number(this.deviceindex) + 1}`
if (this.list[keyName]) {
this.$set(this.list[keyName], 3, nextSwitch)
}
uni.showToast({
title: this.$t('index.setOk'),
icon: 'success',
duration:2000
})
// 不再请求新数据
}else{
// 失败则保持原状态
values[3] = prevSwitch
uni.showToast({
title: res.msg,
icon: 'none',
duration:2000
})
}
})
}
} catch (error) {
console.error('btnchange error:', error)
this.retryOperation()
}
},
// 点击设置定时时间
btnitem(key, index, values) {
// 从 key 中提取索引号,例如从 'p_set1' 提取 '1'
const indexMatch = key.match(/p_set(\d+)/)
this.deviceindex = indexMatch ? indexMatch[1] : index
this.timeflag = true
this.hour = values[0]
this.minutekq = values[1]
const totalSeconds = values[2]
const minutes = Math.floor(totalSeconds / 60)
const seconds = totalSeconds % 60
const formattedMinutes = minutes < 10 ? '0' + minutes : minutes.toString()
const formattedSeconds = seconds < 10 ? '0' + seconds : seconds.toString()
this.minute = formattedMinutes
this.second = formattedSeconds
// 添加间隔天数的处理,确保为数字
this.jgtian = parseInt(values[4]) || 0
// 设置设备相关值
this.devicehour = values[0]
this.deviceminute = values[1]
this.devicemiao = values[2]
if (this.list.hasOwnProperty(key)) {
const array = this.list[key]
// 只转换开关状态为布尔值
this.deviceflag = array[3] ? 1 : 0
}
},
formattedTime(minutes, seconds) {
// 将数字转换为字符串并补零
const formattedMinutes = String(minutes).padStart(2, '0')
const formattedSeconds = String(seconds).padStart(2, '0')
// 返回格式化后的时间字符串
return `${formattedMinutes}:${formattedSeconds}`
},
formatTime(seconds) {
const minutes = Math.floor(seconds / 60)
const remainingSeconds = seconds % 60
const s = (remainingSeconds < 10 ? '0' : '') + remainingSeconds
return this.$t('dingshi.durationMinSec', { m: minutes, s })
},
// 取消选择设置定时时间
btnqx() {
this.timeflag = false
this.hour = '--'
this.minutekq = '--'
this.minute = '--'
this.second = '--'
},
// 确定选择设置定时时间
async btnqd() {
try {
this.showLoading()
this.timeflag = false
this.hour = '--'
this.minutekq = '--'
this.minute = '--'
this.second = '--'
// 确保间隔天数为数字
const intervalDays = parseInt(this.jgtian) || 0;
let cucun = this.buildBleTimerCmd(this.deviceindex, this.devicehour, this.deviceminute, this.devicemiao, 1, intervalDays)
if(this.shebid == ''){
this.lastOperation = () => {
xBlufi.notifySendCustomData({
customData: cucun
})
}
this.lastOperation()
await this.delay(1000)
xBlufi.notifySendCustomData({
customData: "11get"
})
// BLE 下设置后计时刷新由设备推送完成
this.hideLoading()
}else{
let parameters = {
date:cucun
}
const deviceTime = (String(this.devicehour).length < 2 ? '0' + this.devicehour : this.devicehour) + ':' + (String(this.deviceminute).length < 2 ? '0' + this.deviceminute : this.deviceminute);
let data = {
deviceId:this.shebid,
index:this.deviceindex,
enabled:1,
wateringTime:deviceTime,
duration:this.devicemiao,
interval:intervalDays
// instructionKey:'date',
// parameters:parameters
}
this.$u.post(`/app/device/timedWatering`,data).then(res => {
if (res.code == 200) {
uni.showToast({
title: this.$t('index.setOk'),
icon: 'success',
duration:2000
})
// 网关成功:本地立即更新列表,避免再次请求
const key = `p_set${this.deviceindex}`
if (!this.list[key]) {
this.$set(this.list, key, [0,0,0,false,1])
}
// 更新为本次设置的值(使用 $set 保证响应式)
this.$set(this.list[key], 0, Number(this.devicehour) || 0)
this.$set(this.list[key], 1, Number(this.deviceminute) || 0)
this.$set(this.list[key], 2, Number(this.devicemiao) || 0)
this.$set(this.list[key], 3, true)
this.$set(this.list[key], 4, Number(intervalDays) || 1)
const now = new Date()
const at = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`
let shuju = {}
shuju[`d${this.deviceindex}`] = { value: String(this.jgtian), at }
shuju[`h${this.deviceindex}`] = { value: String(this.devicehour), at }
shuju[`m${this.deviceindex}`] = { value: String(this.deviceminute), at }
shuju[`o${this.deviceindex}`] = { value: '1', at }
shuju[`s${this.deviceindex}`] = { value: String(this.devicemiao), at }
let data = {
mac: this.mac,
params: shuju
}
this.$u.put(`/app/updateDeviceParam`, data).then(res => {})
}else{
uni.showToast({
title: res.msg,
icon: 'none',
duration:2000
})
}
})
}
} catch (error) {
console.error('btnqd error:', error)
this.retryOperation()
}
},
// 保存抽水泵设置
async btnbc() {
try {
if(this.shi >= 24){
uni.showToast({
title: this.$t('dingshi.maxHour'),
icon: 'none',
duration:2000
})
return
} else if(this.fen >= 60){
uni.showToast({
title: this.$t('dingshi.maxMin'),
icon: 'none',
duration:2000
})
return
}
// 限制工作时长不能超过9999秒
if(this.miao > 9999){
uni.showToast({
title: this.$t('dingshi.maxWorkSec'),
icon: 'none',
duration:2000
})
this.miao = 9999
}
this.showLoading();
this.timeflag = false;
if(this.tian > 99){
uni.showToast({
title: this.$t('dingshi.maxInterval'),
icon: 'none',
duration:2000
})
}
let tian = this.tian > 99 ? 99 : this.tian
let cucun = '11pset' + ',' + this.shi + ',' + this.fen + ',' + this.miao + ',' + tian + '@'
cucun = this.applyChannelToBleCmd(cucun)
if(this.shebid == ''){
this.lastOperation = () => {
xBlufi.notifySendCustomData({
customData: cucun
})
};
this.lastOperation()
await this.delay(1000)
xBlufi.notifySendCustomData({
customData: "11get"
})
uni.showToast({
title: this.$t('common.saveOk'),
icon: 'success',
duration: 2000
})
this.hideLoading()
}else{
let parameters = {
date:cucun
}
let data = {
deviceId:this.shebid,
wateringTime:this.shi + ':' + this.fen,
duration:this.miao,
interval:tian
// instructionKey:'date',
// parameters:parameters
}
this.$u.post(`/app/device/timedWatering`,data).then(res => {
if (res.code == 200) {
uni.showToast({
title: this.$t('common.saveOk'),
icon: 'success',
duration:2000
})
}else{
uni.showToast({
title: res.msg,
icon: 'none',
duration:2000
})
}
})
}
} catch (error) {
console.error('btnbc error:', error)
this.retryOperation()
}
},
// 定时浇水时间
confirm(e) {
this.hour = e.hour || '00'
this.minutekq = e.minute || '00'
this.devicehour = e.hour || '00'
this.deviceminute = e.minute || '00'
},
// 定时浇水时长
confirms(e) {
this.minute = e.minute || '00'
this.second = e.second || '00'
this.devicemiao = (Number(this.minute) * 60 + Number(this.second)) || 0
console.log(this.devicemiao)
},
funListenDeviceMsgEvent: function(options) {
switch (options.type) {
case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED:
if (!options.result) {
uni.showToast({
title: this.$t('dingshi.bleAbnormal'),
icon: 'none'
});
}
break;
case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA:
try {
console.log("收到设备发来的自定义数据结果:", options.data);
const inputString = options.data.slice(0, -1) + ";";
if (this.pre == 'WATER' || this.pre == 'TATER' || this.pre == 'DATER' || this.pre == 'SATER') {
if (this.pre === 'SATER') {
// SATER 设备分 3 种类型不定序推送pA(pA1:...)、pB(pB1:...)、ver(ver...@show:...)
// 按类型存最新值,集齐后解析并展示
let chunk = String(options.data || '')
if (chunk) chunk = chunk.slice(0, -1)
if (chunk) {
if (!chunk.endsWith(';')) chunk += ';'
if (chunk.includes('pA1:')) {
this.saterDataByType.pA = chunk
} else if (chunk.includes('pB1:')) {
this.saterDataByType.pB = chunk
} else if (chunk.startsWith('ver')) {
this.saterDataByType.ver = chunk
}
}
const { pA, pB, ver } = this.saterDataByType
if (pA && pB && ver) {
this.saterRawPayload = [ver, pA, pB].join('')
const parsedAB = this.parseSaterRawToAB(this.saterRawPayload)
this.saterListA = parsedAB.A
this.saterListB = parsedAB.B
this.applySaterChannelList()
if (this.$store) {
this.$store.commit('setBleWaterData', { raw: this.saterRawPayload })
}
}
} else {
const pairs = inputString.split(';');
const pSetObjects = {};
pairs.forEach(pair => {
if (!pair) return;
const [key, value] = pair.split(':');
if (key && key.startsWith('p_set') && value) {
try {
const numbers = value.split(',').map(num => {
const parsed = parseInt(num);
return isNaN(parsed) ? 0 : parsed;
});
// 只转换开关状态为布尔值
numbers[3] = numbers[3] === 1;
pSetObjects[key] = numbers;
} catch (e) {
console.error('数据解析错误:', e);
}
}
});
if (Object.keys(pSetObjects).length > 0) {
this.list = pSetObjects;
}
}
// 同步到全局 storeSATER 已在上面集齐时同步 saterRawPayload此处仅处理 WATER/TATER/DATER
if (this.$store && this.pre !== 'SATER') {
this.$store.commit('setBleWaterData', { raw: options.data })
}
} else {
const input = options.data.slice(0, -1) + ";"
// 去除末尾的分号并分割字符串
const parts = input.replace(";", "").split(":")
// 获取时间部分并分割
const timeParts = parts[1].split(",")
// 解析为对象
console.log(timeParts,'timePartstimePartstimeParts');
this.csbobj = {
hour: parseInt(timeParts[0]), // 小时
minute: parseInt(timeParts[1]), // 分钟
second: parseInt(timeParts[2]), // 秒
day: parseInt(timeParts[3]) // 天数
}
console.log(this.csbobj);
this.shi = this.csbobj.hour < 10 ? '0' + this.csbobj.hour : this.csbobj.hour
this.fen = this.csbobj.minute < 10 ? '0' + this.csbobj.minute : this.csbobj.minute
this.miao = this.csbobj.second
this.tian = this.csbobj.day
}
this.hideLoading();
} catch (error) {
console.error('数据处理错误:', error);
this.retryOperation();
}
break
}
},
// 处理工作时长输入
handleMiaoInput(e) {
// 在uni-app中直接使用e.detail.value获取输入值
let value = e.detail.value || e.target.value || '';
console.log('输入值:', value); // 调试用
// 转换为数字
let numValue = parseInt(value) || 0;
console.log('转换后数值:', numValue); // 调试用
// 限制最大值为9999
if (numValue > 9999) {
numValue = 9999;
uni.showToast({
title: this.$t('dingshi.maxWorkSec'),
icon: 'none',
duration: 2000
});
}
// 更新数据
this.miao = numValue;
console.log('最终miao值:', this.miao); // 调试用
},
// 处理工作时长失去焦点时的验证
handleMiaoBlur(e) {
// 再次验证并限制
if (this.miao > 9999) {
this.miao = 9999;
uni.showToast({
title: this.$t('dingshi.maxWorkSec'),
icon: 'none',
duration: 2000
});
}
},
// 改变天数
changeDays(change) {
let newValue = (parseInt(this.jgtian) || 1) + change;
// 确保天数不小于1
this.jgtian = Math.max(1, newValue);
},
}
}
</script>
<style lang="less">
::v-deep .u-title {
margin-bottom: 22rpx;
}
::v-deep .uicon-nav-back {
margin-bottom: 22rpx;
}
.channel-switch{
width: 680rpx;
margin: 22rpx auto 6rpx;
display: flex;
justify-content: flex-end;
padding: 8rpx;
border-radius: 999rpx;
box-sizing: border-box;
}
.channel-btn{
min-width: 110rpx;
height: 56rpx;
line-height: 56rpx;
padding: 0 24rpx;
text-align: center;
border-radius: 999rpx;
font-size: 28rpx;
font-weight: 600;
color: #6E7C70;
margin-left: 10rpx;
background: transparent;
border: 2rpx solid transparent;
transition: all .2s ease;
}
.channel-btn:first-child{
margin-left: 0;
}
.channel-btn.active{
color: #fff;
background: linear-gradient(135deg, #5CA74D 0%, #48893B 100%);
border-color: #4F9741;
box-shadow: 0 8rpx 18rpx rgba(72, 137, 59, 0.28);
transform: translateY(-1rpx);
}
.baocun{
margin: auto;
width: 680rpx;
height: 94rpx;
background: #48893B;
border-radius: 14rpx 14rpx 14rpx 14rpx;
margin-top: 50rpx;
text-align: center;
line-height: 100rpx;
border-radius: 20rpx;
color: #fff;
font-size: 32rpx;
}
.choushuiben{
width: 680rpx;
height: 426rpx;
background: #FFFFFF;
box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0,0,0,0.08);
border-radius: 20rpx;
padding: 36rpx 34rpx;
box-sizing: border-box;
.tit{
font-weight: 600;
font-size: 36rpx;
color: #3D3D3D;
}
.name{
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 34rpx;
border-bottom: 1px solid #D8D8D8;
padding-bottom: 34rpx;
box-sizing: border-box;
view{
display: flex;
}
text{
font-size: 32rpx;
color: #3D3D3D;
}
input{
width: 100rpx;
}
}
}
.jiaoshui {
position: fixed;
top: 366rpx;
left: 50%;
transform: translateX(-50%);
width: 678rpx;
max-height: 1200rpx;
padding-bottom: 30rpx;
box-sizing: border-box;
background: #FFFFFF;
border-radius: 24rpx 24rpx 24rpx 24rpx;
z-index: 99;
.top {
margin-top: 42rpx;
width: 100%;
text-align: center;
font-size: 44rpx;
color: #3D3D3D;
font-weight: 600;
}
.ts {
margin-top: 30rpx;
width: 100%;
text-align: center;
font-size: 32rpx;
color: #808080;
font-weight: 600;
}
.shifen {
width: 512rpx;
height: 128rpx;
background: #F0F0F0;
border-radius: 16rpx 16rpx 16rpx 16rpx;
margin: auto;
margin-top: 30rpx;
display: flex;
justify-content: space-between;
line-height: 128rpx;
padding: 0 102rpx;
box-sizing: border-box;
text {
font-size: 44rpx;
color: #3D3D3D;
font-weight: 600;
}
}
.jssc {
font-size: 32rpx;
color: #808080;
font-weight: 600;
margin-top: 58rpx;
margin-left: 96rpx;
}
.jiange {
width: 512rpx;
margin: 30rpx auto 0;
display: flex;
align-items: center;
justify-content: space-between;
text {
font-size: 32rpx;
color: #808080;
font-weight: 600;
}
.number-input {
display: flex;
align-items: center;
background: #F0F0F0;
border-radius: 16rpx;
padding: 0 20rpx;
height: 80rpx;
.btn-minus, .btn-plus {
width: 60rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
font-size: 40rpx;
color: #48893B;
font-weight: bold;
background: #fff;
border-radius: 8rpx;
}
.days {
margin: 0 30rpx;
min-width: 60rpx;
text-align: center;
font-size: 32rpx;
color: #3D3D3D;
}
}
}
.anniu {
display: flex;
justify-content: space-between;
margin-top: 58rpx;
padding: 0 44rpx;
box-sizing: border-box;
.qx {
width: 278rpx;
height: 80rpx;
border-radius: 10rpx 10rpx 10rpx 10rpx;
border: 2rpx solid #7FAD76;
font-size: 36rpx;
color: #7FAD76;
font-weight: 600;
line-height: 80rpx;
text-align: center;
}
.qd {
width: 278rpx;
height: 80rpx;
background: #7FAD76;
border-radius: 10rpx 10rpx 10rpx 10rpx;
font-size: 36rpx;
color: #fff;
font-weight: 600;
line-height: 80rpx;
text-align: center;
}
}
}
.mask {
width: 100%;
height: 100vh;
background-color: #000;
opacity: .6;
position: fixed;
top: 0;
left: 0;
z-index: 98;
}
.list {
.list_val {
width: 678rpx;
height: 248rpx;
background: #FFFFFF;
box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08);
border-radius: 20rpx;
padding-top: 16rpx;
padding-left: 42rpx;
padding-right: 42rpx;
box-sizing: border-box;
display: flex;
justify-content: space-between;
margin-top: 30rpx;
.lt {
width: 100%;
.one {
font-size: 72rpx;
color: #50565A;
font-weight: 600;
}
.two {
font-size: 32rpx;
color: #50565A;
margin-top: 12rpx;
text {
display: inline-block;
width: 1rpx;
height: 28rpx;
background: #3D3D3D;
margin-left: 26rpx;
margin-right: 26rpx;
}
}
}
.rt {
padding-top: 70rpx;
box-sizing: border-box;
}
}
}
page {
width: 100%;
padding: 20rpx 30rpx;
box-sizing: border-box;
background-color: #fff;
}
.bj {
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
</style>