gasSupplyAir.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. <template>
  2. <a-modal
  3. v-model:visible="visible"
  4. width="1200px"
  5. height="500px"
  6. class="supplyAir-modal"
  7. title="风窗自主调控瓦斯监测"
  8. @ok="handleOk"
  9. @cancel="handleOk"
  10. >
  11. <div class="modal-box">
  12. <div class="left-box"> </div>
  13. <div class="right-box">
  14. <BarAndLine
  15. class="echarts-line"
  16. xAxisPropType="readTime"
  17. height="400px"
  18. :dataSource="echartsData"
  19. :chartsColumns="chartsColumnList"
  20. :option="echatsOption"
  21. />
  22. </div>
  23. </div>
  24. <div class="setting-box">
  25. <div class="right-inputs">
  26. <div class="vent-flex-row" v-if="!isMock">
  27. <template v-if="monitorData['nwindownum'] == 1">
  28. <div class="input-box"
  29. >风窗实时开度(°):<span>{{ monitorData['forntArea'] }}</span></div
  30. >
  31. </template>
  32. <template v-else>
  33. <div class="input-box"
  34. >前窗实时开度(°):<span>{{ monitorData['forntArea'] }}</span></div
  35. >
  36. <div class="input-box"
  37. >后窗实时开度(°):<span>{{ monitorData['rearArea'] }}</span></div
  38. >
  39. </template>
  40. <div class="input-box"
  41. >风窗实时瓦斯含量(%):<span>{{ monitorData['gas'] }}</span></div
  42. >
  43. </div>
  44. <div class="vent-flex-row" v-else>
  45. <template v-if="monitorData['nwindownum'] == 1">
  46. <div class="input-box"
  47. >风窗实时开度(°):<span>{{ frontWindowAngle }}</span></div
  48. >
  49. </template>
  50. <template v-else>
  51. <div class="input-box"
  52. >前窗实时开度(°):<span>{{ frontWindowAngle }}</span></div
  53. >
  54. <div class="input-box"
  55. >后窗实时开度(°):<span>{{ rearWindowAngle }}</span></div
  56. >
  57. </template>
  58. <div class="input-box"
  59. >风窗实时瓦斯含量(%):<span>{{ gasTemp ? gasTemp.toFixed(2) : gas?.toFixed(2) }}</span></div
  60. >
  61. <div class="input-box"
  62. >风窗实时风量(m³/min):<span>{{ fWindowM3Temp ? fWindowM3Temp.toFixed(2) : fWindowM3 ? fWindowM3.toFixed(2) : '-' }}</span></div
  63. >
  64. </div>
  65. </div>
  66. </div>
  67. </a-modal>
  68. </template>
  69. <script lang="ts" setup>
  70. import { ref, nextTick, onMounted, watch, computed, reactive } from 'vue';
  71. import BarAndLine from '/@/components/chart/BarAndLine.vue';
  72. import { useGlobSetting } from '/@/hooks/setting';
  73. const props = defineProps({
  74. modalIsShow: {
  75. type: Boolean,
  76. default: false,
  77. },
  78. modalType: {
  79. type: String,
  80. },
  81. data: {
  82. type: Object,
  83. default: () => {},
  84. },
  85. gasVal: {
  86. type: Number,
  87. },
  88. isMock: {
  89. type: Boolean,
  90. },
  91. });
  92. const emit = defineEmits(['handleOk', 'handleCancel']);
  93. const visible = computed(() => props.modalIsShow);
  94. const { sysOrgCode } = useGlobSetting();
  95. // const sysOrgCode = 'sdmtjtswmk';
  96. const echartsData = ref<
  97. {
  98. gasVal: string | number;
  99. gas: string | number;
  100. readTime: string;
  101. fWindowM3: string | number;
  102. forntArea: string | number;
  103. rearArea?: string | number;
  104. }[]
  105. >([]);
  106. const monitorData = ref({});
  107. const echatsOption = {
  108. legend: {
  109. top: 10,
  110. },
  111. grid: {
  112. top: '80',
  113. left: '30',
  114. right: '35',
  115. bottom: '10',
  116. containLabel: true,
  117. },
  118. toolbox: {
  119. feature: {
  120. saveAsImage: {
  121. show: false,
  122. },
  123. },
  124. },
  125. xAxis: {
  126. type: 'category',
  127. axisLabel: {
  128. margin: 10,
  129. color: '#f1f1f199',
  130. },
  131. name: '',
  132. },
  133. yAxis: {
  134. axisLabel: {
  135. color: '#0071A5',
  136. },
  137. },
  138. };
  139. const chartsColumnListTemp = [
  140. {
  141. legend: '瓦斯超限值',
  142. seriesName: '(%)',
  143. ymax: 1100,
  144. yname: '%',
  145. linetype: 'line',
  146. yaxispos: 'left',
  147. color: '#00FFA8',
  148. sort: 1,
  149. xRotate: 0,
  150. dataIndex: 'gasVal',
  151. },
  152. {
  153. legend: '瓦斯实时值',
  154. seriesName: '(%)',
  155. ymax: 1100,
  156. yname: '%',
  157. linetype: 'line',
  158. yaxispos: 'left',
  159. color: '#FDB146',
  160. sort: 1,
  161. xRotate: 0,
  162. dataIndex: 'gas',
  163. },
  164. {
  165. legend: sysOrgCode == 'sdmtjtswmk' ? '窗1开度' : '前窗开度',
  166. seriesName: '(°)',
  167. ymax: 1100,
  168. yname: '°',
  169. linetype: 'line',
  170. yaxispos: 'right',
  171. color: '#02FBA7',
  172. sort: 2,
  173. xRotate: 0,
  174. dataIndex: 'forntArea',
  175. },
  176. {
  177. legend: sysOrgCode == 'sdmtjtswmk' ? '窗2开度' : '后窗开度',
  178. seriesName: '(°)',
  179. ymax: 1100,
  180. yname: '°',
  181. linetype: 'line',
  182. yaxispos: 'right',
  183. color: '#AD19FE',
  184. sort: 2,
  185. xRotate: 0,
  186. dataIndex: 'rearArea',
  187. },
  188. ];
  189. const chartsColumnList = ref(chartsColumnListTemp);
  190. let frontWindowAngle = ref<undefined | number>(undefined);
  191. let rearWindowAngle = ref<undefined | number>(undefined);
  192. let fWindowM3 = ref<undefined | number>(undefined);
  193. let gas = ref<undefined | number>(undefined);
  194. let fWindowM3Temp = ref<undefined | number>(undefined);
  195. let gasTemp = ref<undefined | number>(undefined);
  196. let index = 1;
  197. watch(
  198. () => props.data,
  199. (newVal) => {
  200. if (!visible.value) return;
  201. if (newVal['nwindownum'] == 1) {
  202. // 单道风窗
  203. if (chartsColumnList.value.length != 3) chartsColumnList.value = [chartsColumnListTemp[0], chartsColumnListTemp[1], chartsColumnListTemp[2]];
  204. } else {
  205. // 多道风窗
  206. if (chartsColumnList.value.length != 4)
  207. chartsColumnList.value = [chartsColumnListTemp[0], chartsColumnListTemp[1], chartsColumnListTemp[3], chartsColumnListTemp[4]];
  208. }
  209. monitorData.value = newVal;
  210. if (echartsData.value.length > 20) {
  211. echartsData.value.shift();
  212. }
  213. if (props.isMock) {
  214. // 这里开启风窗开度模拟
  215. if (newVal['nwindownum'] == 1 && frontWindowAngle.value === undefined) {
  216. frontWindowAngle.value = newVal['forntArea'];
  217. } else if (newVal['nwindownum'] == 2) {
  218. if (frontWindowAngle.value === undefined) frontWindowAngle.value = (newVal['forntArea'] / newVal['maxarea']) * 90;
  219. if (rearWindowAngle.value === undefined) rearWindowAngle.value = (newVal['rearArea'] / newVal['maxarea']) * 90;
  220. }
  221. if (fWindowM3.value === undefined) fWindowM3.value = Number(newVal['fWindowM3']);
  222. // if (gas == undefined) gas = Number(newVal['gas']) > Number(props.gasVal) ? newVal['gas'] : props.gasVal + 0.2;
  223. if (gas.value == undefined) gas.value = props.gasVal + 0.2;
  224. // 开启模拟
  225. if (gas.value > props.gasVal - 0.3) {
  226. mock(newVal['maxarea']);
  227. echartsData.value = [
  228. ...echartsData.value,
  229. {
  230. gasVal: props.gasVal,
  231. gas: gas.value as number,
  232. readTime: newVal['readTime'].substring(11),
  233. forntArea: frontWindowAngle.value as number,
  234. rearArea: rearWindowAngle.value as number,
  235. fWindowM3: fWindowM3.value as number,
  236. },
  237. ];
  238. } else {
  239. const random = Math.random() - 0.5;
  240. fWindowM3Temp.value = fWindowM3.value + random * 50;
  241. gasTemp.value = gas.value + random * 0.01;
  242. echartsData.value = [
  243. ...echartsData.value,
  244. {
  245. gasVal: props.gasVal,
  246. gas: gasTemp.value,
  247. readTime: newVal['readTime'].substring(11),
  248. forntArea: frontWindowAngle.value as number,
  249. rearArea: rearWindowAngle.value as number,
  250. fWindowM3: fWindowM3Temp.value,
  251. },
  252. ];
  253. }
  254. } else {
  255. echartsData.value = [
  256. ...echartsData.value,
  257. {
  258. gasVal: props.gasVal,
  259. gas: newVal['gas'],
  260. readTime: newVal['readTime'].substring(11),
  261. forntArea: (newVal['forntArea'] / newVal['maxarea']) * 90,
  262. rearArea: (newVal['rearArea'] / newVal['maxarea']) * 90,
  263. fWindowM3: newVal['fWindowM3'],
  264. },
  265. ];
  266. }
  267. }
  268. );
  269. function mock(maxArea?: number) {
  270. debugger;
  271. if (maxArea) {
  272. // 每调用一次数据就增减一些
  273. // frontWindowAngle 增加一些
  274. if (frontWindowAngle.value !== undefined && frontWindowAngle.value <= 90) {
  275. frontWindowAngle.value = Number(Math.min(frontWindowAngle.value + 3, 90).toFixed(0));
  276. }
  277. if (rearWindowAngle.value !== undefined && rearWindowAngle.value <= 90) {
  278. rearWindowAngle.value = Number(Math.min(rearWindowAngle.value + 3, 90).toFixed(0));
  279. }
  280. if (fWindowM3.value !== undefined) {
  281. fWindowM3.value += 40 * index;
  282. }
  283. if (gas.value !== undefined) {
  284. gas.value -= Number((0.001 * index).toFixed(3));
  285. }
  286. ++index;
  287. }
  288. }
  289. function handleOk() {
  290. emit('handleCancel');
  291. echartsData.value = [];
  292. frontWindowAngle.value = undefined;
  293. rearWindowAngle.value = undefined;
  294. fWindowM3.value = undefined;
  295. gas.value = undefined;
  296. fWindowM3Temp.value = undefined;
  297. gasTemp.value = undefined;
  298. }
  299. onMounted(() => {});
  300. </script>
  301. <style scoped lang="less">
  302. .modal-box {
  303. display: flex;
  304. flex-direction: row;
  305. background-color: #ffffff05;
  306. padding: 10px 8px 0 8px;
  307. border: 1px solid #00d8ff22;
  308. position: relative;
  309. // min-height: 600px;
  310. .left-box {
  311. flex: 1; /* 占据 3/4 的空间 */
  312. background-image: url(../../../../../assets/images/window-gas.png);
  313. background-repeat: no-repeat;
  314. background-size: contain; /* 确保背景图片完整显示 */
  315. background-position: center; /* 确保背景图片居中 */
  316. }
  317. .right-box {
  318. flex: 1; /* 占据 3/4 的空间 */
  319. height: 400px;
  320. width: 100%;
  321. }
  322. }
  323. .setting-box {
  324. width: 1570px;
  325. height: 70px;
  326. margin: 10px 0;
  327. background-color: #ffffff05;
  328. border: 1px solid #00d8ff22;
  329. display: flex;
  330. align-items: center;
  331. justify-content: space-between;
  332. .right-inputs {
  333. width: 100%;
  334. display: flex;
  335. height: 40px;
  336. margin: 0 10px;
  337. justify-content: space-between;
  338. }
  339. .left-buttons {
  340. display: flex;
  341. height: 40px;
  342. .btn {
  343. margin: 0 10px;
  344. }
  345. }
  346. .border-clip {
  347. width: 1px;
  348. height: 25px;
  349. border-right: 1px solid #8b8b8b77;
  350. }
  351. .input-box {
  352. width: 300px;
  353. span {
  354. color: aqua;
  355. padding: 0 20px;
  356. }
  357. }
  358. }
  359. @keyframes open {
  360. 0% {
  361. height: 0px;
  362. }
  363. 100% {
  364. height: fit-content;
  365. }
  366. }
  367. @keyframes close {
  368. 0% {
  369. height: fit-content;
  370. }
  371. 100% {
  372. height: 0px;
  373. }
  374. }
  375. :deep(.zxm-divider-inner-text) {
  376. color: #cacaca88 !important;
  377. }
  378. :deep(.zxm-form-item) {
  379. margin-bottom: 10px;
  380. }
  381. </style>