workerFace.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. <template>
  2. <div class="center-container">
  3. <div class="lr-box left-box">
  4. <div class = "container-title">
  5. <a-select
  6. class="title-select"
  7. ref="select"
  8. v-model:value="currentTitleValue"
  9. @change="handleTitleChange"
  10. >
  11. <a-select-option value="2">15212工作面</a-select-option>
  12. <a-select-option value="1598491318007898113">采煤工作面</a-select-option>
  13. <a-select-option value="3">掘进工作面</a-select-option>
  14. </a-select>
  15. </div>
  16. <div class="item">
  17. <dv-decoration7 style="height:30px;">
  18. <div class="base-title">监测信息</div>
  19. </dv-decoration7>
  20. <div class="need-air-group vent-flex-row">
  21. <div class="air-box">
  22. <div class="title">总进风量</div>
  23. <div class="air-num">10000</div>
  24. </div>
  25. <div class="air-box">
  26. <div class="title">总回风量</div>
  27. <div class="air-num">80000</div>
  28. </div>
  29. <div class="air-box">
  30. <div class="title">总需风量</div>
  31. <div class="air-num">90000</div>
  32. </div>
  33. </div>
  34. <div class="item-container">
  35. <BarAndLineCustom
  36. xAxisPropType="time"
  37. :chartData="monitorData"
  38. height="240px"
  39. :propTypeArr="['jin', 'hui']"
  40. :option="echartsOption" />
  41. </div>
  42. </div>
  43. <div class="item ">
  44. <dv-decoration7 style="height:30px;">
  45. <div class="base-title">基本信息</div>
  46. </dv-decoration7>
  47. <div class="base-information-box">
  48. <div class="base-information">
  49. <div v-for="(device, index) in workerFaceDeviceList" :key="index" class="device-num-box">
  50. <div class="icon"></div>
  51. <div class="text-box">
  52. <div class="title">{{ device.title }}</div>
  53. <div class="value">{{ device.value }}套</div>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. <div class="lr-box right-box">
  61. <div class="warning-box">
  62. <dv-decoration7 style="height:30px;">
  63. <div class="base-title">报警信息</div>
  64. </dv-decoration7>
  65. <div class="warning-top">
  66. <div class="warning-icon">
  67. <div class="title">告警信息</div>
  68. <div class="num-box">
  69. <div class="num">20</div>
  70. <div class="rate-box">
  71. <div class="day-rate">日环比: +2%</div>
  72. <div class="week-rate">周环比: +2%</div>
  73. <div class="moth-rate">月环比: +2%</div>
  74. </div>
  75. </div>
  76. </div>
  77. <div class="warning-icon">
  78. <div class="title">预警信息</div>
  79. <div class="num-box">
  80. <div class="num">20</div>
  81. <div class="rate-box">
  82. <div class="day-rate">日环比: +2%</div>
  83. <div class="week-rate">周环比: +2%</div>
  84. <div class="moth-rate">月环比: +2%</div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. <div class="warning-monitor">
  91. <dv-scroll-board ref="scrollBoard" :config="warningConfig" style="width:100%;height:220px" />
  92. </div>
  93. <div class="device-monitor-box">
  94. <dv-decoration7 style="height:30px;">
  95. <div class="base-title">设备信息</div>
  96. </dv-decoration7>
  97. <div class="device-btn-group">
  98. <div v-for="deviceType in deviceTypes" class="device-btn" :class="{'device-active': deviceActive === deviceType.type}" :key="deviceType.type" @click="showDeviceMonitor(deviceType)">{{ deviceType.text }}</div>
  99. </div>
  100. <div class="device-table" :class="{'device-table-open': deviceActive, 'device-table-close': !deviceActive }">
  101. <div class="vent-flex-row device-tab">
  102. <div class="tab tab-active">设备监测</div>
  103. <a-divider type="vertical" style=" height: 10px; background-color: #aaa" />
  104. <div class="tab">历史信息</div>
  105. </div>
  106. <div class="device-animation">
  107. <MonitorTable
  108. class="monitor-table"
  109. :columnsType="deviceColumnsType"
  110. :dataSource="deviceMonitorData"
  111. title="风门监测"
  112. :isShowSelect="false"
  113. :isShowPagination = "false"
  114. :isShowActionColumn="true"
  115. :scroll="{ y: 160 }"
  116. >
  117. <template #filterCell="{ column, record }">
  118. <template v-if="record.frontGateOpenCtrl">
  119. <a-tag v-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 0 && record.frontGateClose == 0" color="red">正在打开</a-tag>
  120. <a-tag v-else-if="column.dataIndex === 'frontGateOpen'" color="processing">打开</a-tag>
  121. </template>
  122. <template v-else>
  123. <a-tag v-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 0 && record.frontGateClose == 0" color="red">正在关闭</a-tag>
  124. <a-tag v-else-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 0 && record.frontGateClose == 1" color="default">关闭</a-tag>
  125. <a-tag v-else-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 1 && record.frontGateClose == 0" color="default">打开</a-tag>
  126. </template>
  127. <template v-if="record.rearGateOpenCtrl">
  128. <a-tag v-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 0 && record.rearGateClose == 0" color="red">正在打开</a-tag>
  129. <a-tag v-else-if="column.dataIndex === 'rearGateOpen'" color="processing">打开</a-tag>
  130. </template>
  131. <template v-else>
  132. <a-tag v-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 0 && record.rearGateClose == 0" color="red">正在关闭</a-tag>
  133. <a-tag v-else-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 0 && record.rearGateClose == 1" color="default">关闭</a-tag>
  134. <a-tag v-else-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 1 && record.rearGateClose == 0" color="default">打开</a-tag>
  135. </template>
  136. <a-tag v-if="column.dataIndex === 'warnFlag'" :color="record.warnFlag == 0 ? 'green' : 'red'">{{
  137. record.warnFlag == 0 ? '正常' : '报警'
  138. }}</a-tag>
  139. <a-tag v-if="column.dataIndex === 'netStatus'" :color="record.netStatus == 0 ? 'default' : 'green'">{{
  140. record.netStatus == 0 ? '断开' : '连接'
  141. }}</a-tag>
  142. </template>
  143. <template #action="{ record }">
  144. <TableAction
  145. :actions="[
  146. {
  147. label: '详情',
  148. onClick: goDetail.bind(null, record),
  149. },
  150. {
  151. label: '定位',
  152. onClick: goDetail.bind(null, record),
  153. },
  154. ]"
  155. />
  156. </template>
  157. </MonitorTable>
  158. </div>
  159. </div>
  160. </div>
  161. </div>
  162. </div>
  163. </template>
  164. <script lang="ts" setup>
  165. import { TableAction } from '/@/components/Table';
  166. import { onMounted, onUnmounted, ref, reactive } from 'vue'
  167. import { Decoration7 as DvDecoration7, ScrollBoard as DvScrollBoard, BorderBox7 as DvBorderBox7 } from '@kjgl77/datav-vue3'
  168. import { workerFaceDeviceList } from "../home.data";
  169. import BarAndLineCustom from '/@/components/chart/BarAndLineCustom.vue';
  170. import { list, deviceMonitor } from '../home.api'
  171. import echarts from '/@/utils/lib/echarts'
  172. import MonitorTable from '/@/views/vent/monitorManager/comment/MonitorTable.vue';
  173. const currentTitleValue = ref('2') // 监测工作面id
  174. const monitorData = ref([]) // 存放监测数据
  175. const echartsOption = reactive(
  176. {
  177. tooltip: { trigger: 'axis', axisPointer: { lineStyle: { color: '#fff' } } },
  178. legend: {
  179. top: '10',
  180. icon: 'rect',
  181. // itemWidth: 14, itemHeight: 5, itemGap: 10,
  182. data: ['进风', '回风'],
  183. right: '10px',
  184. textStyle: { fontSize: 12, color: '#fff' }
  185. },
  186. grid: { x: 50, y: 50, x2: 12, y2: 40 },
  187. xAxis: {
  188. type: 'category',
  189. boundaryGap: false,
  190. axisLine: { lineStyle: { color: '#57617B' } },
  191. axisLabel: { textStyle: { color: '#ffffffcc' } },
  192. splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed', } },
  193. data: []
  194. },
  195. yAxis: [{
  196. type: 'value',
  197. name:'m³/min',
  198. axisTick: {
  199. show: false
  200. },
  201. axisLine: { lineStyle: { show: true, color: '#57617B' } },
  202. axisLabel: { margin: 10, textStyle: { fontSize: 12, color: '#ffffffcc' }},
  203. splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed', } }
  204. }],
  205. series: [{
  206. name: '进风', type: 'line', smooth: true, lineStyle: { normal: { width: 2 } },
  207. yAxisIndex: 0,
  208. areaStyle: {
  209. normal: {
  210. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  211. offset: 0,
  212. color: 'rgba(185,150,248,0.3)'
  213. }, {
  214. offset: 0.8,
  215. color: 'rgba(185,150,248,0)'
  216. }], false),
  217. shadowColor: 'rgba(0, 0, 0, 0.1)',
  218. shadowBlur: 10
  219. }
  220. },
  221. itemStyle: { normal: { color: '#B996F8' } },
  222. data: []
  223. }, {
  224. name: '回风', type: 'line', smooth: true, lineStyle: { normal: { width: 2 } },
  225. yAxisIndex: 0,
  226. areaStyle: {
  227. normal: {
  228. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  229. offset: 0,
  230. color: 'rgba(3, 194, 236, 0.3)'
  231. }, {
  232. offset: 0.8,
  233. color: 'rgba(3, 194, 236, 0)'
  234. }], false),
  235. shadowColor: 'rgba(0, 0, 0, 0.1)',
  236. shadowBlur: 10
  237. }
  238. },
  239. itemStyle: { normal: { color: '#03C2EC' } },
  240. data: []
  241. }]
  242. }
  243. )
  244. const warningConfig = reactive({
  245. data: [
  246. ['15211辅运顺槽', '测风装置', '异常信息'],
  247. ['2-2煤辅运大巷4联巷对面胶运联巷', '气源压力', '异常信息'],
  248. ['3-1煤回风延伸', '平均风速', '异常信息'],
  249. ['2-4煤辅运大巷水仓', '风门', '异常信息'],
  250. ['4-2煤南部集中回风二联巷', '测风装置', '异常信息'],
  251. ['5-2煤回风大巷西侧', '测风装置', '异常信息'],
  252. ['2-2煤辅运大巷三联巷', '风门', '异常信息'],
  253. ['利民风窗', '风窗', '异常信息'],
  254. ],
  255. index: false,
  256. columnWidth: [150],
  257. oddRowBGC: '#003B5155',
  258. evenRowBGC: '#0A273255',
  259. align: ['center', 'center', 'center'],
  260. })
  261. // 监测设备类型集合
  262. const deviceTypes = ref([
  263. {
  264. text: '风门',
  265. type: 'gate_normal',
  266. columnsType: 'gate_monitor'
  267. },
  268. {
  269. text: '风窗',
  270. type: 'window_normal',
  271. columnsType: 'window_monitor'
  272. },
  273. {
  274. text: '测风装置',
  275. type: 'windrect_rect',
  276. columnsType: 'windrect_monitor'
  277. },
  278. ])
  279. const deviceActive = ref('') //当前监测的设备
  280. const deviceColumnsType = ref('') //存放当前监测的Columns的key值
  281. const deviceMonitorData = ref([]) //存放监测的数据集合
  282. // const deviceType =
  283. // 标题选择
  284. function handleTitleChange() {
  285. //
  286. }
  287. function showDeviceMonitor(deviceType) {
  288. if(deviceActive.value === deviceType.type){
  289. deviceActive.value = ''
  290. }else {
  291. deviceColumnsType.value = deviceType.columnsType
  292. deviceActive.value = deviceType.type
  293. }
  294. }
  295. let timer: null | NodeJS.Timeout | undefined = null;
  296. function getMonitor() {
  297. if (timer == null) {
  298. timer = setTimeout(async () => {
  299. // 首页监测
  300. const result = await list({})
  301. if (result) {
  302. const list = result['sys_surface']
  303. const currentObj = list.find((item) => {
  304. return item.deviceID == currentTitleValue.value
  305. })
  306. if(currentObj){
  307. monitorData.value = currentObj['history']
  308. }
  309. }
  310. // 设备监测
  311. const deviceMonitorList = await deviceMonitor({ devicetype: 'sys', pagetype: 'normal', systemID: '2'})
  312. deviceMonitorList.forEach(item => {
  313. if(item['msgTxt']['type'] === deviceActive.value){
  314. deviceMonitorData.value = item['msgTxt']['datalist']
  315. }
  316. })
  317. if (timer) {
  318. timer = null
  319. }
  320. getMonitor()
  321. }, 1000)
  322. }
  323. }
  324. function goDetail() {
  325. }
  326. onMounted(() => {
  327. getMonitor()
  328. })
  329. onUnmounted(() => {
  330. if(timer)
  331. timer = undefined
  332. })
  333. </script>
  334. <style lang="less" scoped>
  335. @ventSpace: zxm;
  336. .center-container{
  337. width: 100%;
  338. height: calc(100% - 100px);
  339. display: flex;
  340. justify-content: space-between;
  341. position: absolute;
  342. top: 90px;
  343. .lr-box {
  344. height: 100%;
  345. width: 347px;
  346. color: #fff;
  347. display: flex;
  348. flex-direction: column;
  349. pointer-events: auto;
  350. .container-title {
  351. width: 398px;
  352. height: 34px;
  353. position: relative;
  354. top: -30px;
  355. background: url('/@/assets/images/vent/new-home/container-title-bg.png') no-repeat;
  356. background-size: contain;
  357. padding: 0 0 0 180px;
  358. font-size: 20px;
  359. pointer-events: auto;
  360. position: relative;
  361. .title-select {
  362. width: 198px;
  363. position: absolute;
  364. top: 0;
  365. left: 180px;
  366. }
  367. }
  368. .item {
  369. // flex: 1;
  370. width: 100%;
  371. display: flex;
  372. justify-content: center;
  373. flex-direction: column;
  374. min-height: 200px;
  375. margin-bottom: 20px;
  376. align-items: center;
  377. .item-container {
  378. width: 100%;
  379. height: 100%;
  380. }
  381. }
  382. .need-air-group{
  383. width: calc(100% - 20px);
  384. display: flex;
  385. justify-content: space-between;
  386. border: 1px solid #20dbfd22;
  387. box-shadow: 0 0 5px #00d8ff22 inset;
  388. padding: 10px;
  389. margin: 10px 10px 0 10px;
  390. .air-box{
  391. display: flex;
  392. flex-direction: column;
  393. justify-content: center;
  394. align-items: center;
  395. .title{
  396. margin-left: 5px;
  397. }
  398. .air-num{
  399. font-family: 'numberFont';
  400. color: #20dbfd;
  401. text-shadow: 0 0 25px #00d8ff;
  402. font-size: 28px;
  403. font-weight: bolder;
  404. }
  405. }
  406. }
  407. .base-title {
  408. width: calc(100% - 60px);
  409. text-align: center;
  410. color: #00d8ff;
  411. }
  412. .base-information-box{
  413. display: flex;
  414. margin-left: 5px;
  415. .base-information {
  416. display: flex;
  417. flex-direction: row;
  418. flex-wrap: wrap;
  419. .device-num-box {
  420. width: 170px;
  421. height: 82px;
  422. background: url('/@/assets/images/vent/new-home/num-bg.png') no-repeat;
  423. background-size: contain;
  424. margin: 5px 0px;
  425. position: relative;
  426. .icon {
  427. position: absolute;
  428. width: 40px;
  429. height: 40px;
  430. background: url('/@/assets/images/vent/new-home/base-icon1.png') no-repeat;
  431. background-size: contain;
  432. top: 22px;
  433. left: 16px;
  434. }
  435. .text-box {
  436. height: 100%;
  437. margin-left: 70px;
  438. display: flex;
  439. justify-content: center;
  440. flex-direction: column;
  441. margin-top: 2px;
  442. .value {
  443. font-family: 'douyuFont';
  444. color: #28DCE4;
  445. margin-top: 5px;
  446. }
  447. }
  448. }
  449. }
  450. }
  451. .warning-box{
  452. .warning-top{
  453. display: flex;
  454. justify-content: space-between;
  455. padding: 10px 2px 0px 2px;
  456. .warning-icon{
  457. width: 168px;
  458. height: 105px;
  459. display: flex;
  460. flex-direction: column;
  461. background: url('/@/assets/images/vent/new-home/warning-bg.png') no-repeat;
  462. background-size: contain;
  463. .title{
  464. font-size: 13px;
  465. margin: 5px 0 5px 14px;
  466. }
  467. .num-box{
  468. display: flex;
  469. margin-left: 20px;
  470. .num{
  471. font-family: 'numberFont';
  472. font-size: 34px;
  473. color: #20dbfd;
  474. text-shadow: 0 0 25px #00d8ff;
  475. margin-right: 10px;
  476. }
  477. .rate-box{
  478. font-size: 12px;
  479. .day-rate{
  480. color: #FE3E12;
  481. }
  482. .week-rate{
  483. color: #FADB3E;
  484. }
  485. .moth-rate{
  486. color: #12FE81;
  487. }
  488. }
  489. }
  490. }
  491. }
  492. }
  493. .device-monitor-box{
  494. margin-top: 20px;
  495. position: reactive;
  496. .device-btn-group{
  497. display: flex;
  498. flex-wrap: wrap;
  499. margin-top: 10px;
  500. .device-active{
  501. &::before{
  502. border-color: #0efcff;
  503. box-shadow: 1px 1px 3px 1px #0efcff inset;
  504. }
  505. }
  506. .device-btn{
  507. width: 100px;
  508. height: 40px;
  509. position: relative;
  510. display: flex;
  511. justify-content: center;
  512. align-items: center;
  513. font-size: 14px;
  514. color: #0efcff;
  515. cursor: pointer;
  516. margin: 0 6px;
  517. &::before{
  518. content: '';
  519. position: absolute;
  520. top: 0;
  521. right: 0;
  522. bottom: 0;
  523. left: 0;
  524. border: 1px solid #6176AF;
  525. transform: skewX(-38deg);
  526. }
  527. }
  528. }
  529. .device-table{
  530. position: absolute;
  531. width: 1550px;
  532. height: 270px;
  533. right: 0;
  534. bottom: 0;
  535. backdrop-filter: blur(30px);
  536. border: 1px solid #8b8b8b22;
  537. padding: 2px 0 10px 10px;
  538. z-index: 9999;
  539. &::before{
  540. position: absolute;
  541. content: '';
  542. width: 10px;
  543. height: 10px;
  544. border-top: 1px solid #00d8ff;
  545. border-left: 1px solid #00d8ff;
  546. left: 0px;
  547. top: -1px;
  548. }
  549. &::after{
  550. position: absolute;
  551. content: '';
  552. width: 10px;
  553. height: 10px;
  554. border-bottom: 1px solid #00d8ff;
  555. border-left: 1px solid #00d8ff;
  556. left: 0px;
  557. bottom: -1px;
  558. }
  559. .device-tab{
  560. width: 100%;
  561. .tab{
  562. margin: 5px;
  563. cursor: pointer;
  564. }
  565. .tab-active{
  566. color: #00d8ff;
  567. }
  568. }
  569. .device-animation{
  570. border-bottom: 1px solid #91e9fe44;
  571. }
  572. .monitor-table{
  573. background-color: #67e6fd05;
  574. }
  575. }
  576. .device-table-open{
  577. width: 1550;
  578. animation-name: open;
  579. /* 持续时间 */
  580. animation-duration: 2s;
  581. transition: all 2s linear 1s;
  582. }
  583. .device-table-close{
  584. width: 0px;
  585. animation-name: close;
  586. /* 持续时间 */
  587. animation-duration: 2s;
  588. transition: all 2s linear 1s;
  589. }
  590. }
  591. }
  592. }
  593. :deep(.@{ventSpace}-table-thead){
  594. background-color: transparent !important;
  595. th{
  596. color: #00d8ff !important;
  597. border-color: #91e9fe44 !important;
  598. border: none !important;
  599. border-top: 1px solid #91e9fe44 !important;
  600. &:first-child{
  601. border-left: 1px solid #91e9fe44 !important;
  602. }
  603. &:last-child{
  604. border-right: 1px solid #91e9fe44 !important;
  605. }
  606. .@{ventSpace}-table-column-title{
  607. color: #00d8ff !important;
  608. }
  609. .@{ventSpace}-table-cell-scrollbar{
  610. box-shadow: none !important;
  611. }
  612. }
  613. }
  614. :deep(.@{ventSpace}-table-tbody){
  615. tr{
  616. td{
  617. background-color: transparent !important;
  618. border-bottom: 1px solid #91e9fe33 !important;
  619. // border-top: none !important;
  620. // border-left: none !important;
  621. &:first-child{
  622. border-left: 1px solid #91e9fe44 !important;
  623. }
  624. &:last-child{
  625. border-right: 1px solid #91e9fe44 !important;
  626. }
  627. }
  628. &:last-child{
  629. td{
  630. border-bottom: 1px solid #91e9fe44 !important;
  631. }
  632. }
  633. }
  634. }
  635. @keyframes open {
  636. /* 开始状态 */
  637. 0% {
  638. opacity: 0;
  639. width: 0px;
  640. }
  641. /* 结束状态 */
  642. 100% {
  643. opacity: 1;
  644. width: 1550px;
  645. }
  646. }
  647. @keyframes close {
  648. /* 开始状态 */
  649. 0% {
  650. opacity: 1;
  651. width: 1550px;
  652. }
  653. /* 结束状态 */
  654. 100% {
  655. opacity: 0;
  656. width: 0px;
  657. }
  658. }
  659. </style>