HorFloorSpace.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. <template>
  2. <div
  3. class="floorSpace"
  4. :class="[screenType === 'hor' ? 'horiFloorClass ' : 'verFloorClass ']"
  5. >
  6. <div class="buildName" v-show="allBuild.length">
  7. {{ nowBuildName }}
  8. </div>
  9. <div class="leftChange" v-if="screenType == 'hor'">
  10. <div class="allIndicator">
  11. <div
  12. class="showItem"
  13. v-bind:style="{
  14. top: selIndicator.index * 16 + '%',
  15. }"
  16. >
  17. <div class="title">{{ selIndicator.name }}</div>
  18. <div class="ltextCont">
  19. <div class="value">{{ totalAvgValues }}{{ selIndicator.unit }}</div>
  20. <div class="name">平均{{ selIndicator.name }}</div>
  21. </div>
  22. <div class="other">
  23. <img class="img" :src="selIndicator.img" />
  24. </div>
  25. </div>
  26. <div
  27. class="eachItem"
  28. v-for="(item, index) in allIndicator"
  29. @click="clickIndicator(index)"
  30. v-bind:class="{ select: item.id == selIndicator.id }"
  31. >
  32. <div class="title">{{ item.name }}</div>
  33. <!-- <div class="textCont" v-show="item.id == selIndicator.id">
  34. <span class="value"
  35. >{{ totalAvgValues }}{{ selIndicator.unit }}</span
  36. ><br /><span class="name"
  37. >平均{{ selIndicator.name }}</span
  38. >
  39. </div>
  40. <img
  41. v-show="item.id == selIndicator.id"
  42. class="img"
  43. :src="selIndicator.img"
  44. /> -->
  45. </div>
  46. </div>
  47. </div>
  48. <div class="topChange" v-if="screenType == 'ver'">
  49. <div class="allIndicator">
  50. <div
  51. class="eachItem"
  52. v-for="(item, index) in allIndicator"
  53. @click="clickIndicator(index)"
  54. v-bind:class="{ select: item.id == selIndicator.id }"
  55. >
  56. <span>{{ item.name }}</span>
  57. <!-- <img
  58. class="bar"
  59. src="@/assets/image/horImg/lastAllLight.png"
  60. /> -->
  61. </div>
  62. </div>
  63. <div class="imageDiv">
  64. <img :src="selIndicator.verimg" />
  65. </div>
  66. <div class="textCont">
  67. 平均<span>{{ selIndicator.name }}</span
  68. ><span class="value">{{ totalAvgValues }}</span
  69. ><span>
  70. {{ selIndicator.unit }}
  71. </span>
  72. </div>
  73. </div>
  74. <div class="floorWrap" id="floorWrap">
  75. <div
  76. class="floor-item"
  77. v-for="(item, index) in showFloors"
  78. :key="index"
  79. v-bind:style="{ height: item.floorHeight + 'px' }"
  80. >
  81. <div class="floor-num">
  82. <span>{{ item.localName }}</span>
  83. </div>
  84. <div class="floor-space">
  85. <div
  86. class="space-box"
  87. v-for="(childItem, id) in item.dataSpaces"
  88. :key="id"
  89. v-bind:style="{
  90. width: item.spacewidth + '%',
  91. height: item.spaceheight + '%',
  92. }"
  93. >
  94. <div
  95. class="space-name"
  96. v-bind:style="{
  97. backgroundColor: selectColor(
  98. childItem.avgValues,
  99. selIndicatorId,
  100. true
  101. ),
  102. }"
  103. >
  104. {{ childItem.localName }}
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </div>
  111. </template>
  112. <script lang="ts">
  113. import { ref, defineComponent, reactive, toRefs, onMounted } from "vue";
  114. import { queryBuilding, queryFs, queryParam } from "@/api/index";
  115. import useProjectStore from "@/store/useProjectStore";
  116. import { dapingImage } from "@/utils/dapingImage";
  117. import moment from "moment";
  118. import { selectColor } from "@/utils/publicMethod";
  119. export default defineComponent({
  120. props: {
  121. screenType: {
  122. type: String,
  123. },
  124. showPing: {
  125. type: Number,
  126. },
  127. },
  128. setup(props, contx) {
  129. const {
  130. floor_co2,
  131. floor_jiaquan,
  132. floor_pm25,
  133. floor_shidu,
  134. floor_wendu,
  135. floor_co2_ver,
  136. floor_jiaquan_ver,
  137. floor_pm25_ver,
  138. floor_shidu_ver,
  139. floor_wendu_ver,
  140. } = dapingImage;
  141. const projectStore = useProjectStore();
  142. let intervalNumber = 3000;
  143. if (projectStore.projectId === "Pj1101050057") {
  144. intervalNumber = 10000;
  145. }
  146. const allData = reactive({
  147. selectColor: selectColor,
  148. timeoutsign: null,
  149. selIndicator: {},
  150. selIndicatorId: "", //为了颜色用
  151. // 温度
  152. nowIndicatorIndex: null, //现在选中的指标 index
  153. allIndicator: [
  154. {
  155. id: "temp",
  156. index: 0,
  157. code: "Tdb",
  158. name: "温度",
  159. img: dapingImage.floor_wendu,
  160. verimg: dapingImage.floor_wendu_ver,
  161. unit: "℃",
  162. fixed: 1,
  163. },
  164. {
  165. id: "humidity",
  166. index: 1,
  167. code: "RH",
  168. name: "湿度",
  169. img: dapingImage.floor_shidu,
  170. verimg: dapingImage.floor_shidu_ver,
  171. unit: "%",
  172. fixed: 0,
  173. },
  174. {
  175. id: "co2",
  176. index: 2,
  177. code: "CO2",
  178. name: "CO₂",
  179. img: dapingImage.floor_co2,
  180. verimg: dapingImage.floor_co2_ver,
  181. unit: "ppm",
  182. fixed: 0,
  183. },
  184. {
  185. id: "methanal",
  186. index: 3,
  187. code: "HCHO",
  188. name: "甲醛",
  189. img: dapingImage.floor_jiaquan,
  190. verimg: dapingImage.floor_jiaquan_ver,
  191. unit: "mg/m³",
  192. fixed: 2,
  193. },
  194. {
  195. id: "pm25",
  196. index: 4,
  197. code: "PM2d5",
  198. name: "PM2.5",
  199. img: dapingImage.floor_pm25,
  200. verimg: dapingImage.floor_pm25_ver,
  201. unit: "ug/m³",
  202. fixed: 0,
  203. },
  204. ],
  205. allBuild: [],
  206. nowBuildName: "",
  207. nowBuildPage: 1, //目前是第几个建筑
  208. allFloor: [],
  209. firstPageParams: [],
  210. secondPageParams: [],
  211. nowPage: 1, //当前哪一屏幕
  212. pageNum: 0,
  213. showFloors: [],
  214. totalAvgValues: null,
  215. hqueryBuild() {
  216. queryBuilding()
  217. .then((res) => {
  218. var data = (res.data || {}).content || [];
  219. //debugger;
  220. if (projectStore.projectId == "Pj3301100002") {
  221. var filterdata = data.filter((item) => {
  222. return item.localName == "1#楼";
  223. });
  224. allData.allBuild = filterdata;
  225. } else {
  226. allData.allBuild = data;
  227. }
  228. allData.nowBuildPage = 1;
  229. allData.fqueryFs();
  230. })
  231. .catch((res) => {
  232. contx.emit("donetowpage"); // 所有建筑切换完毕
  233. // loading.close();
  234. });
  235. },
  236. fqueryFs() {
  237. //var loading = this.$loading({ fullscreen: true });
  238. //debugger;
  239. var buildId = (allData.allBuild[allData.nowBuildPage - 1] || {}).id; //当前的建筑id
  240. if (!buildId) {
  241. return;
  242. }
  243. queryFs({
  244. criteria: {
  245. projectId: projectStore.projectId,
  246. buildingId: buildId,
  247. },
  248. size: 14, //最多14层
  249. page: 1,
  250. orders: [
  251. {
  252. column: "floorSequenceId",
  253. asc: true,
  254. },
  255. ],
  256. })
  257. .then((res) => {
  258. // loading.close();
  259. var allFloor = res.data.content || [];
  260. allFloor = allFloor.filter(function (item) {
  261. return item.spaceNum > 0;
  262. });
  263. //如果该建筑的所有楼层 没有空间 则请求下一个建筑
  264. if (allFloor.length == 0) {
  265. //换下一栋楼
  266. allData.nowBuildPage = allData.nowBuildPage + 1;
  267. if (allData.nowBuildPage > allData.allBuild.length) {
  268. contx.emit("donetowpage"); // 所有建筑切换完毕
  269. return;
  270. }
  271. allData.fqueryFs();
  272. return;
  273. }
  274. allData.nowBuildName =
  275. allData.allBuild[allData.nowBuildPage - 1].localName;
  276. allData.allFloor = allFloor;
  277. var allFloorNum = allFloor.length;
  278. //如果超过7层 就显示两屏幕 第一屏 firstPageNum
  279. //如果超过7层 就显示两屏幕 第二屏 secondPageNum
  280. var firstPageNum, secondPageNum;
  281. if (allFloorNum <= 7) {
  282. firstPageNum = allFloorNum;
  283. secondPageNum = 0;
  284. allData.pageNum = 1;
  285. } else {
  286. firstPageNum = Math.ceil(allFloorNum / 2);
  287. secondPageNum = Math.floor(allFloorNum / 2);
  288. allData.pageNum = 2;
  289. }
  290. var firstMaxSpace = allData.floorHandle(firstPageNum); //第一屏 一层最多空间
  291. var sendMaxSpace = allData.floorHandle(secondPageNum);
  292. var firstPageFloors = allFloor.slice(0, firstPageNum); //第一屏 所有楼层
  293. var secondPageFloors = allFloor.slice(firstPageNum); //第二屏 所有楼层
  294. //第一屏的参数 第二屏的参数
  295. allData.firstPageParams = firstPageFloors.map((item) => {
  296. var obj = {};
  297. obj.id = item.id;
  298. obj.projectId = projectStore.projectId;
  299. obj.spaceNum = firstMaxSpace; //最多空间数
  300. return obj;
  301. });
  302. allData.secondPageParams = secondPageFloors.map((item) => {
  303. var obj = {};
  304. obj.id = item.id;
  305. obj.projectId = projectStore.projectId;
  306. obj.spaceNum = sendMaxSpace;
  307. return obj;
  308. });
  309. allData.nowIndicatorIndex = 0;
  310. //debugger;
  311. allData.getTimeFloorParam(intervalNumber);
  312. })
  313. .catch(function (res) {
  314. // loading.close();
  315. allData.nowBuildPage = allData.nowBuildPage + 1;
  316. if (allData.nowBuildPage > allData.allBuild.length) {
  317. contx.emit("donetowpage"); // 所有建筑切换完毕
  318. return;
  319. }
  320. allData.fqueryFs();
  321. });
  322. },
  323. toplay() {
  324. allData.getTimeFloorParam(500);
  325. },
  326. tostop() {
  327. clearTimeout(allData.timeoutsign);
  328. },
  329. getTimeFloorParam(time) {
  330. //第一屏的参数 第二屏的参数
  331. var floorparam =
  332. allData.nowPage == 1
  333. ? allData.firstPageParams
  334. : allData.secondPageParams;
  335. allData
  336. .fqueryParam(floorparam)
  337. .then(() => {
  338. if (projectStore.stopSign) {
  339. return;
  340. }
  341. allData.timeoutsign = setTimeout(() => {
  342. //debugger;
  343. allData.nowIndicatorIndex = allData.nowIndicatorIndex + 1; //湿度等指标的轮询变化
  344. if (allData.nowIndicatorIndex == 5) {
  345. //如果指标轮询结束 通知切换
  346. if (allData.pageNum == allData.nowPage) {
  347. allData.nowPage = 1;
  348. if (allData.nowBuildPage == allData.allBuild.length) {
  349. contx.emit("donetowpage");
  350. clearTimeout(allData.timeoutsign);
  351. } else {
  352. //换下一个建筑
  353. allData.nowBuildPage = allData.nowBuildPage + 1;
  354. allData.fqueryFs();
  355. }
  356. return;
  357. }
  358. //如果是两页 并且nowPage是第一页
  359. if (allData.pageNum == 2 && allData.nowPage == 1) {
  360. allData.nowPage = 2;
  361. allData.nowIndicatorIndex = 0;
  362. }
  363. }
  364. allData.getTimeFloorParam(intervalNumber);
  365. }, time);
  366. })
  367. .catch(() => {
  368. //debugger;
  369. });
  370. },
  371. fqueryParam(floorparam) {
  372. var endTime = moment();
  373. var startTime = moment().subtract(30, "minutes");
  374. var startStr = startTime.format("YYYYMMDDHHmmss");
  375. var endStr = endTime.format("YYYYMMDDHHmmss");
  376. var newv = allData.nowIndicatorIndex;
  377. //debugger;
  378. allData.selIndicator = allData.allIndicator[newv];
  379. var param = allData.selIndicator.code;
  380. return queryParam(endStr, startStr, param, floorparam)
  381. .then((res) => {
  382. //loading.close();
  383. //debugger;
  384. var showFloors = (res.data.data || {}).floors || [];
  385. allData.totalAvgValues = res.data.data.avgValues || null;
  386. allData.totalAvgValues &&
  387. (allData.totalAvgValues = allData.totalAvgValues.toFixed(
  388. allData.selIndicator.fixed
  389. ));
  390. var wrapHeight =
  391. document.getElementById("floorWrap") &&
  392. document.getElementById("floorWrap").offsetHeight;
  393. showFloors.forEach((ele) => {
  394. var filterFloorarr = allData.allFloor.filter((item) => {
  395. return item.id == ele.id;
  396. });
  397. var filterFloor = filterFloorarr[0] || {};
  398. ele.name = filterFloor.name;
  399. ele.localId = filterFloor.localId;
  400. ele.localName = filterFloor.localName;
  401. var dataSpacesNum = (ele.dataSpaces || []).length;
  402. var floorParam = allData.spaceHandle(dataSpacesNum); //一行的个数
  403. ele.spacewidth = 100 / floorParam.lineNum;
  404. ele.spaceheight = 100 / floorParam.floorline; //每一行的高度
  405. ele.floorHeight = wrapHeight / showFloors.length; //每一层的高度
  406. });
  407. allData.showFloors = showFloors;
  408. allData.selIndicatorId = allData.selIndicator.id;
  409. })
  410. .catch((err) => {
  411. //debugger;
  412. });
  413. },
  414. spaceHandle(spaceNum) {
  415. //返回一层 的每一行 几个房间
  416. var lineNum = spaceNum; //一行的房间数
  417. var floorline = Math.ceil(spaceNum / 14); //20-30 3排 30-40个 4排 所以一排10个
  418. lineNum = Math.ceil(spaceNum / floorline);
  419. return { lineNum, floorline };
  420. //debugger;
  421. },
  422. floorHandle(floorNum) {
  423. //返回一层 最多多少房间
  424. var maxFloorSpace = 28; //一层 最多显示房间数
  425. // switch (floorNum) {
  426. // case 1:
  427. // maxFloorSpace = 160;
  428. // break;
  429. // case 2:
  430. // maxFloorSpace = 80;
  431. // break;
  432. // case 3:
  433. // maxFloorSpace = 50;
  434. // break;
  435. // case 4:
  436. // maxFloorSpace = 30;
  437. // break;
  438. // case 5:
  439. // case 6:
  440. // case 7:
  441. // maxFloorSpace = 20;
  442. // break;
  443. // }
  444. return maxFloorSpace;
  445. },
  446. });
  447. onMounted(() => {
  448. allData.nowPage = 1;
  449. allData.hqueryBuild();
  450. //console.log("floorspace-mounted");
  451. });
  452. return { ...toRefs(allData) };
  453. },
  454. });
  455. </script>
  456. <style lang="scss" scoped>
  457. .floorSpace {
  458. width: 100%;
  459. height: 100%;
  460. display: flex;
  461. position: relative;
  462. border-radius: 16px;
  463. .buildName {
  464. position: absolute;
  465. top: -40px;
  466. left: -40px;
  467. background: linear-gradient(
  468. 90deg,
  469. rgba(131, 195, 255, 0.16) 0%,
  470. rgba(131, 195, 255, 0) 100%
  471. );
  472. height: 46px;
  473. line-height: 46px;
  474. font-size: 20px;
  475. //min-width: 145px;
  476. padding: 0 20px;
  477. color: #f7ecdb;
  478. box-sizing: border-box;
  479. }
  480. }
  481. .topChange {
  482. height: 220px;
  483. width: 100%;
  484. margin: 0 auto;
  485. background: #ffffff;
  486. position: relative;
  487. background: rgba(149, 162, 194, 0.1);
  488. backdrop-filter: blur(20px);
  489. border-radius: 20px;
  490. .allIndicator {
  491. position: relative;
  492. padding-top: 36px;
  493. padding-bottom: 36px;
  494. display: flex;
  495. align-items: center;
  496. justify-content: center;
  497. .eachItem {
  498. cursor: pointer;
  499. font-size: 28px;
  500. font-weight: 600;
  501. color: #9b98ad;
  502. margin-right: 40px;
  503. display: flex;
  504. flex-direction: column;
  505. align-items: center;
  506. width: 90px;
  507. .bar {
  508. width: 80px;
  509. }
  510. &.select {
  511. color: #f7e6cd;
  512. background-image: url("@/assets/image/horImg/lastAllLight.png");
  513. background-repeat: no-repeat;
  514. background-position: center bottom;
  515. background-size: 100%;
  516. padding-bottom: 7px;
  517. // .bar {
  518. // // background: #46ccf6;
  519. // }
  520. }
  521. }
  522. }
  523. .imageDiv {
  524. height: 32px;
  525. margin: 0 32px;
  526. font-size: 0;
  527. text-align: center;
  528. img {
  529. font-size: 0;
  530. height: 100%;
  531. }
  532. }
  533. .textCont {
  534. color: #f7e6cd;
  535. font-size: 20px;
  536. font-weight: 600;
  537. text-align: center;
  538. padding-top: 16px;
  539. .value {
  540. margin-left: 6px;
  541. }
  542. }
  543. }
  544. .leftChange {
  545. height: 100%;
  546. width: 154px;
  547. box-sizing: border-box;
  548. padding: 65px 0 20px;
  549. margin: 0 auto;
  550. position: relative;
  551. //min-height: 730px;
  552. .allIndicator {
  553. // padding-top: 65px;
  554. //padding-bottom: 20px;
  555. // display: flex;
  556. // align-items: center;
  557. // justify-content: center;
  558. position: relative;
  559. height: 100%;
  560. .showItem {
  561. transition: all 400ms linear;
  562. // height: 342px;
  563. height: 36%;
  564. box-sizing: border-box;
  565. padding-top: 20px;
  566. position: absolute;
  567. top: 0;
  568. left: 16px;
  569. width: 120px;
  570. // display: flex;
  571. // flex-direction: column;
  572. background-color: rgba(100, 108, 130, 0.2);
  573. backdrop-filter: blur(10px);
  574. background-image: url("@/assets/image/horImg/twoLight.png");
  575. background-repeat: no-repeat;
  576. background-position: center top;
  577. background-size: 100%;
  578. border-radius: 10px;
  579. text-align: center;
  580. .other {
  581. height: 60%;
  582. padding: 14px 0;
  583. box-sizing: border-box;
  584. font-size: 0;
  585. .img {
  586. height: 100%;
  587. padding: 0;
  588. margin: 0;
  589. }
  590. }
  591. .title {
  592. color: #f7ecdb;
  593. font-size: 24px;
  594. //font-size: 1.3vw;
  595. height: 20%;
  596. font-weight: 600;
  597. }
  598. .ltextCont {
  599. color: #f7ecdb;
  600. line-height: 23px;
  601. height: 20%;
  602. .value {
  603. font-weight: 700;
  604. font-size: 20px;
  605. font-family: PersagyBold;
  606. }
  607. .name {
  608. font-weight: 400;
  609. font-size: 14px;
  610. }
  611. }
  612. }
  613. .eachItem {
  614. cursor: pointer;
  615. //margin-bottom: 56px;
  616. padding-top: 20px;
  617. // height: 90px;
  618. height: 16%;
  619. box-sizing: border-box;
  620. text-align: center;
  621. font-family: PingFang SC;
  622. .title {
  623. color: #9b98ad;
  624. font-size: 24px;
  625. font-weight: 600;
  626. }
  627. &.select {
  628. // height: 350px;
  629. height: 36%;
  630. }
  631. }
  632. .eachItem:last-child {
  633. margin-bottom: 0;
  634. }
  635. }
  636. }
  637. .floorWrap {
  638. flex: 1;
  639. margin: 0 auto;
  640. // background: #ffffff;
  641. border-top-right-radius: 16px;
  642. border-bottom-right-radius: 16px;
  643. box-sizing: border-box;
  644. .floor-item {
  645. display: flex;
  646. padding: 18px 20px 18px 0;
  647. box-sizing: border-box;
  648. // background: linear-gradient(
  649. // 186deg,
  650. // rgba(50, 129, 246, 0.1) 6.16%,
  651. // rgba(50, 129, 246, 0) 81.03%
  652. // );
  653. }
  654. .floor-num {
  655. display: flex;
  656. justify-content: center;
  657. align-items: center;
  658. font-family: PersagyBold;
  659. font-size: 36px;
  660. font-weight: bold;
  661. line-height: 43px;
  662. color: #f7ecdb;
  663. width: 90px;
  664. flex-shrink: 0;
  665. }
  666. .floor-space {
  667. display: flex;
  668. flex: 1;
  669. flex-wrap: wrap;
  670. font-size: 14px;
  671. .space-box {
  672. padding: 4px;
  673. box-sizing: border-box;
  674. .space-name {
  675. display: flex;
  676. justify-content: center;
  677. align-items: center;
  678. //height: 86px;
  679. height: 100%;
  680. min-width: 20px;
  681. border-radius: 8px;
  682. color: #f7ecdb;
  683. backdrop-filter: blur(5px);
  684. background: rgba(34, 139, 81, 0.76);
  685. text-align: center;
  686. padding: 0 8px;
  687. box-sizing: border-box;
  688. font-weight: 500;
  689. font-family: Persagy;
  690. }
  691. }
  692. }
  693. }
  694. .verFloorClass {
  695. display: block;
  696. .floorWrap {
  697. padding-top: 14px;
  698. height: calc(100% - 220px);
  699. }
  700. .buildName {
  701. top: -55px;
  702. }
  703. }
  704. </style>