bundle.modal.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <template>
  2. <BasicModal v-bind="$attrs" @register="register" :title="`束管监测详情 ${currentTime}`" width="1200px" @ok="handleOk" @cancel="handleCancel" >
  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.strinstallpos }}</span>
  7. </div>
  8. </div>
  9. <div class="modal-right">
  10. <span class="base-title">实时监测参数</span>
  11. <div class="right-top">
  12. <div class="top-item">
  13. <div class="icon">
  14. <SvgIcon class="icon-style" name="coval" style="width: 62px; height: 38px; margin-top: 10px;" />
  15. </div>
  16. <div class="item-container">
  17. <div class="title">一氧化碳</div>
  18. <div class="value">{{ posMonitor.coval }} <span>ppm</span> </div>
  19. </div>
  20. </div>
  21. <div class="top-item">
  22. <div class="icon">
  23. <SvgIcon class="icon-style" name="co2val" style="width: 72px; height: 46px;" />
  24. </div>
  25. <div class="item-container">
  26. <div class="title">二氧化碳</div>
  27. <div class="value">{{ posMonitor.co2val }} <span>%</span></div>
  28. </div>
  29. </div>
  30. <div class="top-item">
  31. <div class="icon">
  32. <SvgIcon class="icon-style" name="gasval" style="width: 72px; height: 46px;"/>
  33. </div>
  34. <div class="item-container">
  35. <div class="title">甲烷</div>
  36. <div class="value">{{ posMonitor.gasval }} <span>%</span></div>
  37. </div>
  38. </div>
  39. <div class="top-item">
  40. <div class="icon">
  41. <SvgIcon class="icon-style" name="ch2val" style="width: 76px; height: 42px;"/>
  42. </div>
  43. <div class="item-container">
  44. <div class="title">乙烯</div>
  45. <div class="value">{{ posMonitor.ch2val }} <span>ppm</span></div>
  46. </div>
  47. </div>
  48. <div class="top-item">
  49. <div class="icon">
  50. <SvgIcon class="icon-style" name="chval" style="width: 76px; height: 42px;" />
  51. </div>
  52. <div class="item-container">
  53. <div class="title">乙炔</div>
  54. <div class="value">{{ posMonitor.chval }} <span>ppm</span></div>
  55. </div>
  56. </div>
  57. <div class="top-item">
  58. <div class="icon">
  59. <SvgIcon class="icon-style" name="o2val" style="width: 76px; height: 50px;"/>
  60. </div>
  61. <div class="item-container">
  62. <div class="title">氧气</div>
  63. <div class="value">{{ posMonitor.o2val }} <span>%</span></div>
  64. </div>
  65. </div>
  66. <div class="top-item warning-box">
  67. <div class="icon">
  68. <SvgIcon class="icon-style" size="42" name="alarm-warning" style="margin-top: 5px;" />
  69. </div>
  70. <div class="item-container">
  71. <div class="title">风险等级</div>
  72. <div class="warning-value">低风险</div>
  73. </div>
  74. </div>
  75. <div class="top-item warning-box">
  76. <div class="icon">
  77. <SvgIcon class="icon-style" size="42" name="link" style="margin-top: 5px;"/>
  78. </div>
  79. <div class="item-container">
  80. <div class="title">连接状态</div>
  81. <div class="warning-value">连接</div>
  82. </div>
  83. </div>
  84. </div>
  85. <div class="right-bottom">
  86. <span class="base-title">设备监测曲线</span>
  87. <div class="echarts-box">
  88. <BarAndLine
  89. class="echarts-line"
  90. xAxisPropType="readTime"
  91. :dataSource="deviceList"
  92. height="100%"
  93. :chartsColumns="chartsColumns"
  94. :option="echatsOption"
  95. chartsType="listMonitor" />
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </BasicModal>
  101. </template>
  102. <script lang="ts">
  103. import { defineComponent, ref, watch, shallowRef, reactive } from 'vue';
  104. import { BasicModal, useModalInner } from '/@/components/Modal';
  105. import BarAndLine from '/@/components/chart/BarAndLine.vue';
  106. import { SvgIcon } from '/@/components/Icon';
  107. import { Decoration7 as DvDecoration7, ScrollBoard as DvScrollBoard } from '@kjgl77/datav-vue3';
  108. import dayjs from 'dayjs'
  109. export default defineComponent({
  110. components: { BasicModal, BarAndLine, SvgIcon, DvScrollBoard, DvDecoration7 },
  111. props: {
  112. dataSource: {type: Array},
  113. activeID: {type: String}
  114. },
  115. setup(props) {
  116. const currentTime = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
  117. const modelRef = ref({});
  118. const loading = ref(true);
  119. const activeDeviceID = ref('');
  120. const deviceList = ref<any[]>([])
  121. const posList = ref<any[]>([])
  122. const posMonitor = shallowRef({})
  123. const echatsOption = {
  124. grid: {
  125. top: '25%',
  126. left: '0%',
  127. right: '0%',
  128. bottom: '3%',
  129. containLabel: true
  130. },
  131. toolbox: {
  132. feature: {}
  133. }
  134. }
  135. const chartsColumns = [
  136. {
  137. legend: '一氧化碳',
  138. seriesName: '(ppm)',
  139. ymax: 20,
  140. yname: 'ppm',
  141. linetype: 'line',
  142. yaxispos: 'left',
  143. color: '#FDB146',
  144. sort: 1,
  145. xRotate: 0,
  146. dataIndex: 'coval',
  147. },
  148. {
  149. legend: '二氧化碳',
  150. seriesName: '(%)',
  151. ymax: 10,
  152. yname: '%',
  153. linetype: 'line',
  154. yaxispos: 'right',
  155. color: '#9C83D9',
  156. sort: 2,
  157. xRotate: 0,
  158. dataIndex: 'co2val',
  159. },
  160. {
  161. legend: '甲烷',
  162. seriesName: '(%)',
  163. ymax: 10,
  164. yname: '%',
  165. linetype: 'line',
  166. yaxispos: 'right',
  167. color: '#DA3914',
  168. sort: 2,
  169. xRotate: 0,
  170. dataIndex: 'gasval',
  171. },
  172. {
  173. legend: '氧气',
  174. seriesName: '(%)',
  175. ymax: 10,
  176. yname: '%',
  177. linetype: 'line',
  178. yaxispos: 'right',
  179. color: '#03C2EC',
  180. sort: 2,
  181. xRotate: 0,
  182. dataIndex: 'o2val',
  183. },
  184. {
  185. legend: '乙炔',
  186. seriesName: '(ppm)',
  187. ymax: 20,
  188. yname: 'ppm',
  189. linetype: 'line',
  190. yaxispos: 'left',
  191. color: '#00FFA8',
  192. sort: 1,
  193. xRotate: 0,
  194. dataIndex: 'chval',
  195. },
  196. {
  197. legend: '乙烯',
  198. seriesName: '(ppm)',
  199. ymax: 20,
  200. yname: 'ppm',
  201. linetype: 'line',
  202. yaxispos: 'left',
  203. color: '#AE19FF',
  204. sort: 1,
  205. xRotate: 0,
  206. dataIndex: 'ch2val',
  207. },
  208. ]
  209. const [register, { setModalProps, closeModal }] = useModalInner();
  210. function handleVisibleChange(visible) {
  211. if (visible) {
  212. loading.value = true;
  213. setModalProps({ loading: true, confirmLoading: true });
  214. setTimeout(() => {
  215. loading.value = false;
  216. setModalProps({ loading: false, confirmLoading: false });
  217. }, 1000);
  218. }
  219. }
  220. // 选择监测
  221. function selectDevice (id){
  222. loading.value = true;
  223. setModalProps({ loading: true, confirmLoading: true });
  224. setTimeout(() => {
  225. loading.value = false;
  226. activeDeviceID.value = id
  227. setModalProps({ loading: false, confirmLoading: false });
  228. }, 300);
  229. }
  230. function handleOk(e) {
  231. e.preventDefault()
  232. closeModal()
  233. }
  234. function handleCancel(e) {
  235. e.preventDefault()
  236. closeModal()
  237. }
  238. watch([() => props.dataSource, () => props.activeID], ([newDataSource, newActiveID], [oldDataSource, oldActiveID]) => {
  239. if(newActiveID != oldActiveID){
  240. activeDeviceID.value = newActiveID as string
  241. }
  242. deviceList.value = newDataSource?.filter((item:any, index) => {
  243. if((!activeDeviceID.value && index == 0) || item.deviceID === activeDeviceID.value){
  244. activeDeviceID.value = item.deviceID
  245. posMonitor.value = item.readData
  246. }
  247. item.readTime = item.readTime?.substring(11)
  248. return item
  249. })
  250. })
  251. return { register, model: modelRef, currentTime, handleVisibleChange, selectDevice, handleOk, handleCancel, deviceList, activeDeviceID, posMonitor, echatsOption, posList, chartsColumns };
  252. },
  253. });
  254. </script>
  255. <style lang="less" scoped>
  256. .fiber-modal{
  257. width: 100%;
  258. height: 650px;
  259. display: flex;
  260. flex-direction: row;
  261. justify-content: space-between;
  262. .modal-left{
  263. width: 200px;
  264. height: 100%;
  265. overflow-y: auto;
  266. background: #ffffff11;
  267. padding: 5px;
  268. border-radius: 5px;
  269. .active-device-title {
  270. color: aqua;
  271. }
  272. .link-item{
  273. position: relative;
  274. cursor: pointer;
  275. line-height: 30px;
  276. padding-left: 30px;
  277. span:hover{
  278. color: #89ffff;
  279. }
  280. &::after{
  281. content: '';
  282. position: absolute;
  283. display: block;
  284. width: 8px;
  285. height: 8px;
  286. top: 12px;
  287. left: 10px;
  288. transform: rotateZ(45deg) skew(10deg, 10deg);
  289. background: #45d3fd;
  290. }
  291. }
  292. }
  293. .modal-right{
  294. width: calc(100% - 220px);
  295. .base-title{
  296. line-height: 32px;
  297. position: relative;
  298. padding-left: 20px;
  299. &::after{
  300. content: '';
  301. position: absolute;
  302. display: block;
  303. width: 4px;
  304. height: 12px;
  305. top: 4px;
  306. left: 10px;
  307. background: #45d3fd;
  308. border-radius: 4px;
  309. }
  310. }
  311. .right-top{
  312. display: flex;
  313. flex-direction: row;
  314. justify-content: space-between;
  315. flex-wrap: wrap;
  316. margin-bottom: 10px;
  317. .top-item{
  318. width: 220px;
  319. height: 100px;
  320. display: flex;
  321. flex-direction: row;
  322. justify-content: center;
  323. border: 1px solid rgba(25,237,255,.4);
  324. box-shadow: inset 0 0 10px rgba(0,197,255,.6);
  325. background: rgba(0,0,0,.06666666666666667);
  326. padding-top: 20px;
  327. margin: 10px 0;
  328. .icon{
  329. margin-right: 10px;
  330. margin-top: 5px;
  331. color: #FDB146;
  332. }
  333. .item-container{
  334. width: 100px;
  335. display: flex;
  336. flex-direction: column;
  337. justify-content: center;
  338. div{
  339. text-align: center;
  340. }
  341. .title{
  342. font-size: 18px;
  343. }
  344. .value{
  345. text-shadow: 0 0 25px #00fbfe;
  346. background: linear-gradient( 0deg,#45d3fd, #45d3fd, #61ddb1,#61ddb1);
  347. font-style: normal;
  348. background-size: cover;
  349. font-family: electronicFont;
  350. font-size: 30px;
  351. -webkit-background-clip: text;
  352. background-clip: text;
  353. -webkit-text-fill-color: transparent;
  354. position: relative;
  355. top: -8px;
  356. span{
  357. font-family: Arial, Helvetica, sans-serif;
  358. font-size: 18px;
  359. color: aliceblue;
  360. }
  361. }
  362. }
  363. }
  364. .warning-box{
  365. padding-top: 0px;
  366. .icon{
  367. margin-top: 20px;
  368. :deep(.icon-style){
  369. width: auto;
  370. color: #FDB146;
  371. }
  372. }
  373. .warning-value{
  374. font-size: 18px;
  375. color: #61ddb1;
  376. }
  377. }
  378. }
  379. .right-center{
  380. margin-top: 20px;
  381. display: flex;
  382. flex-direction: row;
  383. justify-content: space-between;
  384. .table-box{
  385. position: relative;
  386. width: 500px;
  387. height: 250px;
  388. }
  389. .warning-box{
  390. width: calc(100% - 520px);
  391. .warning-container{
  392. width: 100%;
  393. height: convert;
  394. background: #009acd00;
  395. :deep(.dv-scroll-board){
  396. .row-item{
  397. height: 40px !important;
  398. line-height: 40px !important;
  399. }
  400. .header-item{
  401. border-top: 1px solid #91e9fe !important;
  402. border-bottom: 1px solid #91e9fe !important;
  403. }
  404. }
  405. }
  406. }
  407. }
  408. .right-bottom{
  409. margin-top: 20px;
  410. .echarts-box{
  411. width: 100%;
  412. height: 320px;
  413. position: relative;
  414. .echarts-line{
  415. width: calc(100% + 80px);
  416. position: absolute
  417. }
  418. }
  419. }
  420. }
  421. }
  422. :deep(.zxm-table-body){
  423. border: 1px solid rgba(57, 232, 255, 0.2) !important;
  424. .zxm-table-tbody > tr > td{
  425. border: none !important;
  426. }
  427. }
  428. :deep(.zxm-table-cell){
  429. border-right: none !important;
  430. }
  431. </style>