560 lines
14 KiB
Vue
560 lines
14 KiB
Vue
<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> |