2025-07-18 09:26:18 +00:00
|
|
|
|
<route lang="json5" type="page">
|
|
|
|
|
|
{
|
|
|
|
|
|
layout: 'default',
|
|
|
|
|
|
style: {
|
|
|
|
|
|
navigationBarTitleText: '办公室设备列表',
|
2025-07-24 01:39:14 +00:00
|
|
|
|
|
2025-07-18 09:26:18 +00:00
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
</route>
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<view class="container">
|
|
|
|
|
|
<!-- 楼层选择器 -->
|
|
|
|
|
|
<wd-row>
|
|
|
|
|
|
<wd-col :span="16">
|
|
|
|
|
|
<wd-col-picker label="选择楼层" prop="type" v-model="typeData" :columns="typeData" @confirm="handleConfirm"
|
|
|
|
|
|
:column-change="columnChange" :display-format="displayFormat" style="width: 99%;" />
|
|
|
|
|
|
</wd-col>
|
|
|
|
|
|
<wd-col :span="8" style="margin-top: 5px;">
|
|
|
|
|
|
<wd-button @click="cleanreset">重置</wd-button>
|
|
|
|
|
|
</wd-col>
|
|
|
|
|
|
</wd-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 设备状态卡片网格 - 两列布局 -->
|
|
|
|
|
|
<!-- 设备状态卡片网格 - 两列布局 -->
|
|
|
|
|
|
<view class="floor-wrapper">
|
|
|
|
|
|
<view v-for="(floor, floorIndex) in filteredFloors" :key="'floor' + floorIndex" class="floor-section">
|
|
|
|
|
|
<view class="room-grid">
|
|
|
|
|
|
<view v-for="(room, roomIndex) in floor.rooms" :key="room.id" class="room-card"
|
|
|
|
|
|
:class="{ 'room-active': room.homezt === 1 }"
|
|
|
|
|
|
@click="jump(`./officehomedevice?id=${room.id}&fjh=${room.fjh}`)">
|
|
|
|
|
|
<text v-if="room.fjh" class="room-number">{{ room.fjh }}室</text>
|
|
|
|
|
|
<view class="room-info">
|
|
|
|
|
|
<text class="info-label">所属部门:</text>
|
|
|
|
|
|
<text class="info-value">{{ room.ssbmname }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-07-24 01:39:14 +00:00
|
|
|
|
<!--
|
|
|
|
|
|
<view class="connection-section">
|
2025-07-18 09:26:18 +00:00
|
|
|
|
<button v-if="!connected" @click="connectWebSocket" class="connect-btn">
|
|
|
|
|
|
连接WebSocket
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
|
|
<button @click="disconnectWebSocket" class="disconnect-btn">
|
|
|
|
|
|
断开连接
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
|
|
<text :class="['status', connected ? 'connected' : 'disconnected']">
|
|
|
|
|
|
{{ connectionStatus }}
|
|
|
|
|
|
</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="message-container">
|
|
|
|
|
|
<text class="subtitle">消息记录</text>
|
|
|
|
|
|
<scroll-view scroll-y="true" class="message-list">
|
|
|
|
|
|
<view v-for="(item, index) in messages" :key="index" :class="['message-item', item.type]">
|
|
|
|
|
|
<text class="message-content">{{ item.content }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
</view> -->
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import {
|
|
|
|
|
|
ref
|
|
|
|
|
|
} from 'vue';
|
2025-07-24 01:39:14 +00:00
|
|
|
|
import {
|
|
|
|
|
|
onLaunch,
|
|
|
|
|
|
onShow,
|
|
|
|
|
|
onHide,
|
|
|
|
|
|
onLoad,
|
|
|
|
|
|
onReady
|
|
|
|
|
|
} from '@dcloudio/uni-app'
|
2025-07-18 09:26:18 +00:00
|
|
|
|
import {
|
|
|
|
|
|
gethomelist,
|
|
|
|
|
|
treeRootList,
|
|
|
|
|
|
contiontmqtt,
|
|
|
|
|
|
selectfjkzbmforfjid,
|
|
|
|
|
|
createdSwitch,
|
|
|
|
|
|
getMqttPushClient,
|
|
|
|
|
|
treeChildList,
|
|
|
|
|
|
listAllRegions,
|
|
|
|
|
|
Selecthomelist
|
|
|
|
|
|
} from '@/api/devicecontrol/officedevice';
|
2025-07-24 01:39:14 +00:00
|
|
|
|
// import socketforleader from '@/common/socketforleader'
|
2025-07-18 09:26:18 +00:00
|
|
|
|
|
|
|
|
|
|
// WebSocket状态
|
|
|
|
|
|
const connected = ref(false);
|
|
|
|
|
|
const message = ref('');
|
|
|
|
|
|
const messages = ref([]);
|
|
|
|
|
|
let socketTask = null;
|
|
|
|
|
|
const filteredFloors = ref([]); //楼层数据
|
|
|
|
|
|
const treeData = ref([]);
|
|
|
|
|
|
const homelist = ref([]) //获取房间信息
|
|
|
|
|
|
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
|
|
// 树节点选择处理
|
|
|
|
|
|
const selectedKeys = ref([]);
|
|
|
|
|
|
const lastSelectedNode = ref('');
|
|
|
|
|
|
const typeData = ref([])
|
|
|
|
|
|
const data = ref([])
|
|
|
|
|
|
const selectBydata = ref([]) //查找后的房间信息
|
|
|
|
|
|
const jump = (url) => {
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: url
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-07-24 01:39:14 +00:00
|
|
|
|
|
|
|
|
|
|
// 应用初始化
|
|
|
|
|
|
onLaunch(() => {
|
|
|
|
|
|
console.log('初始化------')
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-18 09:26:18 +00:00
|
|
|
|
/***-------------------------------开始数据处理------------------------**/
|
|
|
|
|
|
const getmqttdata = async () => {
|
|
|
|
|
|
await getMqttPushClient().then(res => {
|
|
|
|
|
|
console.log("连接mqtt数据服务器----0000000----", res)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
//获取房间信息
|
|
|
|
|
|
const getofficehomelist = async () => {
|
|
|
|
|
|
await gethomelist().then((res) => {
|
|
|
|
|
|
if (res.success) {
|
|
|
|
|
|
homelist.value = res.result.map((item, index) => ({
|
|
|
|
|
|
...item, // 保留原有字段
|
|
|
|
|
|
homezt: 0, // 添加homezt字段,默认为0
|
|
|
|
|
|
}));
|
|
|
|
|
|
//添加楼层情况
|
|
|
|
|
|
}
|
|
|
|
|
|
}).catch((err) => {
|
|
|
|
|
|
console.log(err);
|
|
|
|
|
|
});
|
|
|
|
|
|
filteredFloors.value = groupByFloor(homelist)
|
|
|
|
|
|
|
|
|
|
|
|
console.log("33333333333333-------", filteredFloors.value)
|
|
|
|
|
|
getAllswitchByids();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 数据分组处理
|
|
|
|
|
|
const groupByFloor = (data) => {
|
|
|
|
|
|
console.log("data---", data)
|
|
|
|
|
|
const groups = data.value.reduce((acc, cur) => {
|
|
|
|
|
|
const floorKey = cur.wlwbmcode.slice(-2) // 根据实际字段调整
|
|
|
|
|
|
if (!acc[floorKey]) {
|
|
|
|
|
|
acc[floorKey] = {
|
|
|
|
|
|
level: floorKey,
|
|
|
|
|
|
rooms: []
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
acc[floorKey].rooms.push(cur)
|
|
|
|
|
|
return acc
|
|
|
|
|
|
}, {})
|
|
|
|
|
|
|
|
|
|
|
|
return Object.values(groups).sort((a, b) => a.level - b.level)
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 操作开关
|
|
|
|
|
|
*
|
|
|
|
|
|
*/
|
|
|
|
|
|
const getAllswitchByids = async () => {
|
|
|
|
|
|
//查询开关状态
|
|
|
|
|
|
for (const item of filteredFloors.value) {
|
|
|
|
|
|
for (const item2 of item.rooms) {
|
|
|
|
|
|
let fjkzbm = await getfjkzbm(item2)
|
|
|
|
|
|
if (fjkzbm) {
|
|
|
|
|
|
await sleep(1000);
|
|
|
|
|
|
let device = await foreachhomedata(fjkzbm);
|
|
|
|
|
|
item2.homezt = device.key2 // 使用Vue.set确保响应式,不需要 $set
|
|
|
|
|
|
console.log("device----房间号-" + item.homename + "---数据---", device.key2)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
item2.homezt = device.key2 // 使用Vue.set确保响应式
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const getfjkzbm = async (item) => {
|
|
|
|
|
|
// console.log("5555----------",item.id)
|
|
|
|
|
|
let fjkzbm = {};
|
|
|
|
|
|
//查询房间控制编码
|
|
|
|
|
|
await selectfjkzbmforfjid({
|
|
|
|
|
|
fjbid: item.id
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res.result.length == 1) {
|
|
|
|
|
|
fjkzbm = res.result[0]
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
return fjkzbm
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const foreachhomedata = async (fjkzbm) => {
|
|
|
|
|
|
let device = {}; // 在方法内部定义 device
|
|
|
|
|
|
const res = await createdSwitch({ // 直接 await 而不是用 .then
|
|
|
|
|
|
topic: 's' + fjkzbm.sbkzbm,
|
|
|
|
|
|
qos: 0,
|
|
|
|
|
|
pushMessage: fjkzbm.kgzt
|
|
|
|
|
|
})
|
|
|
|
|
|
if (res) {
|
|
|
|
|
|
device = JSON.parse(res.message)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log("错误房间号--" + fjkzbm + "----")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return device
|
|
|
|
|
|
}
|
|
|
|
|
|
const cleanreset = () => {
|
|
|
|
|
|
filteredFloors.value = []
|
|
|
|
|
|
loadtree();
|
|
|
|
|
|
}
|
|
|
|
|
|
//--------树状表展示方法--------
|
|
|
|
|
|
// 测试查询
|
|
|
|
|
|
const loadtree = () => {
|
|
|
|
|
|
listAllRegions().then((res) => {
|
|
|
|
|
|
data.value = res.result
|
|
|
|
|
|
typeData.value = [data.value.map(item => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
value: item.id,
|
|
|
|
|
|
label: item.name
|
|
|
|
|
|
}
|
|
|
|
|
|
})]
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleConfirm({
|
|
|
|
|
|
value
|
|
|
|
|
|
}) {
|
|
|
|
|
|
// console.log("点击查询-----",value)
|
|
|
|
|
|
queryRoomsByDepartments(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
const displayFormat = (selectedItems) => {
|
|
|
|
|
|
if (selectedItems.length > 0) {
|
|
|
|
|
|
return selectedItems[selectedItems.length - 1].label
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const columnChange = ({
|
|
|
|
|
|
selectedItem,
|
|
|
|
|
|
resolve,
|
|
|
|
|
|
finish
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
// console.log("selectedItem---------",selectedItem.value)
|
|
|
|
|
|
const areaData = findChildren(data.value, selectedItem.value)
|
|
|
|
|
|
if (areaData && areaData.length) {
|
|
|
|
|
|
resolve(
|
|
|
|
|
|
areaData.map((item) => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
value: item.id,
|
|
|
|
|
|
label: item.name
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
finish()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const findChildren = (data, code) => {
|
|
|
|
|
|
if (!code) {
|
|
|
|
|
|
return data
|
|
|
|
|
|
}
|
|
|
|
|
|
for (const item of data) {
|
|
|
|
|
|
// console.log("item---",item)
|
|
|
|
|
|
// console.log("item--code-",code)
|
|
|
|
|
|
if (item.id === code) {
|
|
|
|
|
|
return item.children || null
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.children) {
|
|
|
|
|
|
const childrenResult = findChildren(item.children, code)
|
|
|
|
|
|
if (childrenResult) {
|
|
|
|
|
|
return childrenResult
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null
|
|
|
|
|
|
}
|
|
|
|
|
|
// 根据部门ID查询房间
|
|
|
|
|
|
const queryRoomsByDepartments = async (departmentIds) => {
|
|
|
|
|
|
console.log("departmentIds-----------", departmentIds)
|
|
|
|
|
|
const lastId = departmentIds[departmentIds.length - 1]
|
|
|
|
|
|
console.log("Processing last ID:", lastId)
|
|
|
|
|
|
// //在这块添加查询方法
|
|
|
|
|
|
const res = await Selecthomelist({
|
|
|
|
|
|
id: lastId
|
|
|
|
|
|
})
|
|
|
|
|
|
if (res.success) {
|
|
|
|
|
|
selectBydata.value = res.result;
|
|
|
|
|
|
console.log("selectBydata.value:", selectBydata.value)
|
|
|
|
|
|
filteredFloors.value = groupByFloor(selectBydata)
|
2025-07-24 01:39:14 +00:00
|
|
|
|
// console.log("数据分组-555---", filteredFloors.value[0].rooms)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
//分组完进行房间状态查询,张祥瑞
|
|
|
|
|
|
getAllswitchByids()
|
2025-07-24 01:39:14 +00:00
|
|
|
|
|
2025-07-18 09:26:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//----------------树状展示end-----------
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------以上为数据处理---end-------------
|
|
|
|
|
|
//处理返回的消息
|
|
|
|
|
|
const handlesocketMessage = (jsonString) => {
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log("1300--666666666666666---", jsonString)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
try {
|
|
|
|
|
|
const messageObj = JSON.parse(jsonString);
|
|
|
|
|
|
|
|
|
|
|
|
// 提取嵌套的content字段
|
|
|
|
|
|
if (messageObj.content) {
|
|
|
|
|
|
const device = JSON.parse(messageObj.content);
|
|
|
|
|
|
updatafjzt(messageObj.fjid, device);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('解析消息出错:', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const updatafjzt = (fjid, device) => {
|
|
|
|
|
|
filteredFloors.value = filteredFloors.value.map(floor => ({
|
|
|
|
|
|
...floor,
|
|
|
|
|
|
rooms: floor.rooms.map(room => room.id === fjid ? {
|
|
|
|
|
|
...room,
|
|
|
|
|
|
homezt: device.key2
|
|
|
|
|
|
} :
|
|
|
|
|
|
room
|
|
|
|
|
|
)
|
|
|
|
|
|
}));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-07-24 01:39:14 +00:00
|
|
|
|
//------------------------以下为websocket-----------
|
|
|
|
|
|
const WS_URL = 'wss://szcx.zyyt.sinopec.com/mqttprod/ws/simple';
|
|
|
|
|
|
// const WS_URL = 'ws://10.75.15.246:8899/mqttprod/ws/simple';
|
2025-07-18 09:26:18 +00:00
|
|
|
|
const connectionStatus = ref('未连接');
|
2025-07-24 01:39:14 +00:00
|
|
|
|
|
2025-07-18 09:26:18 +00:00
|
|
|
|
// STOMP帧构建器
|
|
|
|
|
|
const buildStompFrame = (command, headers = {}, body = '') => {
|
|
|
|
|
|
let frame = `${command}\n`;
|
|
|
|
|
|
for (const [key, value] of Object.entries(headers)) {
|
|
|
|
|
|
frame += `${key}:${value}\n`;
|
|
|
|
|
|
}
|
|
|
|
|
|
frame += `\n${body}`;
|
|
|
|
|
|
return frame + '\x00';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 连接WebSocket
|
|
|
|
|
|
const connectWebSocket = () => {
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log(123123)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
if (connected.value) return;
|
|
|
|
|
|
|
|
|
|
|
|
connectionStatus.value = '连接中...';
|
|
|
|
|
|
|
|
|
|
|
|
if (socketTask) {
|
|
|
|
|
|
socketTask.close({});
|
|
|
|
|
|
socketTask = null;
|
|
|
|
|
|
}
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log(44444444)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
|
|
|
|
|
|
socketTask = uni.connectSocket({
|
|
|
|
|
|
url: WS_URL,
|
2025-07-24 01:39:14 +00:00
|
|
|
|
protocols: ['v12.stomp', 'v11.stomp'],
|
2025-07-18 09:26:18 +00:00
|
|
|
|
success: () => {
|
|
|
|
|
|
console.log('开始连接WebSocket');
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('连接失败:', err);
|
|
|
|
|
|
connectionStatus.value = '连接失败';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log(55555555555)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
uni.onSocketOpen((res) => {
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log(66666666)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
console.log('WebSocket连接已打开', res);
|
|
|
|
|
|
connected.value = true;
|
2025-07-24 01:39:14 +00:00
|
|
|
|
connectionStatus.value = '连接中...';
|
2025-07-18 09:26:18 +00:00
|
|
|
|
|
|
|
|
|
|
// 发送STOMP CONNECT帧
|
|
|
|
|
|
const connectFrame = buildStompFrame('CONNECT', {
|
|
|
|
|
|
'accept-version': '1.2',
|
|
|
|
|
|
'heart-beat': '10000,10000'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
uni.sendSocketMessage({
|
2025-07-24 01:39:14 +00:00
|
|
|
|
data: connectFrame
|
2025-07-18 09:26:18 +00:00
|
|
|
|
});
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log("77777777777")
|
2025-07-18 09:26:18 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听消息
|
|
|
|
|
|
socketTask.onMessage((res) => {
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log("8888888888888888888")
|
2025-07-18 09:26:18 +00:00
|
|
|
|
const data = res.data;
|
|
|
|
|
|
const [commandLine, ...headerLines] = data.split('\n');
|
|
|
|
|
|
const emptyLineIndex = headerLines.findIndex(line => line === '');
|
|
|
|
|
|
const headers = {};
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < emptyLineIndex; i++) {
|
|
|
|
|
|
const [key, value] = headerLines[i].split(':');
|
|
|
|
|
|
headers[key] = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const body = headerLines.slice(emptyLineIndex + 1).join('\n').replace(/\x00$/, '');
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log("999999999999999", res)
|
|
|
|
|
|
console.log("121212121212", commandLine)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
switch (commandLine) {
|
|
|
|
|
|
case 'CONNECTED':
|
|
|
|
|
|
connectionStatus.value = 'STOMP已连接';
|
|
|
|
|
|
// 订阅主题
|
|
|
|
|
|
const subscribeFrame = buildStompFrame('SUBSCRIBE', {
|
|
|
|
|
|
id: 'sub-0',
|
|
|
|
|
|
destination: '/topic/messages'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
socketTask.send({
|
2025-07-24 01:39:14 +00:00
|
|
|
|
data: subscribeFrame
|
2025-07-18 09:26:18 +00:00
|
|
|
|
});
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'MESSAGE':
|
|
|
|
|
|
handlesocketMessage(body);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'ERROR':
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.error('服务器错误:', body);
|
2025-07-18 09:26:18 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听错误
|
|
|
|
|
|
uni.onSocketError((err) => {
|
|
|
|
|
|
console.error('WebSocket错误:', err);
|
|
|
|
|
|
connectionStatus.value = '连接错误';
|
|
|
|
|
|
connected.value = false;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听关闭
|
|
|
|
|
|
uni.onSocketClose((closeRes) => {
|
|
|
|
|
|
console.log('WebSocket连接已关闭', closeRes);
|
|
|
|
|
|
connectionStatus.value = '已断开';
|
|
|
|
|
|
connected.value = false;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送消息
|
|
|
|
|
|
const sendMessage = () => {
|
|
|
|
|
|
if (!message.value.trim()) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '消息不能为空',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建STOMP SEND帧
|
|
|
|
|
|
const sendFrame = buildStompFrame('SEND', {
|
|
|
|
|
|
destination: '/app/chat',
|
|
|
|
|
|
'content-type': 'text/plain'
|
|
|
|
|
|
}, message.value);
|
|
|
|
|
|
|
|
|
|
|
|
socketTask.send({
|
|
|
|
|
|
data: sendFrame,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
message.value = '';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-07-24 01:39:14 +00:00
|
|
|
|
// 断开WebSocket
|
2025-07-18 09:26:18 +00:00
|
|
|
|
const disconnectWebSocket = () => {
|
|
|
|
|
|
if (socketTask) {
|
|
|
|
|
|
// 发送STOMP DISCONNECT帧
|
|
|
|
|
|
const disconnectFrame = buildStompFrame('DISCONNECT', {
|
|
|
|
|
|
receipt: 'disconnect-receipt'
|
|
|
|
|
|
});
|
2025-07-24 01:39:14 +00:00
|
|
|
|
console.log(socketTask)
|
2025-07-18 09:26:18 +00:00
|
|
|
|
socketTask.send({
|
|
|
|
|
|
data: disconnectFrame,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
socketTask.close({
|
|
|
|
|
|
code: 1000,
|
|
|
|
|
|
reason: '用户手动关闭',
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
connected.value = false;
|
|
|
|
|
|
connectionStatus.value = '已断开';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
2025-07-24 01:39:14 +00:00
|
|
|
|
// disconnectWebSocket();
|
2025-07-18 09:26:18 +00:00
|
|
|
|
loadtree();
|
|
|
|
|
|
connectWebSocket();
|
|
|
|
|
|
getmqttdata();
|
|
|
|
|
|
// getofficehomelist();
|
|
|
|
|
|
})
|
|
|
|
|
|
onUnload(() => {
|
|
|
|
|
|
disconnectWebSocket();
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
/* 基础样式重置 */
|
|
|
|
|
|
* {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.page-container {
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
max-width: 750rpx;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 楼层容器 */
|
|
|
|
|
|
.floor-wrapper {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
/* 移除 flex-direction: column,使用默认的 row,但实际楼层是纵向排列的,这里可能需要恢复 column,否则楼层会横向排列 */
|
|
|
|
|
|
gap: 30rpx;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
|
/* 可选:给整体加边距,避免贴边 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.floor-section {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
/* background-color: #fff; */
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
/* box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 移除原有的.room-grid样式,替换为以下 */
|
|
|
|
|
|
.room-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
/* 每列占50%宽度,减去间距的一半(避免总宽度超100%) */
|
|
|
|
|
|
grid-template-columns: repeat(2, calc(50% - 10rpx));
|
|
|
|
|
|
/* 假设间距20rpx,每列减10rpx */
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
/* 列之间的间距 */
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
/* 确保padding不增加总宽度 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 房间卡片样式优化 */
|
|
|
|
|
|
.room-card {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
/* 强制卡片占满列宽(50% - 10rpx) */
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
padding: 25rpx;
|
|
|
|
|
|
min-height: 140rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.room-card.room-active {
|
|
|
|
|
|
background-color: #e6f7ee;
|
|
|
|
|
|
border-color: #b7eb8f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.room-card:active {
|
|
|
|
|
|
transform: scale(0.98);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 房间号样式 */
|
|
|
|
|
|
.room-number {
|
|
|
|
|
|
font-size: 34rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 15rpx;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 房间信息样式 */
|
|
|
|
|
|
.room-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-label {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-value {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 响应式布局调整 */
|
|
|
|
|
|
@media (max-width: 375px) {
|
|
|
|
|
|
.room-grid {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 以下为websocket连接样式 */
|
|
|
|
|
|
.connection-section {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.connect-btn,
|
|
|
|
|
|
.disconnect-btn {
|
|
|
|
|
|
width: 300rpx;
|
|
|
|
|
|
height: 80rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
margin-right: 20rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.connect-btn {
|
|
|
|
|
|
background-color: #2ecc71;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.disconnect-btn {
|
|
|
|
|
|
background-color: #e74c3c;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.connected {
|
|
|
|
|
|
color: #27ae60;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.disconnected {
|
|
|
|
|
|
color: #e74c3c;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.input-section {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.input {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 90rpx;
|
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
|
border: 1rpx solid #ddd;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.send-btn {
|
|
|
|
|
|
width: 160rpx;
|
|
|
|
|
|
height: 90rpx;
|
|
|
|
|
|
margin-left: 20rpx;
|
|
|
|
|
|
background-color: #3498db;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.send-btn:disabled {
|
|
|
|
|
|
background-color: #bdc3c7;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-container {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.subtitle {
|
|
|
|
|
|
font-size: 34rpx;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-list {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
padding: 10rpx;
|
|
|
|
|
|
background-color: #f9f9f9;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
max-height: 60vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-item {
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
border-bottom: 1rpx solid #eee;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
margin-bottom: 10rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-item.sent {
|
|
|
|
|
|
background-color: #e3f2fd;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-item.received {
|
|
|
|
|
|
background-color: #e8f5e9;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-item.system {
|
|
|
|
|
|
background-color: #fffde7;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-item.error {
|
|
|
|
|
|
background-color: #ffebee;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-content {
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
margin-bottom: 10rpx;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message-time {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #7f8c8d;
|
|
|
|
|
|
align-self: flex-end;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|