nitrogenHome_lt.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. <template>
  2. <div id="nitrogen3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"></div>
  3. <div
  4. id="nitrogenCss3D"
  5. class="threejs-Object-CSS"
  6. style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 2; top: 0px; left: 0px"
  7. >
  8. <a-spin :spinning="loading" />
  9. <div v-for="groupNum in monitorDataGroupNum" :key="groupNum" class="modal-monitor">
  10. <fourBorderBg :class="`kyj${groupNum}`" :id="`nitrogenMonitor${groupNum}`">
  11. <div class="title">空压机{{ groupNum }} </div>
  12. <template v-for="(preMonitor, preMonitorIndex) in preMonitorList" :key="preMonitorIndex">
  13. <div class="monitor-item">
  14. <span class="monitor-title">{{ preMonitor.title }}:</span>
  15. <span class="monitor-val"
  16. ><span class="val">{{ monitorData[preMonitor.code] ? formatNum(monitorData[preMonitor.code]) : '-' }}</span
  17. ><span class="unit">{{ preMonitor.unit }}</span></span
  18. >
  19. </div>
  20. </template>
  21. </fourBorderBg>
  22. </div>
  23. </div>
  24. <div class="nitrogen-home">
  25. <div class="nitrogen-container">
  26. <div class="top-box">
  27. <!-- 左边监测数据 -->
  28. <div class="lr-box left-box">
  29. <ventBox1>
  30. <template #title>
  31. <div>注氮机监测</div>
  32. </template>
  33. <template #container>
  34. <div class="input-item" v-for="(preFan, index) in nitrogenMonitorData" :key="index">
  35. <div class="title">{{ preFan.title }}</div>
  36. <div class="value">{{ monitorData[preFan.code] >= 0 ? formatNum(Number(monitorData[preFan.code])) : '-' }}</div>
  37. <div class="unit">{{ preFan.unit !== 'signal' ? `(${preFan.unit})` : '' }}</div>
  38. </div>
  39. </template>
  40. </ventBox1>
  41. <div class="item item-l" v-for="groupNum in monitorDataGroupNum" :key="groupNum">
  42. <ventBox1>
  43. <template #title>
  44. <div>空压机{{ groupNum }}</div>
  45. </template>
  46. <template #container>
  47. <div class="monitor-box">
  48. <div class="monitor-item">
  49. <div class="state-item" v-for="(preFan, index) in preFanMonitorData" :key="index">
  50. <div class="state-title">{{ preFan.title + (preFan.unit !== 'signal' ? `(${preFan.unit})` : '') }}</div>
  51. <div
  52. :class="{
  53. 'signal-round': true,
  54. 'signal-round-warning': monitorData[preFan.code] == '1',
  55. 'signal-round-run': monitorData[preFan.code] == '0',
  56. 'signal-round-gry': monitorData[preFan.code] != '0' && monitorData[preFan.code] != '1',
  57. }"
  58. ></div>
  59. </div>
  60. </div>
  61. </div>
  62. </template>
  63. </ventBox1>
  64. </div>
  65. </div>
  66. <!-- 右边控制状态 -->
  67. <div class="lr-box right-box">
  68. <ventBox1 class="vent-margin-t-10">
  69. <template #title>
  70. <div>设备实时监测曲线</div>
  71. </template>
  72. <template #container>
  73. <BarAndLine
  74. v-if="chartsColumns.length > 0"
  75. xAxisPropType="readTime"
  76. :dataSource="echartData"
  77. height="340px"
  78. :chartsColumns="chartsColumns"
  79. chartsType="listMonitor"
  80. :option="echatsOption"
  81. />
  82. </template>
  83. </ventBox1>
  84. <div ref="playerRef" style="height: auto; width: 100%; margin-top: 10px"></div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. </template>
  90. <script lang="ts" setup name="nitrogenHome">
  91. import { onMounted, onUnmounted, ref, watch, reactive, defineProps, nextTick, inject } from 'vue';
  92. import ventBox1 from '/@/components/vent/ventBox1.vue';
  93. import fourBorderBg from '../../../comment/components/fourBorderBg.vue';
  94. import { mountedThree, destroy, setModelType } from '../nitrogen.threejs';
  95. import { getDevice } from '../nitrogen.api';
  96. import BarAndLine from '/@/components/chart/BarAndLine.vue';
  97. import { preMonitorList, preFanMonitorData, nitrogenMonitorData } from '../nitrogen.data.lt';
  98. import { formatNum } from '/@/utils/ventutil';
  99. import { useCamera } from '/@/hooks/system/useCamera';
  100. import lodash from 'lodash';
  101. const props = defineProps({
  102. deviceId: {
  103. type: String,
  104. require: true,
  105. },
  106. modalType: {
  107. type: String,
  108. require: true,
  109. },
  110. });
  111. const playerRef = ref();
  112. const refresh = ref(false);
  113. const loading = ref(true);
  114. // const kyjs = ['1号空压机', '1号空压机', '1号空压机', '1号空压机'];
  115. const flvURL1 = () => {
  116. // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
  117. return '';
  118. };
  119. const echatsOption = {
  120. grid: {
  121. top: '35%',
  122. left: '15%',
  123. right: '20px',
  124. bottom: '8%',
  125. // containLabel: true
  126. },
  127. toolbox: {
  128. feature: {},
  129. },
  130. };
  131. const monitorDataGroupNum = ref(1);
  132. const chartsColumns = ref([
  133. {
  134. legend: '瞬时流量',
  135. seriesName: '(m³/h)',
  136. ymax: 2000,
  137. yname: 'm³/h',
  138. linetype: 'line',
  139. yaxispos: 'left',
  140. color: '#FDB146',
  141. sort: 1,
  142. xRotate: 0,
  143. dataIndex: 'InputFlux',
  144. },
  145. ]);
  146. const { getCamera, removeCamera } = useCamera();
  147. const monitorData = ref({});
  148. //图表数据
  149. let echartData = ref<any>([]);
  150. // https获取监测数据
  151. let timer: null | NodeJS.Timeout = null;
  152. async function getMonitor(flag?) {
  153. if (Object.prototype.toString.call(timer) === '[object Null]') {
  154. return new Promise(async (resolve) => {
  155. timer = await setTimeout(
  156. async () => {
  157. if (props.deviceId) {
  158. await getDataSource(props.deviceId);
  159. }
  160. if (timer) {
  161. timer = null;
  162. }
  163. resolve(null);
  164. await getMonitor();
  165. },
  166. flag ? 0 : 3000
  167. );
  168. });
  169. }
  170. }
  171. async function getDataSource(systemID) {
  172. const res = await getDevice({ devicetype: 'sys', systemID, type: 'all' });
  173. if (res) {
  174. const result = res;
  175. if (!result || result.msgTxt.length < 1) return;
  176. result.msgTxt.forEach((item) => {
  177. if (item.type && item.type.startsWith('nitrogen')) {
  178. monitorData.value = Object.assign(item['datalist'][0], item['datalist'][0]['readData']);
  179. const airCompressor = { readTime: monitorData.value['readTime'].substring(11) };
  180. const dataArr = lodash.cloneDeep(echartData.value);
  181. //图表数据
  182. if (dataArr.length <= 5) {
  183. airCompressor[`InputFlux`] = monitorData.value['InputFlux'] || 0;
  184. dataArr.push(airCompressor);
  185. } else {
  186. dataArr.shift();
  187. dataArr.push(airCompressor);
  188. }
  189. echartData.value = dataArr;
  190. }
  191. });
  192. refresh.value = true;
  193. nextTick(() => {
  194. refresh.value = false;
  195. });
  196. }
  197. }
  198. watch([monitorDataGroupNum, loading], ([newMonitorDataGroupNum, newLoading]) => {
  199. nextTick(() => {
  200. if (newMonitorDataGroupNum && !newLoading) {
  201. setModelType(props.modalType, newMonitorDataGroupNum);
  202. }
  203. });
  204. });
  205. onMounted(async () => {
  206. await getMonitor(true);
  207. await mountedThree().then(() => {
  208. loading.value = false;
  209. });
  210. await getCamera(props.deviceId, playerRef.value);
  211. });
  212. onUnmounted(() => {
  213. destroy();
  214. removeCamera();
  215. if (timer) {
  216. clearTimeout(timer);
  217. timer = undefined;
  218. }
  219. });
  220. </script>
  221. <style lang="less" scoped>
  222. @ventSpace: zxm;
  223. .nitrogen-box {
  224. width: 100%;
  225. height: 100%;
  226. display: flex;
  227. justify-content: center;
  228. }
  229. #nitrogenCss3D {
  230. .modal-monitor {
  231. width: 200px;
  232. position: absolute;
  233. left: 0px;
  234. top: 0px;
  235. }
  236. &:deep(.win) {
  237. margin: 0 !important;
  238. background: #00000044;
  239. }
  240. }
  241. .nitrogen-home {
  242. width: 100%;
  243. height: 100%;
  244. position: fixed;
  245. z-index: 9999;
  246. display: flex;
  247. flex-direction: column;
  248. justify-content: center;
  249. align-items: center;
  250. pointer-events: none;
  251. top: 20px;
  252. .nitrogen-container {
  253. width: 100%;
  254. height: calc(100% - 100px);
  255. display: flex;
  256. justify-content: space-between;
  257. margin-bottom: 100px;
  258. .device-state {
  259. width: 100%;
  260. position: absolute;
  261. top: 20px;
  262. color: #e90000;
  263. display: flex;
  264. justify-content: center;
  265. font-size: 20px;
  266. }
  267. .top-box {
  268. width: 100%;
  269. padding: 10px;
  270. overflow: hidden;
  271. display: flex;
  272. justify-content: space-between;
  273. // margin-top: 40px;
  274. .center-item-box {
  275. position: absolute;
  276. left: 50%;
  277. top: 50px;
  278. transform: translate(-48%, 0);
  279. width: calc(100% - 720px);
  280. height: 50px;
  281. display: flex;
  282. align-items: center;
  283. pointer-events: auto;
  284. .top-left {
  285. display: flex;
  286. flex: 1.5;
  287. color: #fff;
  288. .button-box {
  289. position: relative;
  290. width: auto;
  291. height: 32px;
  292. display: flex;
  293. align-items: center;
  294. justify-content: center;
  295. border-radius: 5px;
  296. color: #fff;
  297. padding: 10px 15px;
  298. margin: 0px 10px;
  299. box-sizing: border-box;
  300. cursor: pointer;
  301. background: linear-gradient(#1fa6cb, #127cb5);
  302. &:hover {
  303. background: linear-gradient(#1fa6cbcc, #127cb5cc);
  304. }
  305. }
  306. }
  307. .top-center {
  308. display: flex;
  309. flex: 1;
  310. justify-content: center;
  311. align-items: center;
  312. font-size: 20px;
  313. color: #fff;
  314. .top-c-label {
  315. color: yellow;
  316. }
  317. }
  318. .top-right {
  319. display: flex;
  320. flex: 2;
  321. justify-content: right;
  322. align-items: center;
  323. color: #fff;
  324. .control-type {
  325. display: flex;
  326. color: #fff;
  327. .control-title {
  328. color: #73e8fe;
  329. }
  330. }
  331. }
  332. }
  333. .lr-box {
  334. height: 90%;
  335. display: flex;
  336. flex-direction: column;
  337. position: relative;
  338. // overflow: hidden;
  339. z-index: 9999;
  340. pointer-events: auto;
  341. overflow-y: auto;
  342. overflow-x: hidden;
  343. }
  344. .item {
  345. width: 305px;
  346. height: 450px;
  347. position: relative;
  348. border-radius: 5px;
  349. margin-top: 10px;
  350. margin-bottom: 0px;
  351. pointer-events: auto;
  352. color: #fff;
  353. // overflow: hidden;
  354. &:first-child {
  355. margin-top: 0px;
  356. }
  357. .base-title {
  358. color: #fff;
  359. margin-bottom: 8px;
  360. padding-left: 10px;
  361. position: relative;
  362. font-size: 16px;
  363. &::after {
  364. content: '';
  365. position: absolute;
  366. display: block;
  367. width: 4px;
  368. height: 12px;
  369. top: 7px;
  370. left: 0px;
  371. background: #45d3fd;
  372. border-radius: 4px;
  373. }
  374. }
  375. .monitor-item {
  376. width: 100%;
  377. display: flex;
  378. flex-direction: row;
  379. flex-wrap: wrap;
  380. .state-item {
  381. width: 50%;
  382. padding: 5px;
  383. display: flex;
  384. align-items: center;
  385. justify-content: space-between;
  386. .state-title {
  387. width: 100px;
  388. color: #ffffffdd;
  389. flex: 9;
  390. font-size: 14px;
  391. .unit {
  392. // color: #ffffffbb;
  393. }
  394. }
  395. .state-val {
  396. flex: 1;
  397. color: #e4a300;
  398. margin-right: 5px;
  399. text-align: right;
  400. font-size: 14px;
  401. }
  402. }
  403. }
  404. .signal-box {
  405. margin: 5px 0;
  406. display: flex;
  407. align-items: center;
  408. .signal-title {
  409. color: #7af5ff;
  410. margin: 0 5px;
  411. }
  412. &:last-child {
  413. margin-right: 0px;
  414. }
  415. }
  416. .list-item {
  417. padding: 0 10px;
  418. display: flex;
  419. justify-content: space-between;
  420. align-items: center;
  421. .item-data-key {
  422. color: #ffffff99;
  423. }
  424. }
  425. .item-data-box {
  426. color: #fff;
  427. .state-icon {
  428. display: inline-block;
  429. width: 12px;
  430. height: 12px;
  431. border-radius: 12px;
  432. }
  433. .open {
  434. border: 5px solid #133a56;
  435. background: #4ecb73;
  436. }
  437. .close {
  438. border: 5px solid #192961;
  439. background: #6d7898;
  440. }
  441. }
  442. }
  443. .item-l {
  444. width: 100%;
  445. .monitor-box {
  446. width: 100%;
  447. .parameter-title {
  448. position: relative;
  449. width: 100%;
  450. height: 14px;
  451. margin-top: 10px;
  452. .icon,
  453. span {
  454. position: absolute;
  455. top: -10px;
  456. }
  457. }
  458. .group-parameter-title {
  459. background-image: linear-gradient(to right, #39a3ff50, #39a3ff00);
  460. .icon {
  461. left: -12px;
  462. top: -17px;
  463. }
  464. span {
  465. left: 18px;
  466. }
  467. .item-col {
  468. background-image: linear-gradient(to right, #39a3ff00, #39a3ff10);
  469. }
  470. }
  471. .device-parameter-title {
  472. background-image: linear-gradient(to right, #3df6ff40, #3df6ff00);
  473. .icon {
  474. left: -10px;
  475. top: -14px;
  476. }
  477. span {
  478. left: 18px;
  479. }
  480. .item-col {
  481. background-image: linear-gradient(to right, #3df6ff10, #3df6ff00);
  482. }
  483. }
  484. }
  485. }
  486. .right-box {
  487. width: 300px;
  488. margin-top: 50px;
  489. }
  490. .left-box {
  491. width: 335px;
  492. margin-top: 80px;
  493. .input-item {
  494. display: flex;
  495. justify-content: space-between;
  496. align-items: center;
  497. padding: 4px 8px;
  498. margin: 6px 0;
  499. background-image: linear-gradient(to right, #39deff15, #3977e500);
  500. .title {
  501. width: 200px;
  502. }
  503. .title-auto {
  504. width: auto;
  505. }
  506. .input-value {
  507. width: 80px;
  508. height: 28px;
  509. line-height: 28px !important;
  510. background: transparent !important;
  511. border-color: #228da2 !important;
  512. color: #fff !important;
  513. }
  514. .value {
  515. width: 100px;
  516. color: #00d8ff;
  517. padding-right: 20px;
  518. }
  519. .unit {
  520. width: 80px;
  521. }
  522. }
  523. }
  524. }
  525. &:deep(.win) {
  526. width: 100%;
  527. margin: 0 !important;
  528. }
  529. }
  530. }
  531. &:deep(.main) {
  532. .title {
  533. height: 34px;
  534. text-align: center;
  535. font-weight: 600;
  536. color: #7af5ff;
  537. // background-image: url('../../../assets/img/yfj/light.png');
  538. background-repeat: no-repeat;
  539. background-position-x: center;
  540. background-position-y: 100%;
  541. background-size: 80%;
  542. font-size: 16px;
  543. }
  544. .monitor-item {
  545. width: 200px;
  546. display: flex;
  547. flex-direction: row;
  548. width: auto;
  549. margin-bottom: 3px;
  550. .monitor-val {
  551. color: #ffb700;
  552. display: flex;
  553. width: auto;
  554. .val {
  555. width: 80px;
  556. font-size: 14px;
  557. }
  558. .unit {
  559. color: #ffffffbb;
  560. font-size: 14px;
  561. }
  562. }
  563. }
  564. .monitor-title {
  565. width: 100px;
  566. color: #7af5ff;
  567. font-weight: 400;
  568. font-size: 14px;
  569. }
  570. .signal-item {
  571. display: flex;
  572. justify-content: space-between;
  573. // margin-bottom: 5px;
  574. .signal-round {
  575. display: inline-block;
  576. width: 8px;
  577. height: 8px;
  578. border-radius: 50%;
  579. margin: 0 10px;
  580. position: relative;
  581. &::after {
  582. display: block;
  583. content: '';
  584. position: absolute;
  585. width: 12px;
  586. height: 12px;
  587. top: -2px;
  588. left: -2px;
  589. border-radius: 50%;
  590. }
  591. }
  592. .signal-round-gry {
  593. background-color: #858585;
  594. &::after {
  595. background-color: #85858544;
  596. box-shadow: 0 0 1px 1px #85858599;
  597. }
  598. }
  599. .signal-round-run {
  600. background-color: #67fc00;
  601. &::after {
  602. background-color: #67fc0044;
  603. box-shadow: 0 0 1px 1px #c6ff77;
  604. }
  605. }
  606. .signal-round-warning {
  607. background-color: #e9170b;
  608. &::after {
  609. background-color: #e9170b44;
  610. box-shadow: 0 0 1px 1px #e9170b;
  611. }
  612. }
  613. }
  614. }
  615. :deep(.zxm-radio-wrapper) {
  616. color: #fff !important;
  617. }
  618. </style>