index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. <template>
  2. <div style="height: 100%">
  3. <div class="gf-wrapper">
  4. <div class="gf-img">
  5. <div
  6. class="wt-top"
  7. :class="
  8. colorFlag ? colorList1[wtInfo.status] : colorList[wtInfo.status]
  9. "
  10. >
  11. <div class="wt-text">设备名称:{{ wtname }}</div>
  12. <div class="wt-alarm" @click="handleAlarm(wtInfo)">
  13. <i
  14. class="svg-icon svg-icon-sm"
  15. :class="
  16. 'svg-icon-' +
  17. (colorFlag
  18. ? colorList1[wtInfo.status]
  19. : colorList[wtInfo.status])
  20. "
  21. >
  22. <svgIcon svgid="svg-station-surveillance"></svgIcon>
  23. </i>
  24. <span>设备报警</span>
  25. </div>
  26. <!-- <div class="wt-info">厂商名称:{{ otherInfo?.manufacturer }}</div> -->
  27. <div class="wt-xh" @click="handleXhClick(wtInfo)">
  28. 设备型号:{{otherInfo?.manufacturer}} ( {{ otherInfo?.model }} )
  29. </div>
  30. </div>
  31. <img
  32. class="img"
  33. style="width: 95%"
  34. v-if="otherInfo.squareid == 'JZ'"
  35. src="@/assets/imgs/JZ.png"
  36. alt=""
  37. />
  38. <img
  39. class="img"
  40. v-if="otherInfo.squareid == 'ZC'"
  41. src="@/assets/imgs/ZC.png"
  42. alt=""
  43. />
  44. </div>
  45. <div class="part-info">
  46. <div class="part-body yaoxin">
  47. <div class="monitoring-item">
  48. <div class="point point-left bottom"></div>
  49. <div class="point point-right bottom"></div>
  50. 遥信值
  51. </div>
  52. <div class="part-item">
  53. <div
  54. class="part"
  55. :class="{ active: index % 2 === 1 }"
  56. v-for="(val, index) in currentPartD"
  57. :key="index"
  58. >
  59. <div class="table-item" v-for="(item, ind) in val" :key="ind">
  60. <div>{{ item.name }}</div>
  61. <div
  62. class="table-value"
  63. :class="item.value == 1 ? 'round-red' : 'round'"
  64. ></div>
  65. </div>
  66. </div>
  67. </div>
  68. </div>
  69. <div class="part-body yaoce">
  70. <div class="monitoring-item">
  71. <div class="point point-left bottom"></div>
  72. <div class="point point-right bottom"></div>
  73. 遥测值
  74. </div>
  75. <div class="part-item">
  76. <div
  77. class="part"
  78. :class="{ active: index % 2 === 1 }"
  79. v-for="(val, index) in currentPartA"
  80. :key="index"
  81. >
  82. <div class="table-item" v-for="(item, ind) in val" :key="ind">
  83. <div>{{ item.name }}</div>
  84. <div class="table-value">
  85. {{
  86. item.name.includes("状态")
  87. ? item.value
  88. : Number(item.value).toFixed(2)
  89. }}
  90. <div v-if="item.valueUnit != 'NULL'" class="unit">
  91. {{ item.valueUnit }}
  92. </div>
  93. <div v-else class="unit"></div>
  94. </div>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </div>
  101. <alarmDialog ref="alarmDialog" />
  102. <powerAndSpeed ref="powerAndSpeed" :tabEvent="-2" />
  103. </div>
  104. </template>
  105. <script>
  106. import {
  107. GetWtTelemeteryInfo,
  108. GetWtOtherInfo,
  109. } from "@/api/factoryMonitor/index.js";
  110. import { GetWtPoints, GetPointsData } from "@/api/points/index.js";
  111. import svgIcon from "@/components/coms/icon/svg-icon.vue";
  112. import powerAndSpeed from "@/components/powerAndSpeedSearch/index.vue";
  113. import alarmDialog from "@/components/alarm";
  114. export default {
  115. name: "lightDetail",
  116. components: { svgIcon, alarmDialog, powerAndSpeed },
  117. props: {
  118. stationName: {
  119. type: String,
  120. },
  121. leftcellHeight: {
  122. type: String,
  123. default: "4vh",
  124. },
  125. wind: {
  126. type: Object,
  127. default: () => {},
  128. },
  129. flag: {
  130. type: Boolean,
  131. default: false,
  132. },
  133. },
  134. data() {
  135. return {
  136. wtname: "",
  137. wtInfo: {},
  138. colorList: [
  139. "blue",
  140. "blue",
  141. "green",
  142. "green",
  143. "red",
  144. "red",
  145. "orange",
  146. "orange",
  147. "pink",
  148. "pink",
  149. "write",
  150. "write",
  151. "gray",
  152. "gray",
  153. ],
  154. colorList1: ["blue", "green", "red", "orange", "pink", "write", "gray"],
  155. partAInfo: [],
  156. partDInfo: [],
  157. partAInfos: [],
  158. partDInfos: [],
  159. uniformcodesA: [],
  160. uniformcodesD: [],
  161. pointsA: [],
  162. pointsD: [],
  163. allPartInfo: [],
  164. currentPartA: [],
  165. currentPartD: [],
  166. lightCode: null,
  167. squareMsg: null,
  168. squareTelemeteringData: null,
  169. squareTelecommandData: null,
  170. inverterData: null,
  171. timer: "",
  172. colorFlag: false,
  173. wpid: "",
  174. otherInfo: {},
  175. };
  176. },
  177. mounted() {
  178. this.timer = setInterval(async () => {
  179. this.getPointsData();
  180. }, 5000);
  181. },
  182. unmounted() {
  183. clearInterval(this.timer);
  184. this.timer = null;
  185. },
  186. watch: {
  187. wind: {
  188. handler() {
  189. if (Object.keys(this.wind).length) {
  190. this.start(this.wind);
  191. }
  192. },
  193. },
  194. $route: {
  195. handler(val) {
  196. if (
  197. val.path.includes("lightmatrix") ||
  198. val.path.includes("photovoltaicFacility")
  199. ) {
  200. this.colorFlag = true;
  201. }
  202. },
  203. immediate: true,
  204. },
  205. },
  206. methods: {
  207. handleXhClick(wind) {
  208. // console.log(wind);
  209. this.$refs.powerAndSpeed && this.$refs.powerAndSpeed.init(wind);
  210. },
  211. clear() {
  212. this.wtInfo = {};
  213. this.wtname = "";
  214. this.partAInfo = [];
  215. this.partDInfo = [];
  216. this.partAInfos = [];
  217. this.partDInfos = [];
  218. this.uniformcodesA = [];
  219. this.uniformcodesD = [];
  220. this.pointsA = [];
  221. this.pointsD = [];
  222. this.allPartInfo = [];
  223. this.currentPartA = [];
  224. this.currentPartD = [];
  225. },
  226. // 页面初始信息
  227. start(wt) {
  228. if (Object.keys(wt).length) {
  229. this.wtInfo = wt;
  230. this.wpid = wt.wpid;
  231. this.wtname = wt.wtname;
  232. this.getPartInfo(wt.wtid);
  233. this.getWtOtherInfo(wt.wtid);
  234. } else {
  235. this.clear();
  236. }
  237. },
  238. // 设备其他信息
  239. getWtOtherInfo(val) {
  240. GetWtOtherInfo({ wtid: val }).then((res) => {
  241. if (res.code == 200) {
  242. this.otherInfo = res.data;
  243. }
  244. });
  245. },
  246. // 统一编码
  247. getPartInfo(wtid) {
  248. if (this.wtInfo.wtType == -2) {
  249. if (wtid.length) {
  250. GetWtTelemeteryInfo({
  251. part: "nbq",
  252. wtid: wtid,
  253. }).then(({ data }) => {
  254. // 拿到初始获取数据
  255. this.partAInfo = data.data.AI;
  256. this.partDInfo = data.data.DI;
  257. // 拿到数据的uniformcode集合
  258. this.uniformcodesD = this.partDInfo.length
  259. ? this.partDInfo.map((item) => item.uniformCode)
  260. : [];
  261. this.uniformcodesA = this.partAInfo.length
  262. ? this.partAInfo.map((item) => item.uniformCode)
  263. : [];
  264. // 获取测点数据
  265. this.getPointsIds(wtid);
  266. });
  267. }
  268. }
  269. },
  270. getPointsIds(wtid) {
  271. let pointsIdsA = new Promise((resolve, reject) => {
  272. GetWtPoints({
  273. wtid: wtid,
  274. uniformcodes: this.uniformcodesA,
  275. })
  276. .then(({ data }) => {
  277. resolve(data);
  278. })
  279. .catch((e) => {
  280. reject("发生错误");
  281. });
  282. });
  283. let pointsIdsD = new Promise((resolve, reject) => {
  284. GetWtPoints({
  285. wtid: wtid,
  286. uniformcodes: this.uniformcodesD,
  287. })
  288. .then(({ data }) => {
  289. resolve(data);
  290. })
  291. .catch((e) => {
  292. // 标记失败后给定某个数据
  293. reject("发生错误");
  294. });
  295. });
  296. Promise.all([pointsIdsA, pointsIdsD])
  297. .then((results) => {
  298. this.pointsA = results[0].data.length
  299. ? results[0].data.map((item) => (item != null ? item.nemCode : ""))
  300. : [];
  301. this.pointsD = results[1].data.length
  302. ? results[1].data.map((item) => (item != null ? item.nemCode : ""))
  303. : [];
  304. this.getPointsData();
  305. })
  306. .catch((e) => {
  307. console.log("error", e);
  308. });
  309. },
  310. getPointsData() {
  311. let pointsDataA = new Promise((resolve, reject) => {
  312. GetPointsData({
  313. pointIds: this.pointsA,
  314. })
  315. .then(({ data }) => {
  316. resolve(data);
  317. })
  318. .catch((e) => {
  319. // 标记失败后给定某个数据
  320. reject("发生错误");
  321. });
  322. });
  323. let pointsDataD = new Promise((resolve, reject) => {
  324. GetPointsData({
  325. pointIds: this.pointsD,
  326. })
  327. .then(({ data }) => {
  328. resolve(data);
  329. })
  330. .catch((e) => {
  331. // 标记失败后给定某个数据
  332. reject("发生错误");
  333. });
  334. });
  335. Promise.all([pointsDataA, pointsDataD])
  336. .then((results) => {
  337. let pointsInfoA = results[0].data.length ? results[0].data : [];
  338. let pointsInfoD = results[1].data.length ? results[1].data : [];
  339. let partAInfos = [];
  340. let partDInfos = [];
  341. let chunk = 4;
  342. this.partAInfo.forEach((item, index) => {
  343. pointsInfoA.forEach((i, ind) => {
  344. if (index == ind) {
  345. item.value = i.pointValueInDouble;
  346. }
  347. });
  348. });
  349. for (let i = 0, j = this.partAInfo.length; i < j; i += chunk) {
  350. partAInfos.push(this.partAInfo.slice(i, i + chunk));
  351. }
  352. this.partDInfo.forEach((item, index) => {
  353. pointsInfoD.forEach((i, ind) => {
  354. if (index == ind) {
  355. item.value = i.pointValueInDouble;
  356. }
  357. });
  358. });
  359. for (let m = 0, n = this.partDInfo.length; m < n; m += chunk) {
  360. partDInfos.push(this.partDInfo.slice(m, m + chunk));
  361. }
  362. this.currentPartA = partAInfos;
  363. this.currentPartD = partDInfos;
  364. })
  365. .catch((e) => {
  366. // 失败的时候则返回最先被reject失败状态的值
  367. console.log("error", e);
  368. });
  369. },
  370. //打开报警页面
  371. handleAlarm(wtInfo) {
  372. this.$refs.alarmDialog &&
  373. this.$refs.alarmDialog.openDialog(
  374. wtInfo.wtid,
  375. this.wpid,
  376. this.wtInfo.wtType
  377. );
  378. },
  379. },
  380. };
  381. </script>
  382. <style lang="less" scoped>
  383. .wt-top {
  384. // height: 60px;
  385. width: 100%;
  386. // background: rgba(96, 103, 105, 0.2);
  387. border-radius: 5px;
  388. display: flex;
  389. flex-direction: column;
  390. color: #fff;
  391. font-size: 16px;
  392. .wt-row {
  393. display: flex;
  394. width: 100%;
  395. justify-content: space-between;
  396. }
  397. .wt-alarm {
  398. cursor: pointer;
  399. span {
  400. margin-left: 5px;
  401. }
  402. }
  403. .wt-info,
  404. .wt-xh {
  405. color: #959595;
  406. }
  407. .wt-xh {
  408. &:hover,
  409. &:active {
  410. font-weight: 700;
  411. }
  412. }
  413. &.green {
  414. color: #05bb4c;
  415. }
  416. &.blue {
  417. color: #3c88f7;
  418. }
  419. &.pink {
  420. color: #c530c8;
  421. }
  422. &.red {
  423. color: #ba3237;
  424. }
  425. &.orange {
  426. color: #e17d24;
  427. }
  428. &.white {
  429. color: #fff;
  430. }
  431. &.gray {
  432. color: #606769;
  433. }
  434. }
  435. .gf-wrapper {
  436. width: 100%;
  437. height: 100%;
  438. display: flex;
  439. .gf-img {
  440. width: 400px;
  441. height: 100%;
  442. display: flex;
  443. flex-direction: column;
  444. justify-content: space-between;
  445. padding: 20px;
  446. padding-top: 20px;
  447. padding-bottom: 150px;
  448. align-items: center;
  449. margin-right: 10px;
  450. background: rgba(96, 103, 105, 0.2);
  451. img {
  452. width: 100%;
  453. }
  454. }
  455. .part-info {
  456. width: calc(100% - 400px - 10px);
  457. height: 100%;
  458. display: flex;
  459. flex-direction: column-reverse;
  460. .part-body {
  461. width: 100%;
  462. height: 50%;
  463. overflow: auto;
  464. padding-bottom: 20px;
  465. // background: rgba(11, 12, 12, 0.45);
  466. background: rgba(96, 103, 105, 0.2);
  467. border-radius: 5px;
  468. margin-bottom: 10px;
  469. display: flex;
  470. flex-direction: column;
  471. align-items: center;
  472. padding: 10px 0;
  473. .monitoring-item {
  474. position: relative;
  475. width: 98%;
  476. height: 42px;
  477. border-bottom: 1px solid #363b46;
  478. display: flex;
  479. align-items: center;
  480. padding-left: 20px;
  481. font-size: 16px;
  482. font-family: Microsoft YaHei;
  483. font-weight: 400;
  484. color: #ffffff;
  485. }
  486. .point {
  487. width: 8px;
  488. height: 1px;
  489. background-color: #ffffff;
  490. position: absolute;
  491. &.point-left {
  492. left: 0;
  493. }
  494. &.point-right {
  495. right: 0;
  496. }
  497. &.top {
  498. top: -1px;
  499. }
  500. &.bottom {
  501. bottom: -1px;
  502. }
  503. }
  504. .part-item {
  505. width: 100%;
  506. height: calc(100% - 42px);
  507. overflow-y: auto;
  508. }
  509. .part {
  510. width: 100%;
  511. display: flex;
  512. flex-direction: row;
  513. margin-top: 5px;
  514. font-size: 13px;
  515. font-family: Source Han Sans SC;
  516. font-weight: 400;
  517. color: #959595;
  518. padding: 0 10px;
  519. .table-item {
  520. width: 25%;
  521. font-size: 12px;
  522. display: flex;
  523. flex-direction: row;
  524. align-items: center;
  525. justify-content: space-between;
  526. height: 33px;
  527. font-size: 12px;
  528. font-family: Microsoft YaHei;
  529. font-weight: 400;
  530. color: #b3b3b3;
  531. padding: 0 0px;
  532. .table-value {
  533. display: flex;
  534. flex-direction: row;
  535. align-items: baseline;
  536. font-family: Arial;
  537. font-weight: 400;
  538. color: #05bb4c;
  539. margin-right: 25px;
  540. .unit {
  541. font-size: 12px;
  542. font-family: Source Han Sans SC;
  543. font-weight: 400;
  544. color: #817c7c;
  545. margin-left: 5px;
  546. width: 40px;
  547. }
  548. &.round {
  549. width: 8px;
  550. height: 8px;
  551. border-radius: 50%;
  552. background-color: #05bb4c;
  553. margin-right: 90px;
  554. }
  555. &.round-red {
  556. width: 8px;
  557. height: 8px;
  558. border-radius: 50%;
  559. background-color: red;
  560. margin-right: 90px;
  561. }
  562. }
  563. }
  564. &.active {
  565. background-color: rgba(83, 89, 104, 0.15);
  566. }
  567. }
  568. }
  569. .yaoxin {
  570. margin-bottom: 0;
  571. }
  572. }
  573. }
  574. </style>