HorFloorSpace.vue 20 KB

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