560 lines
14 KiB
Vue
Raw Permalink Normal View History

2025-05-22 16:24:05 +08:00
<template>
<view class="device-group-wrap">
<view class="search-wrap">
<div class="left-wrap">
<u-search v-model="queryParams.groupName" shape="square" @search="handleSearch" @custom="handleSearch"
:inputStyle="{ height: '64rpx' }" :placeholder="$tt('group.inputContent')"
:actionText="$tt('timing.search')"
:actionStyle="{ backgroundColor: '#398ade', color: '#fff', padding: '0 12rpx', borderRadius: '6rpx', height: '64rpx', lineHeight: '64rpx' }"></u-search>
</div>
<div class="right-wrap">
<u-button @click="handleAddGrup()" type="success" :text="$tt('common.add')" icon="plus"
:customStyle="{ width: '120rpx', height: '64rpx' }" size="small"></u-button>
</div>
</view>
<view class="card-wrap" v-for="(item, index) in dataList" :key="index" @click="handleEdit(item)">
<u-row gutter="10" customStyle="margin:0;">
<u-col :span="6"
customStyle="background-color:#3fd1ad; padding:40rpx; border-top-left-radius:10rpx; border-bottom-left-radius:10rpx;">
<u--text prefixIcon="grid" iconStyle="color:#fff; font-size:36rpx; margin-right:8rpx;" bold
lines="1" :text="item.groupName" customStyle="color:#fff; font-size: 32rpx;"></u--text>
</u-col>
<u-col :span="6">
<view class="button-group" @click.stop>
<u-button type="success" @click="handleAddDevice(item)" size="small"
customStyle="width:160rpx; height: 70rpx;">{{ $tt('group.add') }}</u-button>
<u-button type="info" @click="showDeviceSelector(item.groupId)" size="small"
customStyle="width:160rpx; height: 70rpx;">区域控制</u-button>
</view>
</u-col>
</u-row>
</view>
<!-- 区域控制弹窗 -->
<u-popup :show="showDevicePopup" mode="center" @close="closeDevicePopup" round="10">
<view class="area-control-popup">
<view class="popup-header">
<text class="popup-title">区域控制</text>
<u-icon name="close" size="20" @click="closeDevicePopup"></u-icon>
</view>
<view class="popup-content">
<!-- 设备类型选择 -->
<u-tabs :list="tabsList" :current="Number(activeMenu)" @click="handleMenuSelect"></u-tabs>
<!-- 安全王配置 -->
<view v-if="activeMenu === 0" class="security-king">
<u-form :model="formData" labelPosition="left">
<u-form-item label="参数上传时间间隔">
<u-input v-model="paramUploadInterval" placeholder="请输入参数上传时间间隔" />
</u-form-item>
<!-- <u-form-item label="接地电阻测试周期">
<u-input v-model="groundResistanceTestInterval" placeholder="请输入接地电阻测试周期" />
</u-form-item> -->
</u-form>
<view class="button-area">
<u-button type="success" @click="submitFormreglin(Security_King)">发送</u-button>
</view>
</view>
<!-- 单灯控配置 -->
<view v-if="activeMenu === 1" class="light-control">
<view class="time-select">
<text class="time-label">时间:</text>
<u-button @click="showTimePicker = true" type="info" size="small">
{{ startTime || '请选择开始时间' }}
</u-button>
</view>
<u-datetime-picker :show="showTimePicker" v-model="startTime" mode="time" @confirm="timeConfirm"
@cancel="timeCancel" :minuteStep="1" format="HH:mm"></u-datetime-picker>
<view class="light-table">
<view class="table-header">
<text style="width: 25%;">阶段</text>
<text style="width: 37.5%;">时长(分钟)</text>
<text style="width: 37.5%;">亮度(%)</text>
</view>
<view class="table-body">
<view class="table-row" v-for="(row, index) in tableData" :key="index">
<text style="width: 25%;">{{ row.segment }}</text>
<view style="width: 37.5%;">
<u-input v-model="row.duration" placeholder="输入时长" type="number" />
</view>
<view style="width: 37.5%;">
<u-input v-model="row.brightness" placeholder="输入亮度" type="number" />
</view>
</view>
</view>
</view>
<view class="button-area">
<u-button type="success" @click="submitlightcontrol(Single_lightcontrol)">发送配置</u-button>
</view>
</view>
</view>
</view>
</u-popup>
<u-empty mode="list" :show="total === 0" marginTop="30"></u-empty>
<u-loadmore :status="status" v-if="total > queryParams.pageSize" marginTop="20"
:nomoreText="$tt('group.nomore')" />
</view>
</template>
<script>
import {
getGroupList
} from '@/apis/modules/group';
import {
listDeviceShort
} from '@/apis/modules/device.js';
export default {
data() {
return {
status: 'nomore', // 加载更多
dataList: [], // 列表数据
total: 0, // 总条数
queryParams: {
pageNum: 1,
pageSize: 10,
userId: 0,
groupName: null,
},
showDevicePopup: false,
selectedDevices: [],
currentGroup: null,
deviceOptions: [
{ deviceName: '安全王' },
{ deviceName: '双灯控' }
],
tabsList: [
{ name: '安全王' },
{ name: '单灯控' }
],
activeMenu: 0,
showTimePicker: false,
startTime: '',
paramUploadInterval: '',
groundResistanceTestInterval: '',
tableData: [
{ segment: '阶段1', duration: '', brightness: '' },
{ segment: '阶段2', duration: '', brightness: '' },
{ segment: '阶段3', duration: '', brightness: '' }
],
Security_King: [],
Single_lightcontrol: [],
formData: {}, // 添加表单数据对象
timeParams: {
hour: true,
minute: true,
second: false
}
};
},
onLoad() {
this.getToken();
if (this.token != '' && this.token != null) {
this.connectMqtt();
}
this.queryParams.userId = this.profile.userId;
this.getList();
},
onShow() {
let operate = getApp().globalData.operate;
if (operate && operate == 'operate') {
this.getList();
// 置空 operate
getApp().globalData.operate = "";
}
},
methods: {
getToken() {
// 本地缓存获取token
this.token = uni.getStorageSync('token');
// vuex存储token
uni.$u.vuex('vuex_token', this.token);
},
// 连接Mqtt消息服务器
async connectMqtt() {
if (this.$mqttTool.client == null) {
await this.$mqttTool.connect(this.vuex_token);
}
this.mqttCallback();
this.getDatas();
},
// 获取列表数据
getList() {
getGroupList(this.queryParams).then(response => {
if (this.queryParams.pageNum == 1) {
this.dataList = response.rows;
} else {
this.dataList = this.dataList.concat(response.rows);
}
this.total = response.total;
uni.stopPullDownRefresh();
});
},
// 搜索
handleSearch(value) {
this.dataList = [];
this.queryParams.pageNum = 1;
this.getList(true);
},
// 新增
handleAddGrup() {
uni.navigateTo({
url: '/pagesB/user/deviceGroup/detail'
});
},
// 编辑
handleEdit(item) {
uni.navigateTo({
url: '/pagesB/user/deviceGroup/detail?groupId=' + item.groupId
});
},
// 选择分组设备
handleAddDevice(item) {
uni.navigateTo({
url: '/pagesB/user/deviceGroup/devices?groupId=' + item.groupId + '&groupUserId=' +
item.userId
});
},
// 下拉刷新
onPullDownRefresh() {
this.dataList = [];
this.queryParams.pageNum = 1;
this.getList(); // Http获取列表
},
// 上拉加载
onReachBottom() {
this.status = 'loading';
this.queryParams.pageNum = this.queryParams.pageNum + 1;
if ((this.queryParams.pageNum - 1) * this.queryParams.pageSize > this.total) {
this.status = 'nomore';
} else {
this.getList();
this.status = 'loading';
}
},
// 显示设备选择弹窗
showDeviceSelector(group) {
this.currentGroup = group;
console.log('当前分组:', JSON.stringify(this.currentGroup));
this.showDevicePopup = true;
// 这里可以添加获取可选设备列表的接口调用
this.getAvailableDevices();
},
// 获取可选设备列表
getAvailableDevices() {
const GroupListqueryParams = {
pageNum: 1,
pageSize: 12,
showChild: true,
groupId: this.currentGroup,
};
listDeviceShort(GroupListqueryParams).then((response) => {
this.deviceList = response.rows;
this.total = response.total;
// 按 productId 分成两个数组
const lightcontrol = this.deviceList.filter(device => device.productId === 138);
const Security = this.deviceList.filter(device => device.productId === 136);
this.Security_King = Security;
this.Single_lightcontrol = lightcontrol;
console.log("安全王设备:", JSON.stringify(this.Security_King));
console.log("单灯控设备:", JSON.stringify(this.Single_lightcontrol));
});
},
// 关闭设备选择弹窗
closeDevicePopup() {
this.showDevicePopup = false;
this.selectedDevices = [];
this.currentGroup = null;
},
// 确认设备选择
confirmDeviceSelection() {
if (this.selectedDevices.length === 0) {
uni.showToast({
title: '请选择设备',
icon: 'none'
});
return;
}
// 这里添加关联设备的逻辑
console.log('选中的设备:', this.selectedDevices);
console.log('当前分组:', this.currentGroup);
// 示例调用关联设备的API
// linkDevicesToGroup({
// groupId: this.currentGroup.groupId,
// deviceIds: this.selectedDevices
// }).then(res => {
// if (res.code === 200) {
// uni.showToast({
// title: '关联成功',
// icon: 'success'
// });
// this.closeDevicePopup();
// this.getList(); // 刷新列表
// }
// });
// 临时显示成功提示
uni.showToast({
title: '关联成功',
icon: 'success'
});
this.closeDevicePopup();
},
// 连接Mqtt消息服务器
async connectMqtt() {
if (this.$mqttTool.client == null) {
await this.$mqttTool.connect(this.vuex_token);
}
},
// 订阅消息
mqttSubscribe(list) {
// 订阅当前页面设备状态和实时监测
let topics = [];
for (let i = 0; i < list.length; i++) {
let topicStatus = '/' + list[i].productId + '/' + list[i].serialNumber + '/status/post';
topics.push(topicStatus);
}
this.$mqttTool.subscribe(topics);
},
// 提交安全王配置
submitFormreglin(devicelist) {
let message = [{
"id": "report_time_min",
"remark": "",
"value": this.paramUploadInterval || "0"
}];
console.log("安全王设置下发数据:", JSON.stringify(message));
this.AreamqttSubscribe(devicelist, JSON.stringify(message));
},
// 提交单灯控配置
submitlightcontrol(devicelist) {
console.log('当前时间值:', this.startTime);
// 默认值
let startHour = '00';
let startMinute = '00';
// 解析时间字符串
if (this.startTime && typeof this.startTime === 'string') {
const timeParts = this.startTime.split(':');
if (timeParts.length === 2) {
startHour = String(timeParts[0]).padStart(2, '0');
startMinute = String(timeParts[1]).padStart(2, '0');
}
}
let message = [
{
"id": "S1_startH",
"remark": "",
"value": startHour
},
{
"id": "S1_startM",
"remark": "",
"value": startMinute
},
{
"id": "S1_seg1M",
"remark": "",
"value": this.tableData[0].duration || "0"
},
{
"id": "S1_seg1B",
"remark": "",
"value": this.tableData[0].brightness || "0"
},
{
"id": "S1_seg2M",
"remark": "",
"value": this.tableData[1].duration || "0"
},
{
"id": "S1_seg2B",
"remark": "",
"value": this.tableData[1].brightness || "0"
},
{
"id": "S1_seg3M",
"remark": "",
"value": this.tableData[2].duration || "0"
},
{
"id": "S1_seg3B",
"remark": "",
"value": this.tableData[2].brightness || "0"
}
];
console.log("单灯控设置下发数据:", JSON.stringify(message));
this.AreamqttSubscribe(devicelist, JSON.stringify(message));
},
// MQTT订阅和发布
AreamqttSubscribe(list, message) {
let topics = [];
for (let i = 0; i < list.length; i++) {
let topicService = '/' + list[i].productId + '/' + list[i].serialNumber + '/function/get';
topics.push(topicService);
this.$mqttTool.subscribe([topicService]);
this.$mqttTool.publish(topicService, message, list[i].serialNumber)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
}
console.log("Subscribe Topics:", JSON.stringify(topics));
uni.showToast({
title: '指令下发成功',
icon: 'success'
});
},
timeConfirm(e) {
console.log('选择的时间:', e);
// 直接保存时分
this.startTime = {
hour: e, // 直接保存选择的时间值
minute: e
};
this.showTimePicker = false;
},
timeCancel() {
this.showTimePicker = false;
},
handleMenuSelect(item) {
this.activeMenu = Number(item.index);
}
}
};
</script>
<style lang="scss">
page {
background: #eef3f7;
}
.device-group-wrap {
.search-wrap {
padding: 20rpx;
background: #ffffff;
display: flex;
flex-direction: row;
align-items: center;
.left-wrap {
flex: 1;
}
.right-wrap {
margin-left: 20rpx;
}
}
.card-wrap {
box-shadow: 0 2rpx 0 0 rgba(0, 0, 0, 0.1);
border-radius: 10rpx;
margin: 20rpx;
background-color: #ffffff;
min-height: 120rpx;
cursor: pointer;
transition: all 0.3s;
&:active {
opacity: 0.8;
}
.button-group {
display: flex;
gap: 10rpx;
padding: 10rpx;
justify-content: center;
align-items: center;
height: 100%;
}
}
}
.area-control-popup {
width: 90vw;
max-height: 80vh;
background-color: #fff;
border-radius: 20rpx;
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #eee;
.popup-title {
font-size: 32rpx;
font-weight: bold;
}
}
.popup-content {
padding: 20rpx;
.time-select {
display: flex;
align-items: center;
margin: 20rpx 0;
.time-label {
margin-right: 10rpx;
font-size: 28rpx;
}
}
.light-table {
border: 1rpx solid #eee;
border-radius: 10rpx;
margin: 20rpx 0;
.table-header {
display: flex;
background-color: #f5f7fa;
padding: 20rpx;
text-align: center;
}
.table-row {
display: flex;
padding: 20rpx;
border-top: 1rpx solid #eee;
align-items: center;
text-align: center;
}
}
.button-area {
margin-top: 30rpx;
text-align: center;
}
}
}
</style>