dust.modal.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. <template>
  2. <BasicModal v-bind="$attrs" destroyOnClose @register="register" :title="`粉尘监测详情 ${currentTime}`" width="1200px" >
  3. <div class="fiber-modal">
  4. <div class="modal-left">
  5. <div v-for="device in deviceList" class="link-item" :class="{'active-device-title': device.deviceID === activeDeviceID }" :key="device.deviceID">
  6. <span class="" @click="selectDevice(device.deviceID)">{{ device.stationname }}</span>
  7. </div>
  8. </div>
  9. <div class="modal-right">
  10. <div class="right-top">
  11. <div class="top-item">
  12. <div class="icon">
  13. <SvgIcon class="icon-style max-temperature" size="30" name="hd-wd" />
  14. </div>
  15. <div class="item-container">
  16. <div class="title">巷道温度</div>
  17. <div class="value"><span class="data">{{ dustMonitor.temperature }}</span> <span>℃</span> </div>
  18. </div>
  19. </div>
  20. <div class="top-item">
  21. <div class="icon">
  22. <SvgIcon class="icon-style min-temperature" size="30" name="dust-nd" />
  23. </div>
  24. <div class="item-container">
  25. <div class="title">粉尘浓度</div>
  26. <div class="value"><span class="data">{{ dustMonitor.humidity }}</span> <span>mg/m³</span></div>
  27. </div>
  28. </div>
  29. <div class="top-item">
  30. <div class="icon">
  31. <SvgIcon class="icon-style aveg-temperature" size="30" name="pw-sy" />
  32. </div>
  33. <div class="item-container">
  34. <div class="title">喷雾水压</div>
  35. <div class="value"><span class="data">{{ dustMonitor.waterPressure }}</span> <span>MPa</span></div>
  36. </div>
  37. </div>
  38. <div class="top-item warning-box">
  39. <div class="icon">
  40. <SvgIcon class="icon-style" size="30" name="pw-zz" />
  41. </div>
  42. <div class="item-container">
  43. <div class="title">喷雾装置</div>
  44. <div class="warning-value">低风险</div>
  45. </div>
  46. </div>
  47. <div class="top-item warning-box">
  48. <div class="icon">
  49. <SvgIcon class="icon-style" size="40" name="kg" />
  50. </div>
  51. <div class="item-container">
  52. <div class="title">喷雾开关</div>
  53. <div class="warning-value">
  54. <a-switch checked-children="开" un-checked-children="关" v-model:checked="dustSwitch" />
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. <div class="right-center">
  60. <span class="base-title">粉尘实时监测</span>
  61. <div class="dust-group">
  62. <div class="dust-item">
  63. <div class="title">粉尘浓度(实时)</div>
  64. <div class="value">{{ dustMonitor.breathWeighted }}<span>mg/m³</span></div>
  65. </div>
  66. <div class="dust-item">
  67. <div class="title">总尘浓度(时间加权)</div>
  68. <div class="value">{{ dustMonitor.totalDust }}<span>mg/m³</span></div>
  69. </div>
  70. <div class="dust-item">
  71. <div class="title">呼吸加权容许浓度</div>
  72. <div class="value">{{ dustMonitor.breathWeighted }}<span>mg/m³</span></div>
  73. </div>
  74. <div class="dust-item">
  75. <div class="title">爆炸浓度(煤尘)</div>
  76. <div class="value">{{ dustMonitor.dustval }}<span>mg/m³</span></div>
  77. </div>
  78. </div>
  79. </div>
  80. <div class="right-bottom">
  81. <span class="base-title">粉尘预测曲线</span>
  82. <div class="echarts-box">
  83. <BarAndLine
  84. xAxisPropType="readTime"
  85. :dataSource="posList"
  86. height="100%"
  87. :chartsColumns="chartsColumns"
  88. :option="echatsOption"
  89. chartsType="listMonitor" />
  90. </div>
  91. </div>
  92. </div>
  93. </div>
  94. </BasicModal>
  95. </template>
  96. <script lang="ts">
  97. import { defineComponent, ref, watch, shallowRef, reactive } from 'vue';
  98. import { BasicModal, useModalInner } from '/@/components/Modal';
  99. import BarAndLine from '/@/components/chart/BarAndLine.vue';
  100. import { SvgIcon } from '/@/components/Icon';
  101. import { Decoration7 as DvDecoration7, ScrollBoard as DvScrollBoard } from '@kjgl77/datav-vue3';
  102. import dayjs from 'dayjs'
  103. export default defineComponent({
  104. components: { BasicModal, BarAndLine, SvgIcon, DvScrollBoard, DvDecoration7 },
  105. props: {
  106. dataSource: {type: Array},
  107. activeID: {type: String}
  108. },
  109. setup(props) {
  110. const currentTime = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
  111. const modelRef = ref({});
  112. const loading = ref(true);
  113. const activeDeviceID = ref('');
  114. const deviceList = ref<any[]>([])
  115. const posList = ref<any[]>([])
  116. const dustMonitor = shallowRef({})
  117. const dustSwitch = ref(false)
  118. const echatsOption = {
  119. grid: {
  120. top: '20%',
  121. left: '2px',
  122. right: '10px',
  123. bottom: '3%',
  124. containLabel: true
  125. },
  126. toolbox: {
  127. feature: {}
  128. }
  129. }
  130. const chartsColumns = [
  131. {
  132. legend: '粉尘平均浓度',
  133. seriesName: '(mg/m³)',
  134. ymax: 5,
  135. yname: 'mg/m³',
  136. linetype: 'line',
  137. yaxispos: 'left',
  138. color: '#FDB146',
  139. sort: 1,
  140. xRotate: 0,
  141. dataIndex: 'hourAvg',
  142. },
  143. {
  144. legend: '粉尘最大浓度',
  145. seriesName: '(mg/m³)',
  146. ymax: 5,
  147. yname: 'mg/m³',
  148. linetype: 'line',
  149. yaxispos: 'left',
  150. color: '#EE6666',
  151. sort: 1,
  152. xRotate: 0,
  153. dataIndex: 'hourMax',
  154. },
  155. {
  156. legend: '粉尘最小浓度',
  157. seriesName: '(mg/m³)',
  158. ymax: 5,
  159. yname: 'mg/m³',
  160. linetype: 'line',
  161. yaxispos: 'left',
  162. color: '#9BCB75',
  163. sort: 1,
  164. xRotate: 0,
  165. dataIndex: 'hourMin',
  166. },
  167. ]
  168. const columns = [
  169. {
  170. title: '安装位置',
  171. dataIndex: 'position',
  172. width: 60,
  173. align: 'center',
  174. customRender: ({ index }) => {
  175. return `测点${index}`
  176. }
  177. },
  178. {
  179. title: '安装距离(m)',
  180. dataIndex: 'pos',
  181. align: 'center',
  182. width: 60,
  183. },
  184. {
  185. title: '测点温度',
  186. dataIndex: 'value',
  187. align: 'center',
  188. width: 50,
  189. },
  190. {
  191. title: '测点状态',
  192. dataIndex: 'state',
  193. align: 'center',
  194. width: 50,
  195. customRender: () => {
  196. return `正常`
  197. }
  198. },
  199. ];
  200. const warningConfig = reactive({
  201. data: [
  202. ['测点6', '318℃', '严重报警'],
  203. ['测点43', '142℃', '一般预警'],
  204. ['测点23', '167℃', '一版预警'],
  205. ['测点6', '198℃', '超高预警'],
  206. ['测点65', '197℃', '超高预警'],
  207. ['测点78', '154℃', '一般预警'],
  208. ['测点61', '104℃', '一般预警'],
  209. ['测点87', '150℃', '一般信息'],
  210. ],
  211. index: false,
  212. columnWidth: [150],
  213. oddRowBGC: '#009acd10',
  214. evenRowBGC: '#009acd05',
  215. align: ['center', 'center', 'center'],
  216. });
  217. const [register, { setModalProps }] = useModalInner();
  218. function handleVisibleChange(visible) {
  219. if (visible) {
  220. loading.value = true;
  221. setModalProps({ loading: true, confirmLoading: true });
  222. setTimeout(() => {
  223. loading.value = false;
  224. setModalProps({ loading: false, confirmLoading: false });
  225. }, 1000);
  226. }
  227. }
  228. // 选择监测
  229. function selectDevice (id){
  230. loading.value = true;
  231. setModalProps({ loading: true, confirmLoading: true });
  232. setTimeout(() => {
  233. loading.value = false;
  234. activeDeviceID.value = id
  235. setModalProps({ loading: false, confirmLoading: false });
  236. }, 300);
  237. }
  238. watch([() => props.dataSource, () => props.activeID], ([newDataSource, newActiveID], [oldDataSource, oldActiveID]) => {
  239. deviceList.value = newDataSource as any[]
  240. if(newActiveID != oldActiveID){
  241. activeDeviceID.value = newActiveID as string
  242. }
  243. newDataSource?.forEach((item:any, index) => {
  244. if((!activeDeviceID.value && index == 0) || item.deviceID === activeDeviceID.value){
  245. activeDeviceID.value = item.deviceID
  246. const list = item.summaryHour
  247. list.filter(data => {
  248. const date = new Date(); //1. js获取当前时间
  249. const min = date.getMinutes(); //2. 获取当前分钟
  250. return Object.assign(data, data.dustval, { readTime: (dayjs(date.setMinutes(min + 10))).format('YYYY-MM-DD HH:mm:ss') })
  251. })
  252. if(list.length > 0) posList.value = list
  253. dustMonitor.value = item.readData
  254. }
  255. })
  256. })
  257. return { register, model: modelRef, currentTime, dustSwitch, handleVisibleChange, selectDevice, deviceList, activeDeviceID, dustMonitor, echatsOption, posList, chartsColumns, columns, warningConfig };
  258. },
  259. });
  260. </script>
  261. <style lang="less" scoped>
  262. .fiber-modal{
  263. width: 100%;
  264. height: 600px;
  265. display: flex;
  266. flex-direction: row;
  267. justify-content: space-between;
  268. .modal-left{
  269. width: 200px;
  270. height: 100%;
  271. overflow-y: auto;
  272. background: #ffffff11;
  273. padding: 5px;
  274. border-radius: 5px;
  275. .active-device-title {
  276. color: aqua;
  277. }
  278. .link-item{
  279. position: relative;
  280. cursor: pointer;
  281. line-height: 30px;
  282. padding-left: 30px;
  283. span:hover{
  284. color: #89ffff;
  285. }
  286. &::after{
  287. content: '';
  288. position: absolute;
  289. display: block;
  290. width: 8px;
  291. height: 8px;
  292. top: 12px;
  293. left: 10px;
  294. transform: rotateZ(45deg) skew(10deg, 10deg);
  295. background: #45d3fd;
  296. }
  297. }
  298. }
  299. .modal-right{
  300. width: calc(100% - 220px);
  301. .base-title{
  302. line-height: 32px;
  303. position: relative;
  304. padding-left: 20px;
  305. &::after{
  306. content: '';
  307. position: absolute;
  308. display: block;
  309. width: 4px;
  310. height: 12px;
  311. top: 4px;
  312. left: 10px;
  313. background: #45d3fd;
  314. border-radius: 4px;
  315. }
  316. }
  317. .right-top{
  318. display: flex;
  319. flex-direction: row;
  320. justify-content: space-between;
  321. margin-bottom: 30px;
  322. padding: 0 10px;
  323. .top-item{
  324. width: 155px;
  325. height: 60px;
  326. display: flex;
  327. flex-direction: row;
  328. justify-content: center;
  329. align-items: center;
  330. background: url('/@/assets/images/vent/model_image/dust-monitor-bg.png') no-repeat;
  331. padding-top: 16px;
  332. .icon{
  333. width: 58px;
  334. height: 60px;
  335. display: flex;
  336. justify-content: center;
  337. align-items: center;
  338. position: relative;
  339. top: -8px;
  340. }
  341. .item-container{
  342. width: 100px;
  343. display: flex;
  344. flex-direction: column;
  345. // justify-content: start;
  346. div{
  347. padding-left: 8px;
  348. }
  349. .title{
  350. font-size: 14px;
  351. margin-bottom: 8px;
  352. }
  353. .value{
  354. position: relative;
  355. width: 110px;
  356. top: -8px;
  357. .data{
  358. display: inline-block;
  359. width: 50px;
  360. font-family: douyuFont;
  361. font-weight: 600;
  362. font-size: 14px;
  363. -webkit-background-clip: text;
  364. background-clip: text;
  365. color: #28DCE4;
  366. }
  367. span{
  368. font-family: Arial, Helvetica, sans-serif;
  369. font-size: 14px;
  370. color: #ffffffdd;
  371. }
  372. }
  373. }
  374. }
  375. .warning-box{
  376. padding-top: 0px;
  377. .icon{
  378. margin-top: 20px;
  379. .icon-style{
  380. color: #FDB146;
  381. }
  382. }
  383. .title{
  384. padding-top: 0px;
  385. }
  386. .warning-value{
  387. font-family: electronicFont;
  388. font-size: 18px;
  389. color: #61ddb1;
  390. }
  391. }
  392. }
  393. .right-center{
  394. margin-top: 20px;
  395. .dust-group{
  396. display: flex;
  397. flex-direction: row;
  398. justify-content: space-between;
  399. .dust-item{
  400. width: 238px;
  401. height: 148px;
  402. background: url('/@/assets/images/vent/model_image/dust-bg.png') no-repeat;
  403. scale: 0.9;
  404. .title{
  405. position: absolute;
  406. top: 80px;
  407. left: 70px;
  408. font-size: 16px;
  409. }
  410. .value{
  411. position: absolute;
  412. top: 50px;
  413. left: 50px;
  414. font-family: 'douyuFont';
  415. color: #20dbfd;
  416. text-shadow: 0 0 25px #00d8ff;
  417. font-size: 18px;
  418. font-weight: bolder;
  419. span{
  420. font-family: Arial, Helvetica, sans-serif;
  421. font-size: 16px;
  422. color: aliceblue;
  423. margin-left: 8px;
  424. }
  425. }
  426. }
  427. }
  428. }
  429. .right-bottom{
  430. margin-top: 20px;
  431. .echarts-box{
  432. width: 100%;
  433. height: 270px;
  434. }
  435. }
  436. }
  437. }
  438. </style>