supplyAir.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <BasicModal
  3. @register="register"
  4. title="按需供风联动"
  5. :maskStyle="{ backgroundColor: '#000000aa', backdropFilter: 'blur(3px)' }"
  6. width="1200px"
  7. v-bind="$attrs"
  8. @ok="onSubmit"
  9. @cancel="onCancel"
  10. :canFullscreen="false"
  11. :destroyOnClose="true"
  12. :footer="null"
  13. :maskClosable="false"
  14. >
  15. <div class="modal-box">
  16. <div class="left-box" style="width: 550px; height: 400px"> </div>
  17. <div class="right-box">
  18. <BarAndLine
  19. class="echarts-line"
  20. xAxisPropType="readTime"
  21. height="400px"
  22. :dataSource="echartsData"
  23. :chartsColumns="chartsColumnList1"
  24. :option="echatsOption1"
  25. />
  26. </div>
  27. </div>
  28. <div class="setting-box">
  29. <div class="right-inputs">
  30. <div class="vent-flex-row">
  31. <div class="input-title">出风口风量(m³/min):</div>
  32. <span class="input-box" size="normal">{{ data.ductOutletAirVolume_merge }}</span>
  33. <div class="input-title">局扇供风量(m³/min):</div>
  34. <span class="input-box" size="normal">{{ data.inletAirVolume_merge }}</span>
  35. <div class="input-title">目标风量(m³/min):</div>
  36. <span class="input-box" size="normal">{{ props.targetVolume }}</span>
  37. <div class="btn btn1" @click="onHide">隐藏</div>
  38. <div class="btn btn1" @click="stop">紧急停止</div>
  39. </div>
  40. </div>
  41. </div>
  42. </BasicModal>
  43. </template>
  44. <script lang="ts" setup>
  45. import { BasicModal, useModalInner } from '/@/components/Modal';
  46. import { ref, onMounted, nextTick, watch } from 'vue';
  47. import echarts from '/@/utils/lib/echarts';
  48. import BarAndLine from '/@/components/chart/BarAndLine.vue';
  49. import { option, chartsColumnList1, echatsOption1 } from '../fanLocal.data';
  50. import { autoAdjust } from '../fanLocal.api';
  51. import { message } from 'ant-design-vue';
  52. const emit = defineEmits(['close', 'register', 'openModal']);
  53. const props = defineProps({
  54. data: {
  55. type: Object,
  56. default: () => {},
  57. },
  58. targetVolume: {
  59. type: Number,
  60. },
  61. fanlocalId: {
  62. type: String,
  63. },
  64. });
  65. // 注册 modal
  66. const [register, { closeModal }] = useModalInner((data) => {
  67. nextTick(() => {
  68. if (option['xAxis']) option['xAxis']['data'] = xData;
  69. option['series'] = yDataList;
  70. initEcharts();
  71. });
  72. });
  73. const ChartRef = ref();
  74. const myChart = ref();
  75. const refresh = ref(true);
  76. const xData: any[] = [];
  77. const yDataList: [] = [];
  78. // const echartsData = ref([]);
  79. // const monitorData = ref({});
  80. const echartsData = ref<Record<string, any>[]>([]);
  81. const monitorData = ref<Record<string, any>>({});
  82. watch(
  83. () => props.data,
  84. (newVal) => {
  85. // 创建新对象,合并 newVal 和 targetVolume
  86. const combinedData = {
  87. inletAirVolume_merge: newVal.inletAirVolume_merge,
  88. targetVolume: props.targetVolume, // 添加目标风量
  89. readTime: newVal.readTime || new Date().toISOString(), // 确保有时间字段
  90. };
  91. monitorData.value = combinedData;
  92. if (echartsData.value.length > 20) {
  93. echartsData.value.shift();
  94. }
  95. echartsData.value = [...echartsData.value, combinedData];
  96. }
  97. );
  98. function onSubmit() {
  99. emit('close');
  100. closeModal();
  101. }
  102. function onCancel() {
  103. //
  104. }
  105. function initEcharts() {
  106. if (ChartRef.value) {
  107. myChart.value = echarts.init(ChartRef.value);
  108. option && myChart.value.setOption(option);
  109. refresh.value = false;
  110. nextTick(() => {
  111. setTimeout(() => {
  112. refresh.value = true;
  113. }, 0);
  114. });
  115. }
  116. }
  117. function onHide() {
  118. closeModal();
  119. }
  120. function stop() {
  121. const params = { auto: 0, fanlocalId: props.fanlocalId };
  122. autoAdjust(params)
  123. .then(() => {
  124. message.success('指令已下发成功!');
  125. })
  126. .catch(() => {
  127. message.error('指令下发失败');
  128. });
  129. }
  130. onMounted(() => {
  131. // initEcharts();
  132. });
  133. </script>
  134. <style scoped lang="less">
  135. .modal-box {
  136. display: flex;
  137. flex-direction: row;
  138. background-color: #ffffff05;
  139. padding: 10px 8px 0 8px;
  140. border: 1px solid #00d8ff22;
  141. position: relative;
  142. // min-height: 600px;
  143. .left-box {
  144. flex: 1; /* 占据 3/4 的空间 */
  145. background-image: url(../../../../../assets/images/supplyAir.svg);
  146. background-repeat: no-repeat;
  147. background-size: contain; /* 确保背景图片完整显示 */
  148. background-position: center; /* 确保背景图片居中 */
  149. }
  150. .right-box {
  151. flex: 1; /* 占据 3/4 的空间 */
  152. height: 400px;
  153. width: 100%;
  154. }
  155. }
  156. .setting-box {
  157. width: 100%;
  158. height: 70px;
  159. margin: 10px 0;
  160. background-color: #ffffff05;
  161. border: 1px solid #00d8ff22;
  162. display: flex;
  163. align-items: center;
  164. justify-content: space-between;
  165. .right-inputs {
  166. width: 100%;
  167. display: flex;
  168. height: 40px;
  169. margin: 0 10px;
  170. justify-content: space-between;
  171. }
  172. .left-buttons {
  173. display: flex;
  174. height: 40px;
  175. .btn {
  176. margin: 0 10px;
  177. }
  178. }
  179. .border-clip {
  180. width: 1px;
  181. height: 25px;
  182. border-right: 1px solid #8b8b8b77;
  183. }
  184. .input-title {
  185. max-width: 150px;
  186. }
  187. .input-box {
  188. width: 120px !important;
  189. background: transparent !important;
  190. border-color: #00d8ff44 !important;
  191. margin-right: 20px;
  192. color: #fff !important;
  193. }
  194. .btn {
  195. padding: 8px 20px;
  196. margin: 10px;
  197. position: relative;
  198. border-radius: 2px;
  199. color: #fff;
  200. width: fit-content;
  201. cursor: pointer;
  202. &::before {
  203. position: absolute;
  204. display: block;
  205. content: '';
  206. width: calc(100% - 4px);
  207. height: calc(100% - 4px);
  208. top: 2px;
  209. left: 2px;
  210. border-radius: 2px;
  211. z-index: -1;
  212. }
  213. }
  214. .btn1 {
  215. border: 1px solid #5cfaff;
  216. &::before {
  217. background-image: linear-gradient(#2effee92, #0cb1d592);
  218. }
  219. &:hover {
  220. border: 1px solid #5cfaffaa;
  221. &::before {
  222. background-image: linear-gradient(#2effee72, #0cb1d572);
  223. }
  224. }
  225. }
  226. }
  227. @keyframes open {
  228. 0% {
  229. height: 0px;
  230. }
  231. 100% {
  232. height: fit-content;
  233. }
  234. }
  235. @keyframes close {
  236. 0% {
  237. height: fit-content;
  238. }
  239. 100% {
  240. height: 0px;
  241. }
  242. }
  243. :deep(.zxm-divider-inner-text) {
  244. color: #cacaca88 !important;
  245. }
  246. :deep(.zxm-form-item) {
  247. margin-bottom: 10px;
  248. }
  249. </style>