main-monitor.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <div class="mainMonitor">
  3. <div class="title-top" @click="getDetail">主通风机监测与控制系统</div>
  4. <div class="toggle-search">
  5. <i class="icon-search">
  6. <SvgIcon class="icon" size="14" name="toggle" />
  7. </i>
  8. <a-select
  9. v-model:value="searchValue"
  10. style="width: 180px; margin-right: 10px"
  11. :options="mainTypeList"
  12. aria-placeholder="请选择"
  13. @change="changeSelect"
  14. />
  15. <div class="status-yx">
  16. <div class="now-name">
  17. <i style="margin: 0px 5px 0px 5px">
  18. <SvgIcon class="icon" size="14" name="yxfj" />
  19. </i>
  20. <span style="color: #fff">运行风机</span>
  21. </div>
  22. <div class="now-status">{{ runStatus }}</div>
  23. </div>
  24. </div>
  25. <div class="main-contents">
  26. <div class="point-des-box">
  27. <div>工况点</div>
  28. <div>负压(Pa): {{ selectDataObj.dataH }}</div>
  29. <div>风量(m³/min): {{ (selectDataObj.dataQ * 60).toFixed(2) }}</div>
  30. </div>
  31. <div class="main" ref="main"></div>
  32. </div>
  33. </div>
  34. </template>
  35. <script lang="ts" setup>
  36. import { ref, reactive, onMounted, nextTick, defineProps, watch } from 'vue';
  37. import { SvgIcon } from '/@/components/Icon';
  38. import * as echarts from 'echarts';
  39. import { useGlobSetting } from '/@/hooks/setting';
  40. const { sysOrgCode } = useGlobSetting();
  41. let props = defineProps({
  42. maindata: Array,
  43. });
  44. const emit = defineEmits(['goDetail']);
  45. let searchValue = ref('');
  46. let mainTypeList = reactive<any>([]); //下拉框
  47. let mainList = reactive<any[]>([]); //主风机列表
  48. let selectDataObj = ref({
  49. dataQ: 0,
  50. dataH: 0,
  51. });
  52. let maxM3 = ref(150); // 高家梁是150,其他400
  53. let maxMPa = ref(4000); //
  54. //风机启动状态
  55. let runStatus = ref('');
  56. //获取dom节点
  57. let main = ref<any>();
  58. //echart图表数据
  59. let echartData = reactive<any>({
  60. xdata: [],
  61. ydata: [],
  62. ydata1: [],
  63. });
  64. //跳转详情
  65. function getDetail() {
  66. emit('goDetail', 'fanMain');
  67. }
  68. //选项切换
  69. function changeSelect(val) {
  70. let objParam;
  71. let objParam1;
  72. searchValue.value = val;
  73. const selectData = mainList.find((item) => item['deviceID'] == val);
  74. if (selectData) {
  75. runStatus.value =
  76. selectData.readData.Fan1StartStatus && selectData.readData.Fan1StartStatus == '1'
  77. ? '1#风机'
  78. : selectData.readData.Fan2StartStatus && selectData.readData.Fan2StartStatus == '1'
  79. ? '2#风机'
  80. : '--';
  81. if (runStatus.value == '1#风机') {
  82. objParam = {
  83. dataQ: selectData.readData.Fan1m3 || 0,
  84. dataH: Math.abs(Number(selectData.readData.Fan1FanPre || 0)),
  85. };
  86. } else if (runStatus.value == '2#风机') {
  87. objParam = {
  88. dataQ: selectData.readData.Fan2m3 || 0,
  89. dataH: Math.abs(Number(selectData.readData.Fan2FanPre || 0)),
  90. };
  91. } else {
  92. objParam = {
  93. dataQ: 0,
  94. dataH: 0,
  95. };
  96. }
  97. // objParam = {
  98. // dataQ: selectData.readData.Fan1m3 || selectData.readData.Fan2m3 || selectData.readData.m3 || selectData.readData.Fanm3,
  99. // dataH: Math.abs(Number(selectData.readData.Fan1FanPre || selectData.readData.Fan2FanPre || selectData.readData.DataPa || selectData.readData.FanNegative || 0)),
  100. // }
  101. objParam1 = {
  102. dataha0: -0.056,
  103. dataha1: 3.6491,
  104. dataha2: 434.4,
  105. dataha3: 100,
  106. dataha4: -1000,
  107. };
  108. setChart(objParam, objParam1);
  109. getOption();
  110. }
  111. }
  112. function getOption() {
  113. nextTick(() => {
  114. const myChart = echarts.init(main.value);
  115. let option = {
  116. title: {
  117. textStyle: {
  118. color: '#3df6ff',
  119. fontSize: 14, // 字体颜色
  120. },
  121. text: '',
  122. },
  123. grid: {
  124. top: '25%',
  125. left: '5%',
  126. right: '19%',
  127. bottom: '8%',
  128. containLabel: true,
  129. },
  130. legend: {
  131. // x:'right',
  132. top: '5%',
  133. textStyle: {
  134. color: '#ffffff',
  135. fontSize: 14, // 字体颜色
  136. },
  137. data: ['风量', '负压'],
  138. },
  139. tooltip: {
  140. backgroundColor: 'rgba(0,0,0,0.8)',
  141. textStyle: {
  142. color: '#3df6ff',
  143. fontSize: 14, // 字体颜色
  144. },
  145. formatter: function (params, ticket, callback) {
  146. // var res = '风量' + ' : ' + Math.round(params.data[0] * 60 * 10) / 10 + '(m³/min)<br/>'
  147. // res = res + '&emsp;&emsp;&emsp;' + params.data[0] + '(m³/s)<br/>'
  148. var res = '风量' + ' : ' + params.data[0] * 60 + '(m³/min)<br/>';
  149. res = res + '&emsp;&emsp;&emsp;' + params.data[0].toFixed(2) + '(m³/s)<br/>';
  150. res = res + '负压' + ' : ' + params.data[1] + '(Pa)<br/>';
  151. return res;
  152. },
  153. trigger: 'item',
  154. },
  155. color: ['#00bb00', '#ffbb00', '#ff0000', '#0000ff'],
  156. xAxis: [
  157. {
  158. name: '风量\r\n(m³/min)\r\n',
  159. nameTextStyle: {
  160. color: '#3df6ff',
  161. fontSize: 12,
  162. },
  163. axisLine: {
  164. lineStyle: {
  165. color: '#0092d5',
  166. width: 1, // 这里是为了突出显示加上的
  167. },
  168. },
  169. splitLine: {
  170. show: false, // 网格线
  171. lineStyle: {
  172. color: '#006c9d',
  173. type: 'dashed', // 设置网格线类型 dotted:虚线 solid:实线
  174. },
  175. },
  176. axisLabel: {
  177. show: true,
  178. position: 'bottom',
  179. textStyle: {
  180. color: '#b3b8cc',
  181. fontSize: 14,
  182. },
  183. formatter: function (value) {
  184. return value * 60 + '';
  185. },
  186. },
  187. type: 'value',
  188. min: 0,
  189. max: maxM3.value, // 高家梁最大9000,
  190. },
  191. {
  192. name: '',
  193. nameTextStyle: {
  194. color: '#3df6ff',
  195. fontSize: 12,
  196. },
  197. axisTick: {
  198. show: false,
  199. },
  200. axisLine: {
  201. show: false,
  202. lineStyle: {
  203. color: '#0092d5',
  204. width: 1, // 这里是为了突出显示加上的
  205. },
  206. },
  207. splitLine: {
  208. show: false, // 网格线
  209. lineStyle: {
  210. color: '#006c9d',
  211. type: 'dashed', // 设置网格线类型 dotted:虚线 solid:实线
  212. },
  213. },
  214. axisLabel: {
  215. show: false,
  216. textStyle: {
  217. color: '#b3b8cc',
  218. fontSize: 14,
  219. },
  220. },
  221. type: 'value',
  222. min: 0,
  223. // max: 400,
  224. data: echartData.xdata,
  225. },
  226. ],
  227. yAxis: [
  228. {
  229. name: '负压(Pa)',
  230. splitNumber: 5,
  231. nameTextStyle: {
  232. color: '#3df6ff',
  233. fontSize: 12,
  234. },
  235. axisLine: {
  236. show: true,
  237. lineStyle: {
  238. color: '#0092d5',
  239. width: 1, // 这里是为了突出显示加上的
  240. },
  241. },
  242. splitLine: {
  243. show: true, // 网格线
  244. lineStyle: {
  245. color: '#006c9d',
  246. type: 'dashed', // 设置网格线类型 dotted:虚线 solid:实线
  247. },
  248. },
  249. axisLabel: {
  250. show: true,
  251. textStyle: {
  252. color: '#b3b8cc',
  253. fontSize: 14,
  254. },
  255. },
  256. type: 'value',
  257. min: 0,
  258. max: maxMPa.value,
  259. },
  260. ],
  261. series: [
  262. {
  263. type: 'effectScatter',
  264. symbolSize: 5,
  265. // symbolOffset:[1, 1],
  266. showEffectOn: 'render',
  267. // 涟漪特效相关配置。
  268. rippleEffect: {
  269. // 波纹的绘制方式,可选 'stroke' 和 'fill'。
  270. brushType: 'stroke',
  271. },
  272. zlevel: 1,
  273. z: 999,
  274. itemStyle: {
  275. color: '#ff0000',
  276. },
  277. data: echartData.ydata2,
  278. },
  279. {
  280. name: '风量',
  281. yAxisIndex: 0,
  282. xAxisIndex: 1,
  283. type: 'line',
  284. smooth: true,
  285. animationDuration: 1000,
  286. showSymbol: false,
  287. data: echartData.ydata,
  288. },
  289. {
  290. name: '负压',
  291. yAxisIndex: 0,
  292. xAxisIndex: 1,
  293. type: 'line',
  294. smooth: true,
  295. animationDuration: 1000,
  296. showSymbol: false,
  297. data: echartData.ydata1,
  298. },
  299. ],
  300. };
  301. myChart.setOption(option);
  302. window.onresize = function () {
  303. myChart.resize();
  304. };
  305. });
  306. }
  307. // 设置曲线数据
  308. function setChart(param, character) {
  309. var dataQ = 300;
  310. var dataH = character.dataha0 * dataQ * dataQ + character.dataha1 * dataQ + character.dataha2;
  311. let Q1 = Math.round((parseFloat(param.dataQ) / 60) * 100) / 100;
  312. let H1 = parseFloat(param.dataH);
  313. selectDataObj.value.dataH = H1;
  314. selectDataObj.value.dataQ = Q1;
  315. let q = Q1 - dataQ;
  316. let h = H1 - dataH;
  317. // 风压特性曲线1
  318. let data = [];
  319. // 风压特性曲线2
  320. let data2 = [];
  321. let datax = [];
  322. maxM3.value = Q1 < 100 ? 150 : Q1 < 200 ? 250 : Q1 < 300 ? 400 : Q1 < 400 ? 500 : Q1 < 600 ? 800 : 1000;
  323. maxMPa.value = H1 < 2000 ? 4000 : H1 < 2500 ? 5000 : 6000;
  324. for (let i = 30; i <= maxM3.value; i++) {
  325. let x = i;
  326. let y4 = character.dataha0 * (x - q) * (x - q) + character.dataha1 * (x - q) + character.dataha2 + h;
  327. data2.push([x, y4]);
  328. }
  329. for (let i = 0; i <= maxM3.value; i++) {
  330. let x = i;
  331. let y = (H1 / Q1 / Q1) * x * x;
  332. data.push([x, y]);
  333. datax.push(x * 60);
  334. }
  335. echartData.xdata = datax;
  336. echartData.ydata = data;
  337. echartData.ydata1 = data2;
  338. echartData.ydata2 = [[Q1, H1]];
  339. }
  340. watch(
  341. () => props.maindata,
  342. (val) => {
  343. mainList = val;
  344. mainTypeList.length = 0;
  345. mainList.forEach((el) => {
  346. mainTypeList.push({
  347. label: el.strinstallpos,
  348. value: el.deviceID,
  349. });
  350. });
  351. if (searchValue.value) {
  352. changeSelect(searchValue.value);
  353. } else {
  354. searchValue.value = mainTypeList[0].value;
  355. changeSelect(searchValue.value);
  356. }
  357. },
  358. {
  359. deep: true,
  360. }
  361. );
  362. onMounted(() => {});
  363. </script>
  364. <style lang="less" scoped>
  365. @font-face {
  366. font-family: 'douyuFont';
  367. src: url('../../../../../assets/font/douyuFont.otf');
  368. }
  369. .mainMonitor {
  370. width: 100%;
  371. height: 100%;
  372. position: relative;
  373. .title-top {
  374. position: absolute;
  375. top: 9px;
  376. left: 46px;
  377. color: #fff;
  378. font-size: 16px;
  379. font-family: 'douyuFont';
  380. cursor: pointer;
  381. &:hover {
  382. color: #66ffff;
  383. }
  384. }
  385. .toggle-search {
  386. position: absolute;
  387. left: 9px;
  388. top: 37px;
  389. display: flex;
  390. .icon-search {
  391. position: absolute;
  392. top: 50%;
  393. left: 5px;
  394. transform: translate(0%, -50%);
  395. }
  396. .status-yx {
  397. height: 30px;
  398. width: 180px;
  399. background-color: rgba(8, 148, 255, 0.3);
  400. border: 1px solid #1d80da;
  401. display: flex;
  402. justify-content: space-between;
  403. align-items: center;
  404. .now-status {
  405. margin-right: 5px;
  406. padding-top: 3px;
  407. font-family: 'douyuFont';
  408. color: #3df6ff;
  409. }
  410. }
  411. }
  412. .main-contents {
  413. position: relative;
  414. top: 66px;
  415. left: 0;
  416. height: calc(100% - 66px);
  417. width: 100%;
  418. .point-des-box {
  419. position: absolute;
  420. background: #0d0d0dbd;
  421. padding: 5px 8px;
  422. border-radius: 10px;
  423. border: 1px solid #ffffff;
  424. z-index: 999;
  425. color: #fff;
  426. right: 20px;
  427. top: 10px;
  428. }
  429. .main {
  430. width: 100%;
  431. height: 100%;
  432. overflow-x: hidden;
  433. }
  434. }
  435. }
  436. :deep .zxm-select-selector {
  437. width: 100%;
  438. height: 30px !important;
  439. padding: 0 11px 0px 25px !important;
  440. background-color: rgba(8, 148, 255, 0.3) !important;
  441. border: 1px solid #1d80da !important;
  442. }
  443. :deep .zxm-select-selection-item {
  444. color: #fff !important;
  445. line-height: 28px !important;
  446. }
  447. :deep .zxm-select-arrow {
  448. color: #fff !important;
  449. }
  450. </style>