index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. <template>
  2. <div class="curtain" v-if="curtainData && curtainData.length">
  3. <div class="curtain-top">
  4. <div class="curtain-desc">
  5. <p class="curtain-title">
  6. {{
  7. curtainData.length && curtainData.length == 1
  8. ? curtainData[0].name
  9. : "窗帘"
  10. }}
  11. </p>
  12. </div>
  13. <div class="curtain-right">
  14. <img
  15. v-if="
  16. curtainData[0].equipmentType !== 4 &&
  17. curtainData[0].equipmentType !== 5
  18. "
  19. :src="parseImgUrl('page-officehome', 'curtain_new.svg')"
  20. alt=""
  21. />
  22. <img
  23. v-else
  24. :src="parseImgUrl('page-officehome', 'curtain_roll.svg')"
  25. alt=""
  26. />
  27. </div>
  28. </div>
  29. <div
  30. class="curtain-box"
  31. v-if="curtainData.length && curtainData.length > 1"
  32. >
  33. <div class="top-nav">
  34. <span
  35. :class="type == 'all' ? 'nav-active' : ''"
  36. @click="checkNav('all')"
  37. >
  38. 总控制
  39. </span>
  40. <span
  41. :class="type == 'child' ? 'nav-active' : ''"
  42. @click="checkNav('child')"
  43. >
  44. 子设备
  45. </span>
  46. </div>
  47. </div>
  48. <template v-if="type == 'all'">
  49. <div
  50. class="line"
  51. v-if="curtainData.length && curtainData.length > 1"
  52. ></div>
  53. <div class="top-control">
  54. <div
  55. class="control-item"
  56. v-if="curtainData[0].isOpenSet"
  57. @click="openCurtainOpening(curtainData)"
  58. >
  59. <img
  60. class="curtain-opening-icon"
  61. :src="parseImgUrl('page-officehome', 'curtain_opening.svg')"
  62. alt=""
  63. />
  64. </div>
  65. <!--左关-下关-->
  66. <div
  67. class="control-item"
  68. :class="activeIndex == 1 ? 'control-item-active' : ''"
  69. @click="openCurtainMain(1)"
  70. >
  71. <template v-if="activeIndex !== 1">
  72. <img
  73. v-if="
  74. curtainData[0].equipmentType !== 4 &&
  75. curtainData[0].equipmentType !== 5
  76. "
  77. :src="parseImgUrl('page-officehome', 'curtain_left.svg')"
  78. alt=""
  79. />
  80. <img
  81. v-else
  82. :src="parseImgUrl('page-officehome', 'curtain_down.svg')"
  83. alt=""
  84. />
  85. </template>
  86. <span v-else>{{ count }}</span>
  87. </div>
  88. <!--暂停-->
  89. <!-- :class="activeIndex == 3 ? 'control-item-active' : ''" -->
  90. <div
  91. class="control-item"
  92. @click="openCurtainMain(3)"
  93. v-if="curtainData[0].stopSet"
  94. >
  95. <img
  96. :src="parseImgUrl('page-officehome', 'curtain_stop.svg')"
  97. alt=""
  98. />
  99. </div>
  100. <!--右开-->
  101. <div
  102. class="control-item"
  103. @click="openCurtainMain(2)"
  104. :class="activeIndex == 2 ? 'control-item-active' : ''"
  105. >
  106. <template v-if="activeIndex !== 2">
  107. <img
  108. v-if="
  109. curtainData[0].equipmentType !== 4 &&
  110. curtainData[0].equipmentType !== 5
  111. "
  112. :src="parseImgUrl('page-officehome', 'curtain_right.svg')"
  113. alt=""
  114. />
  115. <img
  116. v-else
  117. :src="parseImgUrl('page-officehome', 'curtain_up.svg')"
  118. alt=""
  119. />
  120. </template>
  121. <span v-else>{{ count }}</span>
  122. </div>
  123. </div>
  124. </template>
  125. <div class="curtain-child" v-if="type == 'child'">
  126. <div class="child-item" :key="item.id" v-for="item in curtainData">
  127. <div class="curtain-name">
  128. <div class="name">{{ item.name }}</div>
  129. <span v-if="item.isOpenSet">开度{{ item.openValue }}%</span>
  130. </div>
  131. <div class="curtain-control top-control">
  132. <div
  133. class="control-item"
  134. @click="openCurtainOpening([item])"
  135. v-if="item.isOpenSet"
  136. >
  137. <img
  138. :src="parseImgUrl('page-officehome', 'curtain_opening.svg')"
  139. alt=""
  140. />
  141. </div>
  142. <!--左边-->
  143. <div
  144. class="control-item"
  145. @click="openCurtainClid(item, 1)"
  146. :class="item.activeIndex == 1 ? 'control-item-active' : ''"
  147. >
  148. <template v-if="item.activeIndex != 1">
  149. <img
  150. v-if="item.equipmentType !== 4 && item.equipmentType !== 5"
  151. :src="parseImgUrl('page-officehome', 'curtain_left.svg')"
  152. alt=""
  153. />
  154. <img
  155. v-else
  156. :src="parseImgUrl('page-officehome', 'curtain_down.svg')"
  157. alt=""
  158. />
  159. </template>
  160. <span v-else>{{ item.count }}</span>
  161. </div>
  162. <!--暂停-->
  163. <!-- :class="item.activeIndex == 3 ? 'control-item-active' : ''" -->
  164. <div
  165. class="control-item control-stop"
  166. @click="openCurtainClid(item, 3)"
  167. v-if="item.stopSet"
  168. >
  169. <img
  170. :src="parseImgUrl('page-officehome', 'curtain_stop.svg')"
  171. alt=""
  172. />
  173. </div>
  174. <!-- {{ item }} -->
  175. <!--右边-->
  176. <div
  177. class="control-item"
  178. @click="openCurtainClid(item, 2)"
  179. :class="item.activeIndex == 2 ? 'control-item-active' : ''"
  180. >
  181. <template v-if="item.activeIndex != 2">
  182. <img
  183. v-if="item.equipmentType !== 4 && item.equipmentType !== 5"
  184. :src="parseImgUrl('page-officehome', 'curtain_right.svg')"
  185. alt=""
  186. />
  187. <img
  188. v-else
  189. :src="parseImgUrl('page-officehome', 'curtain_up.svg')"
  190. alt=""
  191. />
  192. </template>
  193. <span v-else>{{ item.count }}</span>
  194. </div>
  195. </div>
  196. </div>
  197. </div>
  198. </div>
  199. </template>
  200. <script lang="ts">
  201. import {
  202. computed,
  203. defineComponent,
  204. onBeforeUnmount,
  205. onMounted,
  206. reactive,
  207. toRefs,
  208. watch,
  209. } from "vue";
  210. import {
  211. getObjectDataEqpGroupHttp,
  212. setEquipeHttp,
  213. setSpaceCondtioners,
  214. } from "@/apis/envmonitor";
  215. import { formatDate, parseImgUrl } from "@/utils";
  216. import { Toast } from "vant";
  217. export default defineComponent({
  218. props: {
  219. projectId: {
  220. type: String,
  221. default: () => "",
  222. },
  223. spaceId: {
  224. type: String,
  225. default: () => "",
  226. },
  227. userIsControl: {
  228. type: Boolean,
  229. default: () => false,
  230. },
  231. },
  232. setup(props, contx) {
  233. let curtainData: any = [];
  234. let timer: any = null;
  235. let projectId: any = props.projectId;
  236. let type: any = "all";
  237. let interval: any = {};
  238. let oldTime: any = null;
  239. const proxyData = reactive({
  240. curtainData: curtainData,
  241. userIsControl: props.userIsControl,
  242. lightIcon: "arrow-down",
  243. projectId: projectId,
  244. type: type,
  245. countText: "", // 到记时文案
  246. count: 2, // 到记时
  247. curtainOpen: false,
  248. curtainClose: false,
  249. parseImgUrl: parseImgUrl,
  250. // 开度弹窗
  251. activeIndex: 0,
  252. // 打开开度弹窗
  253. openCurtainOpening(selectData: any) {
  254. contx.emit("showCurtainOpening", selectData);
  255. },
  256. // 导航切换
  257. checkNav(type: any) {
  258. proxyData.type = type;
  259. console.log("proxyData.type==", proxyData.type);
  260. },
  261. // 获取窗帘列表
  262. getEqpGroup() {
  263. const params: any = {
  264. criteria: {
  265. projectId: props.projectId,
  266. spaceId: props.spaceId, // 空间ID
  267. type: 0, // 0.窗帘
  268. },
  269. orders: [
  270. {
  271. column: "sortNum",
  272. asc: true,
  273. },
  274. ],
  275. };
  276. getObjectDataEqpGroupHttp(params).then((res) => {
  277. const resData: any = res;
  278. proxyData.curtainData = resData.count ? resData.content : [];
  279. // 初始化状态数据
  280. proxyData.curtainData.map((item: any) => {
  281. item.count = 0;
  282. item.activeIndex = 0;
  283. });
  284. });
  285. },
  286. // 定时器定时计算
  287. interval: interval,
  288. countInterval() {
  289. proxyData.interval = setInterval(() => {
  290. proxyData.count--;
  291. if (proxyData.count == 0) {
  292. proxyData.count = 2;
  293. proxyData.activeIndex = 0;
  294. clearInterval(proxyData.interval);
  295. }
  296. }, 1000);
  297. },
  298. countChildInterval(item: any) {
  299. // debugger
  300. proxyData.interval = setInterval(() => {
  301. item.count--;
  302. if (item.count == 0) {
  303. item.count = 2;
  304. item.activeIndex = 0;
  305. clearInterval(proxyData.interval);
  306. }
  307. // console.log(item.count)
  308. }, 1000);
  309. },
  310. // 窗帘总开关
  311. openCurtainMain(type: any) {
  312. // type=1(关) type=2(开) type=3(暂停)
  313. if (proxyData.activeIndex == type && proxyData.count !== 0) {
  314. return;
  315. }
  316. proxyData.activeIndex = type;
  317. proxyData.count = 2;
  318. proxyData.countInterval();
  319. proxyData.formateCurtainData(type);
  320. },
  321. formateValue(type: any) {
  322. let value: any = 0;
  323. if (type == 1) {
  324. value = 0;
  325. } else if (type == 2) {
  326. value = 1;
  327. } else {
  328. value = 2;
  329. }
  330. return value;
  331. },
  332. // 处理窗帘数据
  333. formateCurtainData(type: any) {
  334. let data: any = [];
  335. let value: any = proxyData.formateValue(type);
  336. proxyData.curtainData.map((item: any) => {
  337. let obj: any = {
  338. id: item.equipId,
  339. code: "EquipSwitchSet",
  340. value: value,
  341. };
  342. data.push(obj);
  343. });
  344. proxyData.changeCurtainStatus(data);
  345. },
  346. // 修改窗帘的状态
  347. changeCurtainStatus(data: any) {
  348. console.log("窗帘==", data);
  349. setSpaceCondtioners(data).then((res) => {
  350. proxyData.oldTime = formatDate("YYYY.MM.DD HH:mm:ss");
  351. if (!proxyData.timer) {
  352. proxyData.updateGroupPeing();
  353. }
  354. });
  355. },
  356. // 单个窗帘操作
  357. openCurtainClid(item: any, type: any) {
  358. // if (item.activeIndex == type && item.count !== 0) {
  359. // return;
  360. // }
  361. proxyData.curtainData.map((item: any) => {
  362. item.count = 0;
  363. item.activeIndex = 0;
  364. });
  365. item.activeIndex = type;
  366. let data: any = [];
  367. let obj: any = {
  368. id: item.equipId,
  369. // id: "Eq110108025995ec5bdc23fc47a0a9d8debb150d18eb",
  370. code: "EquipSwitchSet",
  371. value: proxyData.formateValue(type),
  372. };
  373. data.push(obj);
  374. item.count = 2;
  375. proxyData.countChildInterval(item);
  376. proxyData.changeCurtainStatus(data);
  377. },
  378. oldTime: oldTime,
  379. timer: timer,
  380. clearTimer() {
  381. clearInterval(proxyData.timer);
  382. proxyData.timer = null;
  383. },
  384. // 更新窗帘的开度
  385. updateGroupPeing() {
  386. // debugger
  387. proxyData.timer = setInterval(() => {
  388. let nowTime: any = formatDate("YYYY.MM.DD HH:mm:ss");
  389. if (proxyData.oldTime) {
  390. let secondTimeDiff: any = proxyData.getTimeDifference(
  391. proxyData.oldTime,
  392. nowTime
  393. );
  394. // console.log("secondTimeDiff==",secondTimeDiff)
  395. if (secondTimeDiff > 60) {
  396. proxyData.getEqpGroup();
  397. proxyData.clearTimer();
  398. }
  399. } else {
  400. proxyData.oldTime = formatDate("YYYY.MM.DD HH:mm:ss");
  401. }
  402. }, 1000);
  403. },
  404. //计算时间差-分钟
  405. getTimeDifference(Stime: any, Ttime: any) {
  406. // debugger
  407. let startDate: any = new Date(Stime);
  408. let stopDate: any = new Date(Ttime);
  409. let startTime: any = startDate.getTime();
  410. let stopTime: any = stopDate.getTime();
  411. let cTime: any = Number(stopTime) - Number(startTime);
  412. let secondTime: any = cTime / 1000;
  413. return parseInt(secondTime);
  414. },
  415. });
  416. watch(props, (newProps: any) => {
  417. if (newProps.spaceId) {
  418. // 当前空间的控制权限
  419. proxyData.getEqpGroup();
  420. proxyData.userIsControl = newProps.userIsControl;
  421. }
  422. });
  423. onBeforeUnmount(() => {
  424. proxyData.clearTimer();
  425. clearInterval(proxyData.interval);
  426. });
  427. onMounted(() => {
  428. // 获取窗帘信息
  429. proxyData.getEqpGroup();
  430. });
  431. return {
  432. ...toRefs(proxyData),
  433. };
  434. },
  435. });
  436. </script>
  437. <style lang="scss" scoped>
  438. .curtain {
  439. width: 100%;
  440. padding-top: 17px;
  441. padding-bottom: 16px;
  442. background: #ffffff;
  443. box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.07), 0px 4px 10px rgba(0, 0, 0, 0.05);
  444. border-radius: 25px;
  445. margin: 15px 0px;
  446. }
  447. .curtain-top {
  448. padding-right: 20px;
  449. padding-left: 20px;
  450. display: flex;
  451. justify-content: space-between;
  452. padding-bottom: 20px;
  453. .curtain-desc {
  454. .curtain-title {
  455. padding-top: 7px;
  456. font-family: "PingFang SC";
  457. font-style: normal;
  458. font-weight: 600;
  459. font-size: 16px;
  460. line-height: 22px;
  461. /* TUI/Subtitle */
  462. color: #4d5262;
  463. }
  464. }
  465. .curtain-right {
  466. position: relative;
  467. width: 100px;
  468. text-align: center;
  469. margin-right: 33px;
  470. img {
  471. width: 100px;
  472. height: 62px;
  473. }
  474. }
  475. }
  476. .curtain-box {
  477. display: flex;
  478. justify-content: space-between;
  479. padding: 0px 20px;
  480. padding-bottom: 25px;
  481. padding-top: 10px;
  482. .top-nav {
  483. height: 28px;
  484. line-height: 28px;
  485. border-radius: 21px;
  486. background: #f1f4f6;
  487. span {
  488. box-sizing: border-box;
  489. display: inline-block;
  490. font-family: "PingFang SC";
  491. font-style: normal;
  492. font-weight: 400;
  493. font-size: 14px;
  494. line-height: 28px;
  495. padding: 0 8px;
  496. color: #424c59;
  497. }
  498. .nav-active {
  499. background: #fff;
  500. border: 1px solid #e1e5eb;
  501. border-radius: 21px;
  502. }
  503. }
  504. }
  505. .line {
  506. border-top: 1px solid #e8ecf0;
  507. }
  508. .top-control {
  509. text-align: right;
  510. padding: 16px 20px;
  511. padding-bottom: 0;
  512. .control-item {
  513. position: relative;
  514. display: inline-block;
  515. margin-left: 8px;
  516. width: 40px;
  517. height: 40px;
  518. background: #f1f4f6;
  519. border-radius: 50%;
  520. &:active {
  521. background: rgba(206, 159, 39, 0.4);
  522. }
  523. img {
  524. position: absolute;
  525. width: 16px;
  526. height: 16px;
  527. left: 50%;
  528. top: 50%;
  529. transform: translate(-50%, -50%);
  530. }
  531. .curtain-opening-icon {
  532. width: 20px;
  533. height: 20px;
  534. }
  535. }
  536. .control-stop {
  537. // &:active {
  538. // background: rgba(206, 159, 39, 0.4);
  539. // }
  540. }
  541. .control-item-active {
  542. background: rgba(206, 159, 39, 0.4);
  543. span {
  544. position: absolute;
  545. font-family: "Persagy";
  546. font-style: normal;
  547. font-weight: 400;
  548. font-size: 16px;
  549. left: 50%;
  550. top: 50%;
  551. transform: translate(-50%, -50%);
  552. }
  553. }
  554. }
  555. .curtain-child {
  556. .child-item {
  557. display: flex;
  558. justify-content: space-between;
  559. padding-top: 16px;
  560. padding-bottom: 16px;
  561. padding-left: 20px;
  562. padding-right: 20px;
  563. border-top: 1px solid #e8ecf0;
  564. .curtain-name {
  565. display: inline-block;
  566. vertical-align: middle;
  567. .name {
  568. font-family: "PingFang SC";
  569. font-style: normal;
  570. font-weight: 600;
  571. font-size: 16px;
  572. line-height: 22px;
  573. padding-top: 5px;
  574. color: #4d5262;
  575. }
  576. span {
  577. display: block;
  578. padding-top: 4px;
  579. font-family: "PingFang SC";
  580. font-style: normal;
  581. font-weight: 400;
  582. font-size: 14px;
  583. line-height: 20px;
  584. color: #c4c4c4;
  585. }
  586. }
  587. }
  588. .top-control {
  589. display: inline-block;
  590. vertical-align: middle;
  591. padding: 0;
  592. // padding-top: 5px;
  593. }
  594. }
  595. </style>