| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588 |
- <template>
- <view class="home-warpTwo">
- <view class="header_two">
- <view class="radar-box">
- <view
- :style="{
- width: `${rotatedRect.width}rpx`,
- height: `${rotatedRect.height}rpx`,
- position: 'absolute',
- top: `${rotatedRect.top - 8}rpx`,
- left: `${rotatedRect.left - 8}rpx`,
- border: `4px solid #333333`,
- }"
- class="tranStyle"
- >
- </view>
- <view
- catchtouchmove="true"
- v-for="(item, index) in modules"
- :key="index"
- class="moduleContent"
- >
- <view
- :class="item.type"
- :style="{
- width: `${item.width}rpx`,
- height: `${item.height}rpx`,
- top: `${item.top}rpx`,
- left: `${item.left}rpx`,
- transform: `rotate(${item.rotate}deg)`,
- 'transform-origin': 'center center',
- }"
- @touchmove.prevent="onTouchMove(index, $event)"
- @touchstart="onTouchStart(index, $event)"
- @touchend="onTouchEnd(index, $event)"
- >
- <image
- class="module-img"
- :src="`../../static/furnitures/${item.type}.png`"
- mode=""
- />
- </view>
- </view>
- <template>
- <image
- v-for="item in targetPoints"
- :key="item.id"
- class="action-icon-M"
- :src="`../../static/${lnbAction}.png`"
- :style="{
- position: 'absolute',
- transform: `translate(-50%, -50%) translate3d(${item.displayX}rpx, ${item.displayY}rpx, 0)`,
- transition: 'transform 1s linear',
- willChange: 'transform',
- zIndex: 9999,
- width: '50rpx',
- height: '50rpx',
- }"
- />
- </template>
- <image
- class="redar-pic"
- src="../../static/rander.png"
- mode=""
- />
- </view>
- <view class="airbody">
- <view class="header_top">
- <view class="airTitle">室内布置</view>
- <view class="addfnt" @click="showAddFt">
- <image src="../../static/addfnt.png" alt=""> </image
- ><view class="add_btn">添加</view></view
- >
- </view>
- <view class="module">
- <view class="device-bottom">
- <view v-if="modules.length == 0" class="no-data">
- 请先点击添加,添加家具
- </view>
- <view
- class="info-box"
- v-for="(item, index) in modules"
- :key="index"
- >
- <image
- :src="`../../static/furnitures/${item.type}.png`"
- mode=""
- />
- <view class="info-text">
- <text>{{ item.name }}</text>
- <text
- >({{ item.width }}*{{
- item.height
- }})cm</text
- >
- </view>
- <view class="edit_del">
- <image
- @click="deleteItem(index)"
- src="../../static/delete.png"
- alt=""
- ></image>
- <image
- @click="editItem(index)"
- style="margin-left: 10rpx"
- src="../../static/edit.png"
- alt=""
- ></image>
- </view>
- </view>
- </view>
- </view>
- </view>
- <view class="bottomTwo" @click="saveRoom">
- <view class="previousTip">保存</view>
- </view>
- </view>
- <!-- 选择家具弹窗 -->
- <view>
- <!-- 底部弹窗 -->
- <view class="bottom-modal" v-if="addfntShow">
- <!-- 遮罩层 -->
- <view class="modal-mask" @click="addfntShow = false"></view>
- <!-- 弹窗内容 -->
- <view class="modal-container">
- <view class="modal-header">
- <text class="header-title">选择家具</text>
- </view>
- <view class="modal-content">
- <view class="device-bottom">
- <view
- class="item-box"
- v-for="(item, index) in selectfntLists"
- :key="index"
- @click="generate(item.type)"
- >
- <image
- :src="`../../static/furnitures/${item.type}.png`"
- mode=""
- />
- <text
- >{{ item.name }}({{ item.width }}*{{
- item.length
- }})</text
- >
- </view>
- </view>
- </view>
- <view class="modal-footer">
- <button
- class="footer-btn cancel"
- @click="addfntShow = false"
- >
- 取消
- </button>
- <button
- class="footer-btn confirm"
- @click="addfntShow = false"
- >
- 确定
- </button>
- </view>
- </view>
- </view>
- </view>
- <!-- 编辑家具弹窗 -->
- <view class="device_control" v-if="editfntShow">
- <view class="control_info">
- <view class="control_left">
- <image
- :src="`../../static/furnitures/${selectImg}.png`"
- class="image_class"
- ></image>
- </view>
- <view class="control_right">
- <view class="control_right_top">
- <view class="title">长(cm)</view>
- <input
- type="number"
- v-model="selectWidth"
- placeholder="请输入长"
- @blur="changeSize"
- />
- </view>
- <view class="control_right_bottom">
- <view class="title">宽(cm)</view>
- <input
- type="number"
- v-model="selectHeight"
- placeholder="请输入宽"
- @blur="changeSize"
- />
- </view>
- </view>
- </view>
- <view class="control_operat" v-if="editfntShow">
- <view class="operat_left">
- <view class="top">
- <image
- src="../../static/btn_top.png"
- mode="aspectFit"
- @click="movefut(0, -10)"
- ></image>
- </view>
- <view class="middle">
- <image
- src="../../static/btn_left.png"
- mode="aspectFit"
- @click="movefut(-10, 0)"
- ></image>
- <image
- src="../../static/btn_right.png"
- mode="aspectFit"
- @click="movefut(10, 0)"
- ></image>
- </view>
- <view class="bottom">
- <image
- src="../../static/btn_bot.png"
- mode="aspectFit"
- @click="movefut(0, 10)"
- ></image>
- </view>
- </view>
- <view class="operat_right">
- <view class="rotate">
- <view class="rotate_left" @click="rotatefut(-90)">
- <image src="../../static/rote_left.png"></image>
- </view>
- <view class="rotate_rigt" @click="rotatefut(90)">
- <image src="../../static/rote_right.png"></image>
- </view>
- </view>
- <view class="del_funit" @click="editfntShow = false"
- >完成</view
- >
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import MqttService from "../../utils/globalMqtt.js";
- import {
- convert_region_r2c,
- rotateRect_cw,
- convert_furniture_r2c,
- rotateRect_ccw,
- convert_region_c2r,
- convert_point_r2c,
- } from "../../utils/changezb.js";
- export default {
- name: "my",
- data() {
- return {
- // 设备参数
- deviceWidth: 400,
- deviceHeight: 500,
- modules: [],
- width: 0,
- length: 0,
- selectedIndex: 0,
- selectIndex: 0,
- controlOptions: [],
- startX: 0, // 记录触摸开始时的X坐标
- startY: 0, // 记录触摸开始时的Y坐标
- draggingIndex: null, // 记录当前正在拖动的模块的索引
- selectedItem: [],
- rotateShow: false,
- selectRotate: "",
- selectedRotate: "",
- softWare: "",
- xOffset: 0,
- yOffset: 0,
- angle: 0,
- xxStart: "",
- xxEnd: "",
- yyStart: "",
- yyEnd: "",
- // 控制部分参数
- selectImg: "setting",
- selectWidth: "",
- selectHeight: "",
- addfntShow: false,
- editfntShow: false,
- selectfntLists: [
- {
- name: "床",
- type: "bed",
- width: 80,
- length: 70,
- },
- {
- name: "柜子",
- type: "bed_cabinet",
- width: 40,
- length: 80,
- },
- {
- name: "化妆椅",
- type: "bed_dressing_chair",
- width: 40,
- length: 40,
- },
- {
- name: "化妆镜",
- type: "bed_dressing_mirror",
- width: 40,
- length: 80,
- },
- {
- name: "床头柜",
- type: "bed_table",
- width: 40,
- length: 40,
- },
- {
- name: "脸盆",
- type: "bath_basin",
- width: 40,
- length: 80,
- },
- {
- name: "门",
- type: "bath_door",
- width: 40,
- length: 40,
- },
- {
- name: "淋浴",
- type: "bath_shower",
- width: 40,
- length: 60,
- },
- {
- name: "马桶",
- type: "bath_toilet",
- width: 40,
- length: 40,
- },
- {
- name: "餐桌(方形)",
- type: "dining_table_rect",
- width: 40,
- length: 40,
- },
- {
- name: "餐桌",
- type: "dining_table",
- width: 40,
- length: 80,
- },
- {
- name: "餐椅",
- type: "dining_chair",
- width: 40,
- length: 80,
- },
- {
- name: "冰箱",
- type: "dining_fridge",
- width: 40,
- length: 80,
- },
- {
- name: "书柜",
- type: "living_bookcase",
- width: 40,
- length: 80,
- },
- {
- name: "沙发",
- type: "living_sofa",
- width: 40,
- length: 80,
- },
- {
- name: "茶几",
- type: "living_tea_table",
- width: 40,
- length: 80,
- },
- {
- name: "电视柜",
- type: "living_tv_stand",
- width: 40,
- length: 80,
- },
- {
- name: "单人沙发",
- type: "living_sofa_single",
- width: 40,
- length: 40,
- },
- ],
- lnbAction: "action8",
- // mqtt模块
- targetPoints: {},
- inactivityTimer: null,
- left: 0,
- top: 0,
- clientIdProp: null,
- clientId: null,
- // 重新计算雷达坐标位置
- x_radar: 300,
- y_radar: 300,
- rotatedRect: {},
- // 处理点位
- point: "",
- };
- },
- computed: {},
- methods: {
- onTouchMove(index, event) {
- if (this.draggingIndex === null) return;
- event.preventDefault && event.preventDefault();
- event.stopPropagation && event.stopPropagation();
- const { modules, startX, startY } = this;
- const currentX = event.touches[0].clientX;
- const currentY = event.touches[0].clientY;
- const deltaX = Math.round(currentX - startX);
- const deltaY = Math.round(currentY - startY);
- // let x = Math.round(
- // this.xxStart + event.currentTarget.offsetLeft * 2
- // );
- // let y = Math.round(this.yyEnd - event.currentTarget.offsetTop * 2);
- // 创建新数组避免直接修改原数组
- const updatedModules = [...this.modules];
- updatedModules[this.draggingIndex] = {
- ...updatedModules[this.draggingIndex],
- left: Math.round(
- updatedModules[this.draggingIndex].left + deltaX
- ),
- top: Math.round(
- updatedModules[this.draggingIndex].top + deltaY
- ),
- // x,
- // y,
- };
- // Vue 的响应式更新
- this.modules = updatedModules;
- this.startX = currentX;
- this.startY = currentY;
- },
- onTouchStart(index, event) {
- const selectedItem = this.modules[index];
- const selectedItemWidth = selectedItem.width / 40;
- const selectedItemHeight = selectedItem.height / 40;
- this.draggingIndex = index;
- this.selectedIndex = index;
- this.startX = event.touches[0].clientX;
- this.startY = event.touches[0].clientY;
- this.selectedItem = selectedItem;
- this.selectedItemWidth = selectedItemWidth;
- this.selectedItemHeight = selectedItemHeight;
- this.selectImg = this.modules[index].type;
- this.selectWidth = this.modules[index].width;
- this.selectHeight = this.modules[index].height;
- },
- onTouchEnd(index, event) {
- // this.draggingIndex = null;
- },
- generate(featuriesType) {
- let component = {
- name: "",
- type: featuriesType,
- width: 0,
- length: 0,
- top: this.y_radar,
- left: this.x_radar,
- rotate: 0,
- };
- switch (featuriesType) {
- case "bed":
- component.width = 80;
- component.length = 120;
- component.height = 120;
- component.name = "床";
- break;
- case "bed_cabinet":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "柜子";
- break;
- case "bed_dressing_chair":
- component.width = 40;
- component.length = 40;
- component.height = 40;
- component.name = "化妆椅";
- break;
- case "bed_dressing_mirror":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "化妆镜";
- break;
- case "bed_table":
- component.width = 40;
- component.length = 40;
- component.height = 40;
- component.name = "床头柜";
- break;
- case "bath_basin":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "脸盆";
- break;
- case "bath_door":
- component.width = 40;
- component.length = 40;
- component.height = 40;
- component.name = "门";
- break;
- case "bath_shower":
- component.width = 40;
- component.length = 60;
- component.height = 60;
- component.name = "淋浴";
- break;
- case "bath_toilet":
- component.width = 40;
- component.length = 40;
- component.height = 40;
- component.name = "马桶";
- break;
- case "dining_table_rect":
- component.width = 40;
- component.length = 40;
- component.height = 40;
- component.name = "餐桌(方形)";
- break;
- case "dining_table":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "餐桌";
- break;
- case "dining_chair":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "餐椅";
- break;
- case "dining_fridge":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "冰箱";
- break;
- case "living_bookcase":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "书柜";
- break;
- case "living_sofa":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "沙发";
- break;
- case "living_tea_table":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "茶几";
- break;
- case "living_tv_stand":
- component.width = 40;
- component.length = 80;
- component.height = 80;
- component.name = "电视柜";
- break;
- case "living_sofa_single":
- component.width = 40;
- component.length = 40;
- component.height = 40;
- component.name = "单人沙发";
- break;
- default:
- break;
- }
- component.type = featuriesType;
- if (component !== null) {
- this.modules.push(component);
- }
- },
- // 输入宽高改变家具大小
- changeSize() {
- if (this.selectHeight <= 0 || this.selectWidth <= 0) {
- this.selectHeight = this.modules[this.draggingIndex].length;
- this.selectWidth = this.modules[this.draggingIndex].width;
- return this.showModal("提示", "家具长宽不能小于0");
- }
- this.modules[this.draggingIndex].length = this.selectHeight;
- this.modules[this.draggingIndex].height = this.selectHeight;
- this.modules[this.draggingIndex].width = this.selectWidth;
- },
- movefut(left, top) {
- this.modules[this.draggingIndex].left =
- this.modules[this.draggingIndex].left + left;
- this.modules[this.draggingIndex].top =
- this.modules[this.draggingIndex].top + top;
- },
- rotatefut(rotate) {
- let item = this.modules[this.draggingIndex];
- if (item.rotate == 0) {
- item.rotate = 360;
- }
- let currentRotate = item.rotate || 0;
- let newAngle = (currentRotate + rotate) % 360;
- this.modules[this.draggingIndex].rotate = newAngle;
- },
- deleteItem(index) {
- this.draggingIndex = index;
- if (this.draggingIndex === null) {
- return this.showModal("提示", "请先选择家具");
- }
- this.showModal("提示", "是否确认删除该家具", (res) => {
- if (res.confirm) {
- this.modules.splice(this.draggingIndex, 1);
- this.draggingIndex = null;
- }
- });
- },
- editItem(index) {
- this.draggingIndex = index;
- this.editfntShow = true;
- const selectedItem = this.modules[index];
- const selectedItemWidth = selectedItem.width / 40;
- const selectedItemHeight = selectedItem.height / 40;
- this.draggingIndex = index;
- this.selectedIndex = index;
- this.selectedItem = selectedItem;
- this.selectedItemWidth = selectedItemWidth;
- this.selectedItemHeight = selectedItemHeight;
- this.selectImg = this.modules[index].type;
- this.selectWidth = this.modules[index].width;
- this.selectHeight = this.modules[index].height;
- },
- // 提取公共的模态框方法
- showModal(title, content, confirmCallback) {
- wx.showModal({
- title,
- content,
- success: (res) => {
- if (res.confirm && confirmCallback) {
- confirmCallback(res);
- }
- },
- });
- },
- saveRoom() {
- const pRadar = {
- x: this.x_radar,
- y: this.y_radar,
- angle: uni.getStorageSync("northAngle"),
- mountPlain: "wall",
- };
- console.log(this.modules, pRadar, "下发之前");
- let copyModule = JSON.parse(JSON.stringify(this.modules));
- copyModule.forEach((item) => {
- item.length = item.height;
- const rect = rotateRect_ccw(item, pRadar, pRadar.angle);
- const rotatedRect = convert_region_c2r(rect, pRadar);
- item.width = item.width;
- item.length = item.length;
- item.name = item.name;
- item.type = item.type;
- item.rotate = item.rotate || 0;
- item.x = rotatedRect.x_cm_start;
- item.y = rotatedRect.y_cm_stop;
- });
- for (const item of copyModule) {
- if (
- item.top < 0 ||
- item.left < 0 ||
- item.top + (item.length - 0) > 600 ||
- item.left + (item.width - 0) > 600
- ) {
- uni.showToast({
- title: `${item.name}超出画布区域,请调整位置后再保存`,
- icon: "none",
- duration: 1500,
- });
- return; // 这里能真正退出整个函数
- }
- }
- this.$http
- .post(
- "wap/room/saveRoom",
- JSON.stringify({
- devId: this.devId,
- furnitures: copyModule,
- }),
- {
- header: {
- "Content-Type": "application/json;charset=UTF-8",
- },
- }
- )
- .then((res) => {
- if (res.data.code == 200) {
- uni.showToast({
- title: "保存成功",
- icon: "success",
- duration: 1500,
- });
- setTimeout(() => {
- uni.navigateBack({
- delta: 1,
- });
- }, 1500);
- } else {
- uni.showToast({
- title: res.data.msg,
- icon: "none",
- duration: 1500,
- });
- }
- })
- .catch((err) => {});
- },
- showAddFt() {
- this.addfntShow = true;
- },
- getdevInfo(devId) {
- this.$http
- .get(`wap/device/queryDeviceInfoById`, {
- devId: devId,
- })
- .then((res) => {
- if (res.data.data) {
- this.devInfo = res.data.data;
- this.width = Math.abs(
- this.devInfo.yyEnd - this.devInfo.yyStart
- );
- this.length = Math.abs(
- this.devInfo.xxEnd - this.devInfo.xxStart
- );
- this.calculateRegion();
- this.statusLight = this.devInfo.statusLight;
- this.xxStart = this.devInfo.xxStart;
- this.xxEnd = this.devInfo.xxEnd;
- this.yyStart = this.devInfo.yyStart;
- this.yyEnd = this.devInfo.yyEnd;
- } else {
- uni.showToast({
- title: res.data.message,
- icon: "none",
- });
- }
- })
- .catch((err) => {
- console.log(err, 8888);
- });
- },
- // 计算检测区域问题
- calculateRegion() {
- let x_cm_start = this.devInfo.xxStart;
- let y_cm_start = this.devInfo.yyStart;
- let x_cm_stop = this.devInfo.xxEnd;
- let y_cm_stop = this.devInfo.yyEnd;
- const trackingRegion = {
- x_cm_start,
- y_cm_start,
- x_cm_stop,
- y_cm_stop,
- };
- const pRadar = {
- x: this.x_radar,
- y: this.y_radar,
- angle: uni.getStorageSync("northAngle"),
- mountPlain: this.devInfo.mountPlain,
- };
- const rect = convert_region_r2c(trackingRegion, pRadar);
- this.rotatedRect = rotateRect_cw(rect, pRadar, pRadar.angle);
- console.log(this.rotatedRect, "rotatedRect");
- },
- getRoomInfo(devId) {
- const pRadar = {
- x: this.x_radar,
- y: this.y_radar,
- angle: uni.getStorageSync("northAngle"),
- mountPlain: "wall",
- };
- this.$http
- .get(`wap/room/readRoom`, {
- devId: devId,
- })
- .then((res) => {
- if (res.data.data) {
- this.modules = res.data.data.furnitures;
- }
- console.log(this.modules, 88888);
- this.modules.forEach((item) => {
- const rect = convert_furniture_r2c(item, pRadar);
- const rotatedRect = rotateRect_cw(
- rect,
- pRadar,
- pRadar.angle
- );
- item.left = rotatedRect.left;
- item.top = rotatedRect.top;
- item.width = rotatedRect.width;
- item.height = rotatedRect.height;
- item.name = item.name;
- item.type = item.type;
- item.rotate = item.rotate;
- });
- console.log(this.modules, 99999);
- });
- },
- handleMessage(topic, message, clientId) {
- // 清除不活动定时器
- clearTimeout(this.inactivityTimer);
- this.inactivityTimer = setTimeout(() => {
- this.targetPoints = {};
- // console.log("长时间没有点位消除");
- }, 1500);
- // 验证topic格式
- const match = topic.match(/^\/dev\/(.+)\/tracker_targets$/);
- if (!match || match[1] !== clientId) return;
- try {
- const data = JSON.parse(message.toString());
- // if (data.health) {
- // if (
- // data.health.breath_rpm ||
- // data.health.breath_rpm === 0
- // ) {
- // this.receptHealth(Math.floor(data.health.breath_rpm));
- // } else {
- // }
- // }
- // console.log(data.tracker_targets, "MQTT消息解析成功22222");
- this.processTrackerData(data.tracker_targets);
- } catch (e) {
- console.error("MQTT消息解析失败", e);
- }
- },
- processTrackerData(arr) {
- if (Array.isArray(arr) && arr.length > 0 && Array.isArray(arr[0])) {
- this.targetPoints = {};
- const currentIds = new Set();
- const newTargetPoints = {};
- // 处理每个追踪目标
- arr.forEach((item) => {
- if (!Array.isArray(item) || item.length < 4) return;
- const [x, y, z, id] = item;
- currentIds.add(id.toString());
- const pRadar = { x: this.x_radar, y: this.y_radar };
- this.point = convert_point_r2c(
- { x, y },
- pRadar,
- uni.getStorageSync("northAngle")
- );
- // 处理新点或更新现有点
- if (!this.targetPoints[id]) {
- newTargetPoints[id] = this.createNewTargetPoint(
- x,
- y,
- z,
- id
- );
- } else {
- newTargetPoints[id] = this.updateExistingTargetPoint(
- this.targetPoints[id],
- x,
- y,
- z,
- 2
- );
- }
- });
- // 移除不存在的点
- Object.keys(this.targetPoints).forEach((id) => {
- if (!currentIds.has(id)) {
- delete this.targetPoints[id];
- }
- });
- // 更新目标点
- this.targetPoints = {
- ...this.targetPoints,
- ...newTargetPoints,
- };
- }
- },
- createNewTargetPoint(x, y, z, id) {
- return {
- x,
- y,
- z,
- id,
- displayX: this.point.x,
- displayY: this.point.y - 12,
- lastX: x,
- lastY: y,
- };
- },
- updateExistingTargetPoint(existingPoint, x, y, z, THRESHOLD) {
- const dx = x - existingPoint.lastX;
- const dy = y - existingPoint.lastY;
- const distance = Math.sqrt(dx * dx + dy * dy);
- if (distance > THRESHOLD) {
- return {
- ...existingPoint,
- x,
- y,
- z,
- lastX: x,
- lastY: y,
- displayX: this.point.x,
- displayY: this.point.y - 12,
- };
- }
- return existingPoint;
- },
- initSubscriptions() {
- const topicList = [
- {
- topic: `/dev/${this.clientId}/tracker_targets`,
- key: "unsubscribeFn",
- callback: (message, msgTopic) => {
- const dataMatch = msgTopic.match(
- /^\/dev\/(.+)\/tracker_targets$/
- );
- const cmdMatch = msgTopic.match(
- /^\/mps\/wx_(.+)\/notice$/
- );
- if (dataMatch && dataMatch[1] === this.clientId) {
- this.handleMessage(
- msgTopic,
- message,
- this.clientId
- );
- } else if (cmdMatch) {
- this.$refs.alarmModel.hanOtherMessage(
- msgTopic,
- message
- );
- }
- },
- },
- {
- topic: `/dev/${this.clientId}/falling_event_change`,
- key: "fallingEventChange",
- callback: (message, msgTopic) => {
- const dataMatch = msgTopic.match(
- /^\/dev\/(.+)\/falling_event_change$/
- );
- if (dataMatch && dataMatch[1] === this.clientId) {
- const dataMessage = JSON.parse(message.toString());
- console.log(dataMessage, 888888);
- if (dataMessage.falling == 1) {
- this.falling = dataMessage.falling;
- this.lnbAction = "actionWarn";
- } else if (
- dataMessage.falling == 2 ||
- dataMessage.falling == 3
- ) {
- this.falling = dataMessage.falling;
- this.lnbAction = "actionSerious";
- } else {
- this.lnbAction = "action8";
- }
- }
- },
- },
- ];
- topicList.forEach((item) => {
- // 避免重复订阅
- if (this[item.key]) return;
- const subscribeFunc = () => {
- const unsubscribe = MqttService.subscribe(
- "DATA",
- item.topic,
- item.callback
- );
- if (unsubscribe) {
- this[item.key] = unsubscribe;
- console.log(`✅ 已成功订阅主题: ${item.topic}`);
- }
- };
- if (MqttService.dataConnected) {
- subscribeFunc();
- } else {
- // MQTT 未连接,等待重连成功再订阅
- const handler = () => {
- subscribeFunc();
- uni.$off("mqttData-ready", handler);
- };
- uni.$on("mqttData-ready", handler);
- }
- });
- },
- },
- onLoad(options) {
- this.devId = options.devId;
- this.clientId = options.clientId;
- console.log(options, "options111111");
- this.getdevInfo(this.devId);
- this.getRoomInfo(this.devId);
- },
- onShow() {
- // const topic = `/dev/${this.clientId}/tracker_targets`;
- // this.unsubscribeFn = MqttService.subscribe(
- // "DATA",
- // topic,
- // (message, msgTopic) => {
- // const dataMatch = msgTopic.match(
- // /^\/dev\/(.+)\/tracker_targets$/
- // );
- // if (dataMatch && dataMatch[1] === this.clientId) {
- // this.handleMessage(msgTopic, message, this.clientId);
- // }
- // }
- // );
- // if (this.unsubscribeFn) {
- // console.log(`✅ 已成功订阅主题: ${topic}`);
- // }
- if (MqttService.dataConnected && MqttService.dataClient) {
- // 已连接,直接订阅
- this.initSubscriptions();
- }
- },
- onHide() {
- ["unsubscribeFn", "fallingEventChange"].forEach((key) => {
- if (this[key]) {
- this[key]();
- this[key] = null;
- }
- });
- },
- onUnload() {
- // 清理定时器
- clearTimeout(this.autoPlayinterval);
- // 清理自动滑动定时器
- clearInterval(this.setIntervalVal);
- this.setIntervalVal = null;
- this.autoPlayinterval = null;
- // 取消订阅
- ["unsubscribeFn", "fallingEventChange"].forEach((key) => {
- if (this[key]) {
- this[key]();
- this[key] = null;
- }
- });
- },
- };
- </script>
- <style lang="less" scoped>
- .home-warpTwo {
- position: relative;
- height: 100vh;
- background: #f4f4f4;
- .header_two {
- width: 750rpx;
- padding-top: 20rpx;
- background: linear-gradient(180deg, #faede2 0%, #ffffff 100%);
- .radar-box {
- margin: 0 auto;
- position: relative;
- width: 600rpx;
- height: 600rpx;
- background: #ffffff;
- border-radius: 37.5rpx;
- box-sizing: border-box;
- .tranStyle {
- position: absolute;
- overflow: hidden;
- background-color: #fff;
- border: 9rpx solid #333333;
- background-image: url("https://hflnxx.oss-cn-shanghai.aliyuncs.com/IMAGE/20250919/toilet_bg.png");
- background-repeat: no-repeat;
- background-position: center;
- }
- .moduleContent {
- view {
- position: absolute;
- }
- .module-img {
- width: 100%;
- height: 100%;
- display: block;
- }
- }
- .action-icon-G {
- position: absolute;
- width: 100rpx;
- height: 100rpx;
- }
- .action-icon-M {
- // position: absolute;
- width: 50rpx;
- height: 50rpx;
- }
- .redar-pic {
- position: absolute;
- top: 50%;
- left: 50%;
- width: 40rpx;
- height: 40rpx;
- transform: translate(-50%, -50%);
- z-index: 20;
- }
- }
- .airbody {
- margin: 20rpx auto 0 auto;
- width: 700rpx;
- background: #ffffff;
- border-radius: 38rpx;
- box-sizing: border-box;
- .header_top {
- padding: 0rpx 40rpx;
- display: flex;
- justify-content: space-between;
- align-items: center;
- .airTitle {
- font-weight: 500;
- color: #784c41;
- font-size: 32rpx;
- padding-left: 20rpx;
- padding-top: 20rpx;
- }
- .addfnt {
- display: flex;
- align-items: center;
- image {
- margin-top: 7rpx;
- width: 25rpx;
- height: 25rpx;
- }
- .add_btn {
- margin-left: 10rpx;
- font-size: 32rpx;
- }
- }
- }
- .module {
- padding: 10rpx 30rpx;
- bottom: 0;
- box-sizing: border-box;
- width: 100%;
- background: #ffffff;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- .device-bottom {
- margin-top: 20rpx;
- height: 500rpx;
- overflow-y: scroll;
- .no-data {
- margin-top: 100rpx;
- text-align: center;
- }
- .info-box {
- display: flex;
- align-items: center;
- // width: 620rpx;
- padding: 0 30rpx;
- height: 110rpx;
- background: #f8f8f8;
- border-radius: 38rpx;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- font-family: PingFang SC, PingFang SC;
- font-weight: 400;
- font-size: 26rpx;
- .info-text {
- display: flex;
- flex-direction: column;
- margin-left: 20rpx;
- }
- image {
- margin-bottom: 10rpx;
- width: 75rpx;
- height: 75rpx;
- }
- .edit_del {
- margin-left: auto;
- image {
- width: 40rpx;
- height: 40rpx;
- }
- }
- }
- .info-box:not(:first-child) {
- margin-top: 20rpx;
- }
- }
- .device_control {
- overflow: hidden;
- margin-top: 20rpx;
- .control_info {
- height: 160rpx;
- background: #f8f8f8;
- border-radius: 37rpx;
- box-sizing: border-box;
- padding: 20rpx 30rpx;
- display: flex;
- align-content: center;
- justify-content: center;
- .control_left {
- width: 110rpx;
- height: 110rpx;
- .image_class {
- width: 110rpx;
- height: 110rpx;
- }
- }
- .control_right {
- margin-left: 100rpx;
- .control_right_top {
- width: 280rpx;
- height: 50rpx;
- display: flex;
- justify-content: space-around;
- align-items: center;
- background: #ffffff;
- border-radius: 18rpx;
- .title {
- color: #a0acbe;
- font-size: 28rpx;
- }
- input {
- width: 130rpx;
- color: #a0acbe;
- }
- }
- .control_right_bottom {
- width: 280rpx;
- height: 50rpx;
- display: flex;
- justify-content: space-around;
- align-items: center;
- margin-top: 10rpx;
- background: #ffffff;
- border-radius: 18rpx;
- .title {
- color: #a0acbe;
- font-size: 28rpx;
- }
- input {
- width: 130rpx;
- color: #a0acbe;
- }
- }
- }
- }
- }
- }
- }
- .bottomTwo {
- display: flex;
- align-items: center;
- justify-content: center;
- position: fixed;
- bottom: 0;
- left: 0;
- width: 750rpx;
- height: 120rpx;
- background: #f3e2dd;
- .previousTip {
- font-weight: 500;
- color: #111111;
- font-size: 32rpx;
- }
- }
- }
- .bottom-modal {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 999;
- display: flex;
- flex-direction: column;
- // 遮罩层
- .modal-mask {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: rgba(0, 0, 0, 0.5);
- transition: all 0.3s ease;
- }
- // 弹窗容器
- .modal-container {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: #fff;
- border-radius: 16rpx 16rpx 0 0;
- max-height: 70vh;
- display: flex;
- flex-direction: column;
- transform: translateY(0);
- transition: transform 0.3s ease;
- box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
- // 头部样式
- .modal-header {
- position: relative;
- padding: 30rpx;
- text-align: center;
- border-bottom: 1rpx solid #f5f5f5;
- .header-title {
- font-size: 32rpx;
- font-weight: 500;
- color: #333;
- }
- }
- // 内容区域
- .modal-content {
- height: 600rpx;
- overflow-y: scroll;
- .device-bottom {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- gap: 20rpx;
- padding: 0 30rpx;
- box-sizing: border-box;
- .item-box {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- width: 200rpx;
- height: 160rpx;
- background: #f5f7fa;
- border-radius: 20rpx 20rpx 20rpx 20rpx;
- font-family: PingFang SC, PingFang SC;
- font-weight: 400;
- font-size: 26rpx;
- image {
- margin-bottom: 20rpx;
- width: 40rpx;
- height: 40rpx;
- }
- }
- }
- }
- // 底部按钮
- .modal-footer {
- display: flex;
- padding: 20rpx 30rpx;
- border-top: 1rpx solid #f5f5f5;
- .footer-btn {
- flex: 1;
- height: 80rpx;
- line-height: 80rpx;
- border-radius: 40rpx;
- font-size: 28rpx;
- margin: 0 10rpx;
- &.cancel {
- border: none;
- background-color: #f5f5f5;
- color: #666;
- }
- &.confirm {
- border: none;
- background-color: #f3e2dd;
- color: #111111;
- }
- }
- }
- }
- }
- // 动画效果
- .modal-enter-active,
- .modal-leave-active {
- transition: all 0.7s;
- .modal-mask {
- opacity: 1;
- }
- .modal-container {
- transform: translateY(0);
- }
- }
- .modal-enter,
- .modal-leave-to {
- .modal-mask {
- opacity: 0;
- }
- .modal-container {
- transform: translateY(100%);
- }
- }
- // 编辑弹窗
- .device_control {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 999;
- height: 550rpx;
- background: #f8f8f8;
- border-radius: 37rpx 37rpx 0 0;
- box-shadow: 0 -5rpx 20rpx rgba(0, 0, 0, 0.1);
- padding: 30rpx;
- display: flex;
- flex-direction: column;
- // 控制区域(原control_info)
- .control_info {
- display: flex;
- align-items: space-around;
- margin-bottom: 40rpx; // 与操作区域间距
- .control_left {
- margin-left: 100rpx;
- .image_class {
- width: 120rpx;
- height: 120rpx;
- }
- }
- .control_right {
- flex: 1;
- margin-left: 100rpx;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- .control_right_top,
- .control_right_bottom {
- display: flex;
- align-items: center;
- .title {
- font-size: 28rpx;
- color: #666;
- margin-bottom: 10rpx;
- }
- input {
- width: 40%;
- height: 60rpx;
- background: #fff;
- border-radius: 12rpx;
- padding: 0 20rpx;
- }
- }
- }
- }
- .control_operat {
- display: flex;
- flex: 1;
- padding: 0 30rpx;
- .operat_left {
- width: 300rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- .top,
- .middle,
- .bottom {
- width: 100%;
- display: flex;
- justify-content: center;
- }
- .middle {
- justify-content: space-between;
- margin: 15rpx 0;
- }
- image {
- width: 80rpx;
- height: 80rpx;
- background: #fff;
- border-radius: 50%;
- padding: 15rpx;
- box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
- }
- }
- .operat_right {
- flex: 1;
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- padding-top: 70rpx;
- .rotate {
- display: flex;
- margin-bottom: 30rpx;
- .rotate_left,
- .rotate_rigt {
- width: 100rpx;
- height: 70rpx;
- background: #fff;
- border-radius: 12rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
- image {
- width: 40rpx;
- height: 40rpx;
- }
- }
- .rotate_rigt {
- margin-left: 20rpx;
- }
- }
- .del_funit {
- width: 220rpx;
- height: 70rpx;
- background: #7b4f43;
- color: white;
- border-radius: 12rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 28rpx;
- }
- }
- }
- }
- }
- </style>
|