123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515 |
- <template>
- <view class="home-warpTwo">
- <view class="header_two">
- <view class="radar-box">
- <view
- :style="{
- width: `${length}rpx`,
- height: `${width}rpx`,
- position: 'absolute',
- top: '50%',
- left: '50%',
- transform: `translate(calc(-50% + ${
- xOffset / 2
- }rpx), calc(-50% + ${yOffset / 2}rpx))`,
- border: `9rpx solid #333333`,
- }"
- class="tranStyle"
- >
- </view>
- <view
- v-for="(item, index) in modules"
- :key="index"
- class="moduleContent"
- >
- <view
- :class="item.type"
- :style="{
- width: `${item.width}rpx`,
- height: `${item.length}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,
- top: '0',
- left: '0',
- 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.length
- }})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";
- 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: 200,
- y_radar: 200,
- };
- },
- computed: {},
- methods: {
- onTouchMove(index, event) {
- if (this.draggingIndex === null) return;
- 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.length / 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].length;
- },
- onTouchEnd(index, event) {
- // this.draggingIndex = null;
- },
- generate(featuriesType) {
- let component = {
- name: "",
- type: featuriesType,
- width: 0,
- length: 0,
- top: 200,
- left: 200,
- rotate: 0,
- };
- switch (featuriesType) {
- case "bed":
- component.width = 80;
- component.length = 120;
- component.name = "床";
- break;
- case "bed_cabinet":
- component.width = 40;
- component.length = 80;
- component.name = "柜子";
- break;
- case "bed_dressing_chair":
- component.width = 40;
- component.length = 40;
- component.name = "化妆椅";
- break;
- case "bed_dressing_mirror":
- component.width = 40;
- component.length = 80;
- component.name = "化妆镜";
- break;
- case "bed_table":
- component.width = 40;
- component.length = 40;
- component.name = "床头柜";
- break;
- case "bath_basin":
- component.width = 40;
- component.length = 80;
- component.name = "脸盆";
- break;
- case "bath_door":
- component.width = 40;
- component.length = 40;
- component.name = "门";
- break;
- case "bath_shower":
- component.width = 40;
- component.length = 60;
- component.name = "淋浴";
- break;
- case "bath_toilet":
- component.width = 40;
- component.length = 40;
- component.name = "马桶";
- break;
- case "dining_table_rect":
- component.width = 40;
- component.length = 40;
- component.name = "餐桌(方形)";
- break;
- case "dining_table":
- component.width = 40;
- component.length = 80;
- component.name = "餐桌";
- break;
- case "dining_chair":
- component.width = 40;
- component.length = 80;
- component.name = "餐椅";
- break;
- case "dining_fridge":
- component.width = 40;
- component.length = 80;
- component.name = "冰箱";
- break;
- case "living_bookcase":
- component.width = 40;
- component.length = 80;
- component.name = "书柜";
- break;
- case "living_sofa":
- component.width = 40;
- component.length = 80;
- component.name = "沙发";
- break;
- case "living_tea_table":
- component.width = 40;
- component.length = 80;
- component.name = "茶几";
- break;
- case "living_tv_stand":
- component.width = 40;
- component.length = 80;
- component.name = "电视柜";
- break;
- case "living_sofa_single":
- component.width = 40;
- component.length = 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].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.length / 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].length;
- },
- // 提取公共的模态框方法
- showModal(title, content, confirmCallback) {
- wx.showModal({
- title,
- content,
- success: (res) => {
- if (res.confirm && confirmCallback) {
- confirmCallback(res);
- }
- },
- });
- },
- saveRoom() {
- console.log(this.modules, 9999);
- if (this.modules.length > 0) {
- this.modules.forEach((item) => {
- item.x = item.left - this.x_radar;
- item.y = this.y_radar - item.top;
- });
- }
- this.$http
- .post(
- "wap/room/saveRoom",
- JSON.stringify({
- devId: this.devId,
- furnitures: this.modules,
- }),
- {
- 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.calculateOffest();
- 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);
- });
- },
- calculateOffest() {
- let xxStart = "";
- let xxEnd = "";
- let yyStart = "";
- let yyEnd = "";
- if (this.devInfo.northAngle == 0) {
- xxStart = this.devInfo.xxStart;
- xxEnd = this.devInfo.xxEnd;
- yyStart = this.devInfo.yyStart;
- yyEnd = this.devInfo.yyEnd;
- }
- if (this.devInfo.northAngle == 90) {
- xxStart = this.devInfo.xxStart;
- xxEnd = this.devInfo.xxEnd;
- yyStart = -this.devInfo.yyEnd;
- yyEnd = -this.devInfo.yyStart;
- }
- if (this.devInfo.northAngle == 180) {
- xxStart = -this.devInfo.xxEnd;
- xxEnd = -this.devInfo.xxStart;
- yyStart = -this.devInfo.yyEnd;
- yyEnd = -this.devInfo.yyStart;
- }
- if (this.devInfo.northAngle == 270) {
- xxStart = -this.devInfo.xxEnd;
- xxEnd = -this.devInfo.xxStart;
- yyStart = this.devInfo.yyStart;
- yyEnd = this.devInfo.yyEnd;
- }
- this.xOffset = xxStart + xxEnd;
- this.yOffset = -(yyStart + yyEnd);
- },
- getRoomInfo(devId) {
- this.$http
- .get(`wap/room/readRoom`, {
- devId: devId,
- })
- .then((res) => {
- if (res.data.data) {
- this.modules = res.data.data.furnitures;
- }
- });
- },
- 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());
- // 处理新点或更新现有点
- 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,
- };
- // console.log(this.targetPoints, "更新后的点位数据2222");
- if (Array.isArray(this.targetPoints)) {
- this.targetPoints = this.targetPoints.filter(
- (item) => item !== null && item !== undefined
- );
- }
- }
- },
- createNewTargetPoint(x, y, z, id) {
- return {
- x,
- y,
- z,
- id,
- displayX: this.x_radar + x,
- displayY: this.y_radar - y,
- 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.x_radar + x,
- displayY: this.y_radar - y,
- };
- }
- 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: 400rpx;
- height: 400rpx;
- 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>
|