remoteControl.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. <template>
  2. <van-nav-bar
  3. title="远程管控"
  4. left-arrow
  5. @click-left="onClickLeft"
  6. safe-area-inset-top
  7. />
  8. <div class="page_check">
  9. <div class="search_pannel">
  10. <div class="pannel_left" @click="showRepairPositionPicker = true">
  11. <van-image
  12. :src="require('@/assets/position.svg')"
  13. width="16"
  14. height="16"
  15. fit="contain"
  16. />
  17. <span>{{ name }}</span>
  18. <van-image
  19. :src="require('@/assets/arrow-right.svg')"
  20. width="24"
  21. height="24"
  22. fit="contain"
  23. />
  24. </div>
  25. <div class="pannel_right" @click="toPath">
  26. <van-image
  27. :src="require('@/assets/search.svg')"
  28. width="16"
  29. height="16"
  30. fit="contain"
  31. />
  32. </div>
  33. </div>
  34. <div class="drop_down">
  35. <van-dropdown-menu active-color="#1989fa">
  36. <van-dropdown-item
  37. v-model="deviceType"
  38. @change="
  39. handelChange(
  40. 'deviceType',
  41. 'deviceTypeTitle',
  42. 'deviceTypeList',
  43. deviceType
  44. )
  45. "
  46. :title="deviceTypeTitle"
  47. :options="deviceTypeList"
  48. />
  49. <van-dropdown-item
  50. v-model="deviceStatus"
  51. @change="
  52. handelChange(
  53. 'deviceStatus',
  54. 'deviceStatusTitle',
  55. 'deviceStatusList',
  56. deviceStatus
  57. )
  58. "
  59. :title="deviceStatusTitle"
  60. :options="deviceStatusList"
  61. />
  62. </van-dropdown-menu>
  63. </div>
  64. <div class="list_total">
  65. <span>共有</span>
  66. <v-count-up
  67. :end-val="total"
  68. class="count_up"
  69. options="{ separator: ',' }"
  70. />
  71. <span>条记录</span>
  72. </div>
  73. <div class="check_info">
  74. <div class="info_list">
  75. <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh"> -->
  76. <van-list
  77. v-model:loading="loading"
  78. :finished="finished"
  79. :error="error"
  80. error-text="请求失败,点击重新加载"
  81. finished-text="没有更多了"
  82. @load="onLoad"
  83. >
  84. <div v-for="(item, index) in list" :key="item.id" class="list_item">
  85. <template v-if="deviceType == 'AirConditioner'">
  86. <!-- <div
  87. v-if="item.attributeList[2]"
  88. class="reduce_type"
  89. :style="{
  90. 'background-color': `${
  91. deviceStatus_filter(item.attributeList[3].value)['color']
  92. }`,
  93. }"
  94. >
  95. <span>{{
  96. `${
  97. deviceStatus_filter(item.attributeList[3].value)["label"]
  98. }`
  99. }}</span>
  100. </div> -->
  101. <template v-if="item.attributeList">
  102. <van-switch
  103. v-model="item.attributeList[3].value"
  104. :active-value="1"
  105. :inactive-value="0"
  106. class="isSwitch"
  107. inactive-color="#dddddd"
  108. @change="
  109. changeSwitch(
  110. item.attributeList[3].value,
  111. index,
  112. item.deviceId
  113. )
  114. "
  115. />
  116. </template>
  117. <span class="header">{{ item.airConditionerName }}</span>
  118. <span
  119. >空间信息:{{ item.installSite }}{{ item.roomNumbers }}</span
  120. >
  121. <!-- <span>设备编号:{{ item.airConditionerNo }}</span> -->
  122. <span v-if="item.attributeList"
  123. >室温:{{ item.attributeList[4].value }}</span
  124. >
  125. <!-- <span>所属租户:{{ item.rentNum }}</span> -->
  126. <!-- <div class="list_btn" v-if="item.attributeList">
  127. <van-button plain type="primary" size="small">{{
  128. item.attributeList[3].value == 1 ? "开启" : "关闭"
  129. }}</van-button>
  130. </div> -->
  131. <van-row class="operation" v-if="item.attributeList">
  132. <van-col
  133. span="8"
  134. @click="
  135. chooseMs(
  136. 'moshitxt',
  137. item.attributeList[2].value,
  138. index,
  139. item.deviceId
  140. )
  141. "
  142. >{{ ms(item.attributeList[2].value)
  143. }}<van-icon name="arrow-down" class="xl"
  144. /></van-col>
  145. <div class="line" style="left: 32%"></div>
  146. <van-col
  147. span="8"
  148. @click="
  149. chooseMs(
  150. 'wendu',
  151. item.attributeList[5].value,
  152. index,
  153. item.deviceId
  154. )
  155. "
  156. >{{ item.attributeList[5].value }}℃<van-icon
  157. name="arrow-down"
  158. class="xl"
  159. /></van-col>
  160. <div class="line" style="left: 65%"></div>
  161. <van-col
  162. span="8"
  163. @click="
  164. chooseMs(
  165. 'fengs',
  166. item.attributeList[0].value,
  167. index,
  168. item.deviceId
  169. )
  170. "
  171. >{{ fs(item.attributeList[0].value)
  172. }}<van-icon name="arrow-down" class="xl"
  173. /></van-col>
  174. </van-row>
  175. </template>
  176. <template v-if="deviceType == 'Ammeter'">
  177. <!-- <div
  178. v-if="item.attributeList"
  179. class="reduce_type"
  180. :style="{
  181. 'background-color': `${
  182. deviceStatus_filter(item.status)['color']
  183. }`,
  184. }"
  185. >
  186. <span>{{
  187. `${deviceStatus_filter(item.status)["label"]}`
  188. }}</span>
  189. </div> -->
  190. <span class="header">{{ item.controlName }}</span>
  191. <span>空间信息:{{ item.installSite }}</span>
  192. <!-- <span>设备编号:{{ item.deviceId }}</span>
  193. <span>实时读数:{{ item.status }}</span> -->
  194. <!-- <span>所属租户:{{ item.rentNum }}</span> -->
  195. <van-switch
  196. v-model="item.status"
  197. active-value="1"
  198. inactive-value="0"
  199. class="isSwitch"
  200. inactive-color="#dddddd"
  201. @change="changeElecSwitch(item.status, item.deviceId)"
  202. />
  203. </template>
  204. </div>
  205. </van-list>
  206. <!-- </van-pull-refresh> -->
  207. </div>
  208. </div>
  209. <van-popup v-model:show="showRepairPositionPicker" round position="bottom">
  210. <van-picker
  211. title="标题"
  212. :columns="positionList"
  213. :columns-field-names="fieldNames"
  214. @cancel="showRepairPositionPicker = false"
  215. @confirm="confirmPosition"
  216. />
  217. </van-popup>
  218. <van-popup v-model:show="showControl" round position="bottom">
  219. <van-picker
  220. v-model="checkedMs"
  221. title="请选择"
  222. :columns="controlList"
  223. @confirm="onConfirmMs"
  224. @cancel="showControl = false"
  225. />
  226. </van-popup>
  227. </div>
  228. </template>
  229. <script>
  230. import api from "../utils/api";
  231. import { ref } from "vue";
  232. import { isEmpty } from "@/utils/index.js";
  233. import VCountUp from "./CountUp";
  234. import { Notify, Dialog, showConfirmDialog } from "vant";
  235. export default {
  236. components: {
  237. "v-count-up": VCountUp,
  238. },
  239. setup() {
  240. //指令下发
  241. const controlList = ref([]);
  242. const showControl = ref(false);
  243. const deviceId = ref("");
  244. const module = ref("");
  245. //切换模式start
  246. const checkedMs = ref([]);
  247. const msCurrentIndex = ref(0);
  248. const moshitxt = ref([
  249. { text: "制热", value: 1 },
  250. { text: "制冷", value: 2 },
  251. { text: "送风", value: 4 },
  252. { text: "除湿", value: 8 },
  253. ]);
  254. //切换模式end
  255. //切换温度start
  256. const checkedWd = ref("");
  257. const wdCurrentIndex = ref(0);
  258. const wendu = ref([]);
  259. //切换温度end
  260. const checkedFs = ref("");
  261. const fsCurrentIndex = ref(0);
  262. const fengs = ref([
  263. { text: "自动", value: 0 },
  264. { text: "低速", value: 1 },
  265. { text: "中速", value: 2 },
  266. { text: "高速", value: 3 },
  267. ]);
  268. const fieldNames = ref({
  269. text: "orgName",
  270. value: "orgId",
  271. children: "childrenList",
  272. });
  273. const storeyId=ref('');
  274. const buildingId=ref('');
  275. const positionList = ref([]); //定位
  276. const page=ref('1');
  277. function ms(data) {
  278. let text = "";
  279. let node = this.moshitxt.filter((item) => {
  280. return item.value == data;
  281. });
  282. if (node[0]) {
  283. text = node[0].text;
  284. }
  285. return text;
  286. }
  287. function fs(data) {
  288. let text = "";
  289. let node = this.fengs.filter((item) => {
  290. return item.value == data;
  291. });
  292. if (node[0]) {
  293. text = node[0].text;
  294. }
  295. return text;
  296. }
  297. return {
  298. page,
  299. module,
  300. deviceId,
  301. controlList,
  302. showControl,
  303. ms,
  304. moshitxt,
  305. checkedMs,
  306. msCurrentIndex,
  307. wendu,
  308. checkedWd,
  309. wdCurrentIndex,
  310. fs,
  311. fengs,
  312. checkedFs,
  313. fsCurrentIndex,
  314. fieldNames,
  315. positionList,
  316. buildingId,
  317. storeyId,
  318. };
  319. },
  320. data() {
  321. return {
  322. showRepairPositionPicker: false,
  323. loading: false,
  324. name: "电商园四期",
  325. deviceType: "AirConditioner",
  326. deviceStatus: "",
  327. deviceTypeTitle: "空调",
  328. deviceStatusTitle: "设备状态",
  329. deviceTypeList: [
  330. { text: "空调", value: "AirConditioner" },
  331. { text: "水表", value: "WaterMeter" },
  332. { text: "电表", value: "Ammeter" },
  333. ],
  334. deviceStatusList: [
  335. { text: "连接中", value: 1 },
  336. { text: "断连中", value: 0 },
  337. ],
  338. total:0,
  339. list: [],
  340. loading: false,
  341. refreshing: false,
  342. finished: false,
  343. };
  344. },
  345. watch: {
  346. positionList(newval, oldval) {
  347. if (newval) {
  348. let json = {
  349. category: "s",
  350. childrenList: null,
  351. orgId: "",
  352. orgName: "全部",
  353. };
  354. for (let i = 0; i < newval.length; i++) {
  355. newval[i].childrenList.push(json);
  356. }
  357. }
  358. },
  359. },
  360. created() {
  361. this.getBuildList();
  362. this.setwendu();
  363. //this.getAircond();
  364. },
  365. methods: {
  366. //定位完成
  367. confirmPosition(val) {
  368. this.buildingId=val[0].orgId;
  369. this.storeyId=val[1].orgId;
  370. let storeyName=val[1].orgName=='全部'?'':val[1].orgName+'-';
  371. this.name="电商园四期-"+val[0].orgName+storeyName;
  372. this.showRepairPositionPicker=false;
  373. },
  374. //继电器下发指令开关
  375. changeElecSwitch(val, deviceId) {
  376. api
  377. .setControlElec({
  378. keyword: "setRelay",
  379. param: val ? 0 : 1,
  380. deviceId: deviceId,
  381. })
  382. .then((res) => {
  383. if (res.code == 0) {
  384. Notify({ type: "success", message: "操作成功" });
  385. }
  386. });
  387. },
  388. //空调下发指令开关
  389. changeSwitch(val, index, deviceId) {
  390. api
  391. .setControl({
  392. keyword: "setPower",
  393. param: val ? 0 : 1,
  394. deviceId: deviceId,
  395. })
  396. .then((res) => {
  397. if (res.code == 0) {
  398. Notify({ type: "success", message: "操作成功" });
  399. }
  400. });
  401. },
  402. onConfirmMs(data) {
  403. let deviceCommandDTO = {};
  404. switch (this.module) {
  405. case "moshitxt":
  406. this.checkedMs[0] = data.value;
  407. this.list[this.msCurrentIndex].attributeList[2].value = data.value;
  408. this.showControl = false;
  409. deviceCommandDTO = {
  410. keyword: "setMode",
  411. param: data.value,
  412. deviceId: this.deviceId,
  413. };
  414. break;
  415. case "wendu":
  416. console.log(data);
  417. this.checkedMs[0] = data;
  418. this.list[this.msCurrentIndex].attributeList[5].value = data;
  419. this.showControl = false;
  420. deviceCommandDTO = {
  421. keyword: "setTemp",
  422. param: data,
  423. deviceId: this.deviceId,
  424. };
  425. break;
  426. case "fengs":
  427. this.checkedMs[0] = data.value;
  428. this.list[this.msCurrentIndex].attributeList[0].value = data.value;
  429. this.showControl = false;
  430. deviceCommandDTO = {
  431. keyword: "setFan",
  432. param: data.value,
  433. deviceId: this.deviceId,
  434. };
  435. break;
  436. }
  437. api.setControl(deviceCommandDTO).then((res) => {
  438. if (res.code == 0) {
  439. Notify({ type: "success", message: "操作成功" });
  440. }
  441. });
  442. },
  443. chooseMs(name, val, index, deviceId) {
  444. this.deviceId = deviceId;
  445. this.msCurrentIndex = index;
  446. this.showControl = true;
  447. this.controlList = this[name];
  448. this.module = name;
  449. },
  450. setwendu() {
  451. this.wendu = [];
  452. for (let i = 16; i < 33; i++) {
  453. this.wendu.push(i);
  454. }
  455. },
  456. elecControl(id, state) {
  457. console.log(id, state);
  458. Dialog.confirm({
  459. title: "标题",
  460. message: "确定执行该操作?",
  461. })
  462. .then(() => {
  463. api
  464. .elecControl({
  465. keyword: "setRelay",
  466. deviceId: id,
  467. param: state ? "1" : "0",
  468. })
  469. .then((res) => {
  470. console.log(res);
  471. if (res.code == 0) {
  472. this.getElec();
  473. }
  474. });
  475. })
  476. .catch(() => {
  477. // on cancel
  478. });
  479. },
  480. getElec() {
  481. console.log(this.page)
  482. api
  483. .getElec({
  484. buildingId:this.buildingId,
  485. storeyId:this.storeyId,
  486. page:this.page,
  487. limit: 10,
  488. status: this.deviceStatus,
  489. controlCategory: "CommonLighting",
  490. })
  491. .then((res) => {
  492. console.log(res)
  493. if (res.code == 0) {
  494. this.total = res.data.total;
  495. this.list=this.list.concat(res.data.list);
  496. this.loading = false;
  497. if( res.data.list.length<10){
  498. this.finished=true;
  499. }else{
  500. this.page++;
  501. }
  502. console.log(this.list)
  503. // for(let i=0;i<res.data.list.length;i++){
  504. // if(res.data.list[i].attributeList&&res.data.list[i].attributeList.length!=0){
  505. // this.list.push(res.data.list[i])
  506. // }
  507. // }
  508. }
  509. });
  510. },
  511. getAircond() {
  512. api
  513. .airconditioner({
  514. page:this.page,
  515. limit: 10,
  516. buildingId:this.buildingId,
  517. storeyId:this.storeyId,
  518. })
  519. .then((res) => {
  520. if (res.code == 0) {
  521. this.total = res.data.total;
  522. for (let i = 0; i < res.data.list.length; i++) {
  523. if (
  524. res.data.list[i].attributeList &&
  525. res.data.list[i].attributeList.length != 0
  526. ) {
  527. this.list.push(res.data.list[i]);
  528. }
  529. }
  530. if( res.data.list.length<10){
  531. this.finished=true;
  532. }else{
  533. this.page++;
  534. }
  535. this.loading = false;
  536. }
  537. });
  538. },
  539. deviceStatus_filter(val) {
  540. if (isEmpty(val)) {
  541. return {};
  542. }
  543. if (val == 1) {
  544. return {
  545. label: "连接中",
  546. color: "#09C700",
  547. btn: "断闸",
  548. };
  549. }
  550. if (val == 0) {
  551. return {
  552. label: "断连中",
  553. color: "#FA5555",
  554. btn: "开闸",
  555. };
  556. }
  557. },
  558. //获取楼栋
  559. getBuildList() {
  560. api.getBuildInfo().then((res) => {
  561. if (res.code == 0) {
  562. this.positionList = res.data[0].childrenList;
  563. if (this.positionList) {
  564. let json = {
  565. category: "s",
  566. childrenList: null,
  567. orgId: "",
  568. orgName: "全部",
  569. };
  570. for (let i = 0; i < this.positionList.length; i++) {
  571. this.positionList[i].childrenList.unshift(json);
  572. }
  573. }
  574. }
  575. });
  576. },
  577. onLoad() {
  578. this.loading = true;
  579. if(this.deviceType=='AirConditioner'){
  580. this.getAircond()
  581. }else{
  582. this.getElec();
  583. }
  584. },
  585. // onRefresh() {
  586. // // 清空列表数据
  587. // finished.value = false;
  588. // // 重新加载数据
  589. // // 将 loading 设置为 true,表示处于加载状态
  590. // loading.value = true;
  591. // this.onLoad();
  592. // },
  593. // change事件可以拿到的是value
  594. handelChange(type, lackTypeTitle, lackTypeList, val) {
  595. this[type] = val;
  596. console.log(this.deviceType)
  597. this.list=[];
  598. this.page=1;
  599. this.finished=true;
  600. if (this.deviceType == "Ammeter") this.getElec();
  601. if (this.deviceType == "AirConditioner") this.getAircond();
  602. // 显示中文名字
  603. this[lackTypeTitle] = this[lackTypeList].filter(
  604. (item) => item.value === val
  605. )[0].text;
  606. },
  607. onClickLeft() {
  608. this.$router.back();
  609. },
  610. },
  611. };
  612. </script>
  613. <style lang="scss" scoped>
  614. .page_check {
  615. height: 100%;
  616. .search_pannel {
  617. padding: 10px 16px;
  618. background: #5c8fff;
  619. box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.04);
  620. display: flex;
  621. align-items: center;
  622. .pannel_left {
  623. display: flex;
  624. align-items: center;
  625. span {
  626. height: 24px;
  627. font-size: 16px;
  628. font-weight: 400;
  629. color: #ffffff;
  630. line-height: 24px;
  631. text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.04);
  632. text-indent: 4px;
  633. }
  634. }
  635. .pannel_left,
  636. .pannel_right {
  637. flex: 1;
  638. }
  639. .pannel_right {
  640. text-align: right;
  641. }
  642. }
  643. .drop_down {
  644. /deep/ {
  645. --van-gray-4: #999999;
  646. --van-dropdown-menu-title-text-color: #0c1935;
  647. }
  648. }
  649. .list_total {
  650. padding: 0 16px;
  651. margin: 8px 0;
  652. display: flex;
  653. text-align: left;
  654. span {
  655. height: 16px;
  656. font-size: 12px;
  657. font-weight: 400;
  658. color: #999999;
  659. line-height: 16px;
  660. }
  661. .count_up {
  662. font-size: 16px;
  663. font-weight: 500;
  664. color: #fa5555;
  665. margin: 0 2px;
  666. }
  667. }
  668. .check_info {
  669. padding: 0 16px;
  670. height: calc(
  671. 100% - var(--van-nav-bar-height) - var(--van-dropdown-menu-height) - 76px
  672. );
  673. .info_list {
  674. height: 100%;
  675. overflow-y: auto;
  676. .list_item {
  677. background: #ffffff;
  678. box-shadow: 0px 0px 10px 0px rgba(153, 153, 153, 0.15);
  679. border-radius: 4px;
  680. margin-bottom: 12px;
  681. padding: 12px 16px;
  682. display: flex;
  683. flex-direction: column;
  684. align-items: flex-start;
  685. position: relative;
  686. &:nth-last-child(1) {
  687. margin-bottom: 0;
  688. }
  689. .header {
  690. height: 22px;
  691. font-size: 16px;
  692. font-weight: 600;
  693. color: #313836;
  694. line-height: 22px;
  695. margin-bottom: 8px;
  696. }
  697. span {
  698. height: 18px;
  699. font-size: 14px;
  700. font-weight: 400;
  701. color: #999999;
  702. line-height: 18px;
  703. margin-bottom: 4px;
  704. &:nth-last-child(1) {
  705. margin-bottom: 0;
  706. }
  707. }
  708. .reduce_type {
  709. position: absolute;
  710. top: 0;
  711. right: 0;
  712. width: 48px;
  713. height: 24px;
  714. border-radius: 0px 4px 0px 10px;
  715. span {
  716. height: 16px;
  717. font-size: 12px;
  718. font-weight: 400;
  719. color: #ffffff;
  720. line-height: 16px;
  721. }
  722. }
  723. // .list_btn {
  724. // position: absolute;
  725. // bottom: 15px;
  726. // right: 12px;
  727. // .van-button {
  728. // &:nth-child(2) {
  729. // margin: 0 12px;
  730. // }
  731. // }
  732. // }
  733. .isSwitch {
  734. position: absolute;
  735. right: 10px;
  736. font-size: 18px;
  737. top: auto;
  738. z-index: 1;
  739. }
  740. .operation {
  741. width: 100%;
  742. position: relative;
  743. font-size: 13px;
  744. margin-top: 10px;
  745. .xl {
  746. margin-left: 4px;
  747. }
  748. .line {
  749. position: absolute;
  750. top: 15%;
  751. width: 2px;
  752. height: 16px;
  753. background: #d6d6d6;
  754. }
  755. }
  756. }
  757. }
  758. }
  759. }
  760. </style>