FloorSpace.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. <template>
  2. <div class="floorCont">
  3. <div class="topChange">
  4. <div class="buildName" v-show="allBuild.length>1">{{ nowBuildName }}</div>
  5. <div class="allIndicator">
  6. <div
  7. class="eachItem"
  8. v-for="(item, index) in allIndicator"
  9. @click="clickIndicator(index)"
  10. v-bind:class="{ select: item.id == selIndicator.id }"
  11. >
  12. <span>{{ item.name }}</span
  13. ><span class="bar"></span>
  14. </div>
  15. </div>
  16. <div class="imageDiv">
  17. <img :src="selIndicator.img" />
  18. </div>
  19. <div class="textCont">
  20. 平均<span>{{ selIndicator.name }}</span
  21. ><span class="value">{{ totalAvgValues }}</span
  22. ><span>
  23. {{ selIndicator.unit }}
  24. </span>
  25. </div>
  26. </div>
  27. <div class="floorWrap">
  28. <div
  29. class="floor-item"
  30. v-for="(item, index) in showFloors"
  31. :key="index"
  32. v-bind:style="{ height: item.floorHeight + 'px' }"
  33. >
  34. <div class="floor-num">
  35. <span>{{ item.localName }}</span>
  36. </div>
  37. <div class="floor-space">
  38. <div
  39. class="space-box"
  40. v-for="(childItem, id) in item.dataSpaces"
  41. :key="id"
  42. v-bind:style="{
  43. width: item.spacewidth + '%',
  44. height: item.spaceheight + '%',
  45. }"
  46. >
  47. <div
  48. class="space-name"
  49. v-bind:style="{
  50. backgroundColor: selectColor(
  51. childItem.avgValues,
  52. selIndicatorId,
  53. true
  54. ),
  55. }"
  56. >
  57. {{ childItem.localName }}
  58. </div>
  59. </div>
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. </template>
  65. <script>
  66. import { Loading } from "element-ui";
  67. import moment from "moment";
  68. import { selectColor } from "@/utils/publicMethod";
  69. import { mapState } from "vuex";
  70. export default {
  71. name: "FloorSpace",
  72. data() {
  73. return {
  74. selIndicator: {},
  75. selIndicatorId: "", //为了颜色
  76. nowIndicatorIndex: null, //现在选中的指标 index
  77. allIndicator: [
  78. {
  79. id: "temp",
  80. name: "温度",
  81. img: require("../../assets/wendu.svg"),
  82. unit: "℃",
  83. code: "Tdb",
  84. fixed: 1,
  85. },
  86. {
  87. id: "humidity",
  88. code: "RH",
  89. name: "湿度",
  90. img: require("../../assets/shidu.svg"),
  91. unit: "%",
  92. fixed: 0,
  93. },
  94. {
  95. id: "co2",
  96. code: "CO2",
  97. name: "CO₂",
  98. img: require("../../assets/co2.svg"),
  99. unit: "ppm",
  100. fixed: 0,
  101. },
  102. {
  103. id: "methanal",
  104. code: "HCHO",
  105. name: "甲醛",
  106. img: require("../../assets/jiaquan.svg"),
  107. unit: "mg/m³",
  108. fixed: 2,
  109. },
  110. {
  111. id: "pm25",
  112. code: "PM2d5",
  113. name: "PM2.5",
  114. img: require("../../assets/pm25.svg"),
  115. unit: "ug/m³",
  116. fixed: 0,
  117. },
  118. ],
  119. allBuild: [],
  120. nowBuildName: "",
  121. nowBuildPage: 1, //目前是第几个建筑
  122. allFloor: [],
  123. firstPageParams: [],
  124. secondPageParams: [],
  125. nowPage: 1, //当前哪一屏幕
  126. pageNum: 0, //总页数 楼层一共几页
  127. showFloors: [],
  128. totalAvgValues: null,
  129. };
  130. },
  131. props: {
  132. showPing: {
  133. type: Number,
  134. default: () => {
  135. return 0;
  136. },
  137. },
  138. },
  139. computed: {
  140. ...mapState({ projectId: (state) => state.projectId }),
  141. },
  142. watch: {
  143. showPing(newv, oldv) {
  144. //debugger;
  145. //当前屏幕第几屏
  146. if (newv == 2) {
  147. this.nowPage = 1;
  148. this.queryBuild();
  149. }
  150. },
  151. },
  152. mounted() {},
  153. methods: {
  154. selectColor: selectColor,
  155. clickIndicator(index) {
  156. this.nowIndicatorIndex = index;
  157. },
  158. getTimeFloorParam() {
  159. //第一屏的参数 第二屏的参数
  160. var floorparam =
  161. this.nowPage == 1
  162. ? this.firstPageParams
  163. : this.secondPageParams;
  164. var _this = this;
  165. this.queryParam(floorparam).then(() => {
  166. var timeoutsign = setTimeout(() => {
  167. _this.nowIndicatorIndex = _this.nowIndicatorIndex + 1; //湿度等指标的轮询变化
  168. if (_this.nowIndicatorIndex == 5) {
  169. if (_this.pageNum == _this.nowPage) {
  170. //如果指标轮询结束 通知切换
  171. _this.nowIndicatorIndex = 0;
  172. _this.nowPage = 1;
  173. if (_this.nowBuildPage == _this.allBuild.length) {
  174. _this.$emit("donetowpage");
  175. clearTimeout(timeoutsign);
  176. } else {
  177. //换下一个建筑
  178. _this.nowBuildPage = _this.nowBuildPage + 1;
  179. _this.queryFs();
  180. }
  181. return;
  182. }
  183. //如果是两页 并且nowPage是第一页
  184. if (_this.pageNum == 2 && _this.nowPage == 1) {
  185. _this.nowPage = 2;
  186. _this.nowIndicatorIndex = 0;
  187. }
  188. }
  189. this.getTimeFloorParam();
  190. }, 1200);
  191. });
  192. },
  193. queryBuild() {
  194. var _this = this;
  195. this.$axios
  196. .post(this.$api.queryBuilding, {
  197. criteria: {
  198. projectId: this.projectId,
  199. },
  200. })
  201. .then((res) => {
  202. var data = (res.data || {}).content || [];
  203. _this.allBuild = data;
  204. _this.nowBuildPage = 1;
  205. _this.queryFs();
  206. })
  207. .catch((res) => {
  208. // loading.close();
  209. });
  210. },
  211. queryFs() {
  212. // var loading = this.$loading({ fullscreen: true });
  213. var _this = this;
  214. var buildId = (this.allBuild[this.nowBuildPage - 1] || {}).id;
  215. if (!buildId) {
  216. return;
  217. }
  218. this.$axios
  219. .post(this.$api.queryFs, {
  220. criteria: {
  221. projectId: this.projectId,
  222. //'Bd3301100002bba81f4830e04cde87d4b6e5652c0d5e',
  223. buildingId: buildId,
  224. },
  225. size: 14, //最多14层
  226. page: 1,
  227. orders: [
  228. {
  229. column: "floorSequenceId",
  230. asc: true,
  231. },
  232. ],
  233. })
  234. .then((res) => {
  235. //loading.close();
  236. var allFloor = res.data.content || [];
  237. allFloor = allFloor.filter(function(item) {
  238. return item.spaceNum > 0;
  239. });
  240. //如果该建筑的所有楼层 没有空间 则请求下一个建筑
  241. if (allFloor.length == 0) {
  242. _this.nowBuildPage = _this.nowBuildPage + 1;
  243. if (_this.nowBuildPage > _this.allBuild.length) {
  244. _this.$emit("donetowpage");
  245. return;
  246. }
  247. _this.queryFs();
  248. return;
  249. }
  250. _this.nowBuildName =
  251. _this.allBuild[_this.nowBuildPage - 1].localName;
  252. this.allFloor = allFloor;
  253. var allFloorNum = allFloor.length;
  254. //如果超过7层 就显示两屏幕 第一屏 firstPageNum
  255. //如果超过7层 就显示两屏幕 第二屏 secondPageNum
  256. var firstPageNum, secondPageNum;
  257. if (allFloorNum <= 7) {
  258. firstPageNum = allFloorNum;
  259. secondPageNum = 0;
  260. this.pageNum = 1;
  261. } else {
  262. firstPageNum = Math.ceil(allFloorNum / 2);
  263. secondPageNum = Math.floor(allFloorNum / 2);
  264. this.pageNum = 2;
  265. }
  266. var firstMaxSpace = this.floorHandle(firstPageNum); //第一屏 一层最多空间
  267. var sendMaxSpace = this.floorHandle(secondPageNum);
  268. var firstPageFloors = allFloor.slice(0, firstPageNum); //第一屏 所有楼层
  269. var secondPageFloors = allFloor.slice(firstPageNum);
  270. this.firstPageParams = firstPageFloors.map((item) => {
  271. var obj = {};
  272. obj.id = item.id;
  273. obj.projectId = this.projectId;
  274. obj.spaceNum = firstMaxSpace;
  275. return obj;
  276. });
  277. this.secondPageParams = secondPageFloors.map((item) => {
  278. var obj = {};
  279. obj.id = item.id;
  280. obj.projectId = this.projectId;
  281. obj.spaceNum = sendMaxSpace;
  282. return obj;
  283. });
  284. this.nowIndicatorIndex = 0;
  285. this.getTimeFloorParam();
  286. })
  287. .catch((res) => {
  288. // loading.close();
  289. });
  290. },
  291. queryParam(floorparam) {
  292. //var loading = this.$loading({ fullscreen: true });
  293. // Tdb 温度
  294. // CO2 二氧化碳
  295. // RH 湿度
  296. // HCHO甲醛
  297. // PM2d5 pm2.5
  298. var endTime = moment();
  299. var startTime = moment().subtract(30, "minutes");
  300. var startStr = startTime.format("YYYYMMDDHHmmss");
  301. var endStr = endTime.format("YYYYMMDDHHmmss");
  302. var newv = this.nowIndicatorIndex;
  303. //debugger;
  304. this.selIndicator = this.allIndicator[newv];
  305. var param = this.selIndicator.code;
  306. return this.$axios
  307. .post(
  308. `${this.$api.queryParam}?endTime=${endStr}&startTime=${startStr}&param=${param}`,
  309. floorparam
  310. )
  311. .then((res) => {
  312. //loading.close();
  313. var showFloors = res.data.data.floors || [];
  314. this.totalAvgValues = res.data.data.avgValues || null;
  315. this.totalAvgValues &&
  316. (this.totalAvgValues = this.totalAvgValues.toFixed(
  317. this.selIndicator.fixed
  318. ));
  319. var wrapHeight =
  320. document.getElementsByTagName("body")[0].offsetHeight -
  321. 428;
  322. wrapHeight = Math.max(wrapHeight, 1000); //1000是楼层区域的最小高度
  323. showFloors.forEach((ele) => {
  324. var filterFloorarr = this.allFloor.filter((item) => {
  325. return item.id == ele.id;
  326. });
  327. var filterFloor = filterFloorarr[0] || {};
  328. ele.name = filterFloor.name;
  329. ele.localId = filterFloor.localId;
  330. ele.localName = filterFloor.localName;
  331. var dataSpacesNum = (ele.dataSpaces || []).length;
  332. var floorParam = this.spaceHandle(dataSpacesNum); //一行的个数
  333. //debugger;
  334. ele.spacewidth = 100 / floorParam.lineNum;
  335. ele.spaceheight = 100 / floorParam.floorline; //每一行的高度
  336. ele.floorHeight = wrapHeight / showFloors.length; //每一层的高度
  337. });
  338. this.showFloors = showFloors;
  339. this.selIndicatorId = this.selIndicator.id;
  340. });
  341. },
  342. floorHandle(floorNum) {
  343. //返回一层 最多多少房间
  344. var maxFloorSpace = 1; //一层 最多显示房间数
  345. switch (floorNum) {
  346. case 1:
  347. maxFloorSpace = 160;
  348. break;
  349. case 2:
  350. maxFloorSpace = 80;
  351. break;
  352. case 3:
  353. maxFloorSpace = 50;
  354. break;
  355. case 4:
  356. maxFloorSpace = 30;
  357. break;
  358. case 5:
  359. case 6:
  360. case 7:
  361. maxFloorSpace = 20;
  362. break;
  363. }
  364. return maxFloorSpace;
  365. },
  366. spaceHandle(spaceNum) {
  367. //返回一层 的每一行 几个房间
  368. var lineNum = spaceNum; //一行的房间数
  369. var floorline = Math.ceil(spaceNum / 10); //20-30 3排 30-40个 4排 所以一排10个
  370. lineNum = Math.ceil(spaceNum / floorline);
  371. return { lineNum, floorline };
  372. //debugger;
  373. },
  374. },
  375. };
  376. </script>
  377. <style lang="less" scoped>
  378. .floorCont {
  379. border-radius: 16px;
  380. overflow: hidden;
  381. }
  382. .topChange {
  383. height: 194px;
  384. // width: 1000px;
  385. margin: 0 auto;
  386. background: #ffffff;
  387. position: relative;
  388. .buildName {
  389. position: absolute;
  390. top: 0;
  391. left: 0;
  392. height: 42px;
  393. background: #e2f8ff;
  394. line-height: 42px;
  395. border-bottom-right-radius: 16px;
  396. text-align: center;
  397. font-size: 26px;
  398. width: 125px;
  399. }
  400. .allIndicator {
  401. padding-top: 32px;
  402. padding-bottom: 20px;
  403. display: flex;
  404. align-items: center;
  405. justify-content: center;
  406. .eachItem {
  407. cursor: pointer;
  408. font-size: 24px;
  409. font-weight: 600;
  410. color: #9b98ad;
  411. margin-right: 60px;
  412. display: flex;
  413. flex-direction: column;
  414. align-items: center;
  415. .bar {
  416. width: 24px;
  417. height: 6px;
  418. display: inline-block;
  419. }
  420. &.select {
  421. color: #3b3558;
  422. .bar {
  423. background: #46ccf6;
  424. }
  425. }
  426. }
  427. }
  428. .imageDiv {
  429. height: 32px;
  430. margin: 0 32px;
  431. text-align: center;
  432. }
  433. .textCont {
  434. color: #3b3558;
  435. font-size: 20px;
  436. font-weight: 600;
  437. text-align: center;
  438. padding-top: 16px;
  439. .value {
  440. margin-left: 4px;
  441. }
  442. }
  443. }
  444. .floorWrap {
  445. // width: 1000px;
  446. margin: 0 auto;
  447. background: #ffffff;
  448. box-sizing: border-box;
  449. .floor-item {
  450. display: flex;
  451. padding: 18px 16px 18px 0;
  452. box-sizing: border-box;
  453. background: linear-gradient(
  454. 186deg,
  455. rgba(50, 129, 246, 0.1) 6.16%,
  456. rgba(50, 129, 246, 0) 81.03%
  457. );
  458. }
  459. .floor-num {
  460. display: flex;
  461. justify-content: center;
  462. align-items: center;
  463. font-family: Persagy;
  464. font-size: 36px;
  465. font-weight: 700;
  466. line-height: 43px;
  467. color: #3b3558;
  468. width: 90px;
  469. flex-shrink: 0;
  470. }
  471. .floor-space {
  472. display: flex;
  473. flex: 1;
  474. flex-wrap: wrap;
  475. .space-box {
  476. padding: 4px;
  477. box-sizing: border-box;
  478. .space-name {
  479. display: flex;
  480. justify-content: center;
  481. align-items: center;
  482. //height: 86px;
  483. height: 100%;
  484. min-width: 80px;
  485. border-radius: 8px;
  486. background: #d9f5d6;
  487. text-align: center;
  488. padding: 0 8px;
  489. box-sizing: border-box;
  490. }
  491. }
  492. }
  493. }
  494. </style>