balancePressHomeBD.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <template>
  2. <a-spin tip="Loading..." :spinning="loading">
  3. <div class="monitor-container">
  4. <div class="lr left-box">
  5. <Transition enter-active-class="animate__animated animate__fadeInLeft" leave-active-class="animate__animated animate__fadeOutLeft">
  6. <ventBox1 v-if="showModules">
  7. <template #title>
  8. <div>均压与低氧参数监测与设置</div>
  9. </template>
  10. <template #container>
  11. <div class="vent-flex-row-between auto-control mt-10px mb-10px">
  12. <div class="title">自动调节:</div>
  13. <a-radio-group :value="avePressSetting.isAuto" name="radioGroup" @change="changeAvePressState($event, 'isAuto')">
  14. <a-radio :value="false">关闭</a-radio>
  15. <a-radio :value="true">开启</a-radio>
  16. </a-radio-group>
  17. </div>
  18. <div class="vent-flex-row-between auto-control mt-10px mb-10px">
  19. <div class="title">调节类型:</div>
  20. <a-radio-group :value="avePressSetting.controlType" name="radioGroup" @change="changeAvePressState($event, 'controlType')">
  21. <a-radio value="o2">氧气</a-radio>
  22. <a-radio value="pressure">压差</a-radio>
  23. </a-radio-group>
  24. </div>
  25. <div>
  26. <!-- <div class="divider-line">开始条件</div>
  27. <div v-for="(item, index) in settingParam1" class="input-item" :key="index">
  28. <div class="title">{{ item.title }}:</div>
  29. <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
  30. <div class="unit">{{ item.unit }}</div>
  31. </div> -->
  32. <div class="divider-line"></div>
  33. <div v-for="(item, index) in settingParam4" class="input-item" :key="index">
  34. <div class="title">{{ item.title }}:</div>
  35. <a-input-number class="input-value" v-model:value="avePressSetting[item.code]" placeholder="" :disabled="settingFormDisabled" />
  36. <div class="unit">&nbsp;{{ item.unit }}</div>
  37. </div>
  38. <!-- <div class="divider-line">结束时间</div>
  39. <div v-for="(item, index) in settingParam3" class="input-item" :key="index">
  40. <div class="title">{{ item.title }}:</div>
  41. <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
  42. <div class="unit">{{ item.unit }}</div>
  43. </div> -->
  44. </div>
  45. <div class="btn-box flex" style="text-align: center">
  46. <div class="btn btn1 flex-1" @click="editSettingForm">{{ settingFormDisabled ? '编辑' : '取消' }}</div>
  47. <div class="btn btn1 flex-1" @click="submitSettingForm">提交</div>
  48. </div>
  49. </template>
  50. </ventBox1>
  51. </Transition>
  52. <Transition enter-active-class="animate__animated animate__fadeInLeft" leave-active-class="animate__animated animate__fadeOutLeft">
  53. <ventBox1 v-if="showModules" class="mt-10px">
  54. <template #title>
  55. <div>均压工作面联动控制</div>
  56. </template>
  57. <template #container>
  58. <div class="vent-flex-row-between auto-control mt-10px mb-10px">
  59. <div class="title">风门与风门自动调节:</div>
  60. <a-radio-group :value="gateLinkage.isAuto" name="radioGroup" @change="changeIsAuto($event, gateLinkage.id)">
  61. <a-radio :value="false">关闭</a-radio>
  62. <a-radio :value="true">开启</a-radio>
  63. </a-radio-group>
  64. <div class="btn btn1" @click="() => openModal(false, { id: gateLinkage.id })">密码修改</div>
  65. </div>
  66. <div class="vent-flex-row-between auto-control mt-10px mb-10px">
  67. <div class="title">风机与风门自动调节:</div>
  68. <a-radio-group :value="avePressLinkage.isAuto" name="radioGroup" @change="changeIsAuto($event, avePressLinkage.id)">
  69. <a-radio :value="false">关闭</a-radio>
  70. <a-radio :value="true">开启</a-radio>
  71. </a-radio-group>
  72. <div class="btn btn1" @click="() => openModal(false, { id: avePressLinkage.id })">密码修改</div>
  73. </div>
  74. <!-- <div class="btn-box" style="text-align: center">
  75. </div> -->
  76. </template>
  77. </ventBox1>
  78. </Transition>
  79. </div>
  80. <ModuleCommon
  81. v-for="(cfg, index) in configs"
  82. :key="`svvmbcb${index}`"
  83. :show-style="cfg.showStyle"
  84. :module-data="cfg.moduleData"
  85. :module-name="cfg.moduleName"
  86. :device-type="cfg.deviceType"
  87. :data="selectData"
  88. :visible="showModules"
  89. />
  90. </div>
  91. <PasswordModal :modal-is-show="modalVisible" modal-title="提交" @handle-ok="handleResolve" @handle-cancel="handleReject" />
  92. <UpdatePassword @register="updatePwdRegister" @submit="handleChangePassword" />
  93. <!-- <BasicModal title="风门状态监测" :mask="false" :bodyStyle="{ height: '50px' }" style="top: 20px" :show-ok-btn="false" @register="warnRegister2">
  94. {{ warnModalText2 }}
  95. </BasicModal>
  96. <BasicModal
  97. title="压差状态监测"
  98. :mask="false"
  99. :bodyStyle="{ height: '50px' }"
  100. centered
  101. ok-text="下发联动控制指令"
  102. @ok="autoControl"
  103. @register="warnRegister1"
  104. >
  105. {{ warnModalText1 }}
  106. </BasicModal>
  107. <BasicModal title="局扇状态监测" :mask="false" :bodyStyle="{ height: '50px' }" style="top: 420px" :show-ok-btn="false" @register="warnRegister3">
  108. {{ warnModalText3 }}
  109. </BasicModal> -->
  110. <div class="switch-button icon-goto right-10px top-70px" :class="{ 'right-390px': showModules }" @click="showModules = !showModules"></div>
  111. <!-- <div v-else class="switch-button icon-goto right-10px top-70px" @click="showModules = true"></div> -->
  112. </a-spin>
  113. </template>
  114. <script setup lang="ts">
  115. import { ref, onMounted, onUnmounted, defineProps } from 'vue';
  116. import { mountedThree, destroy, setModelType, updateText, play } from '../balancePress.threejs';
  117. import { list } from '../balancePress.api';
  118. import ModuleCommon from '../../../home/configurable/components/ModuleCommon.vue';
  119. import { useInitConfigs } from '../../../home/configurable/hooks/useInit';
  120. import { useGlobSetting } from '/@/hooks/setting';
  121. import { settingParam4 } from '../balancePress.data';
  122. import { Modal } from 'ant-design-vue';
  123. import ventBox1 from '/@/components/vent/ventBox1.vue';
  124. import PasswordModal from '../../comment/components/PasswordModal.vue';
  125. import UpdatePassword from '../../comment/components/UpdatePassword.vue';
  126. import { useModal } from '/@/components/Modal';
  127. import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
  128. import { getToken } from '/@/utils/auth';
  129. import { useUserStore } from '/@/store/modules/user';
  130. import { usePressControl } from '../hooks/useControl';
  131. // import { Config } from '../../../deviceManager/configurationTable/types';
  132. const props = defineProps({
  133. deviceId: {
  134. type: String,
  135. require: true,
  136. },
  137. });
  138. const { sysOrgCode } = useGlobSetting();
  139. const loading = ref(false);
  140. const showModules = ref(true);
  141. // 监测数据
  142. const selectData = ref();
  143. // https获取监测数据
  144. let timer: any = null;
  145. function getMonitor(flag?) {
  146. if (Object.prototype.toString.call(timer) === '[object Null]') {
  147. timer = setTimeout(
  148. async () => {
  149. if (props.deviceId) {
  150. const data = await getDataSource(props.deviceId);
  151. // Object.assign(selectData, data);
  152. updateText(selectData);
  153. selectData.value = data;
  154. }
  155. if (timer) {
  156. timer = null;
  157. }
  158. await getMonitor();
  159. },
  160. flag ? 0 : 1000
  161. );
  162. }
  163. }
  164. async function getDataSource(systemID) {
  165. const res = await list({ devicetype: 'sys', systemID });
  166. const result = Array.from(res.msgTxt).reduce(
  167. (obj: any, e: any) => {
  168. obj[e.type] = e;
  169. // if (true) {
  170. if (sysOrgCode === 'sdmtjtswmk') {
  171. if (e.type.startsWith('fanlocal')) {
  172. obj.fanlocal.datalist.push(...e.datalist);
  173. }
  174. if (e.type.startsWith('safetymonitor')) {
  175. e.datalist.forEach((ele) => {
  176. if (ele.strinstallpos.includes('风门')) {
  177. obj.gate.datalist.push(ele);
  178. } else if (ele.strinstallpos.includes('风窗')) {
  179. obj.window.datalist.push(ele);
  180. } else if (ele.strinstallpos.includes('工作面')) {
  181. obj.work_surface.datalist.push(ele);
  182. } else {
  183. obj.others.datalist.push(ele);
  184. }
  185. });
  186. }
  187. }
  188. return obj;
  189. },
  190. {
  191. /** 用于归类fanlocal */
  192. fanlocal: { datalist: [] },
  193. /** 用于归类gate */
  194. gate: { datalist: [] },
  195. /** 用于归类window */
  196. window: { datalist: [] },
  197. /** 用于归类work_surface */
  198. work_surface: { datalist: [] },
  199. others: { datalist: [] },
  200. }
  201. );
  202. return result;
  203. }
  204. const { avePressSetting, avePressLinkage, gateLinkage, formData, getAvePress, changePassword, linkageControl, settingControl, autoControl } =
  205. usePressControl();
  206. const modalVisible = ref(false);
  207. const { configs, fetchConfigs } = useInitConfigs();
  208. const [updatePwdRegister, { openModal, closeModal, setModalProps }] = useModal();
  209. function handleChangePassword(values) {
  210. setModalProps({ confirmLoading: true });
  211. changePassword(values).finally(() => {
  212. setModalProps({ confirmLoading: false });
  213. closeModal();
  214. });
  215. }
  216. function changeIsAuto({ target }, id) {
  217. formData.value.isAuto = target.value;
  218. modalVisible.value = true;
  219. resolver = (password) => {
  220. linkageControl(
  221. { password, id },
  222. {
  223. isAuto: formData.value.isAuto,
  224. }
  225. ).finally(() => {
  226. modalVisible.value = false;
  227. });
  228. };
  229. }
  230. function changeAvePressState({ target }, key) {
  231. formData.value.temp = target.value;
  232. modalVisible.value = true;
  233. resolver = (password) => {
  234. settingControl(
  235. { password, id: avePressSetting.value.id },
  236. {
  237. [key]: formData.value.temp,
  238. }
  239. ).finally(() => {
  240. modalVisible.value = false;
  241. });
  242. };
  243. }
  244. // function submitLinkageForm(password) {}
  245. function submitSettingForm() {
  246. modalVisible.value = true;
  247. resolver = (password) => {
  248. settingControl({ password, id: avePressSetting.value.id }, avePressSetting.value).finally(() => {
  249. modalVisible.value = false;
  250. settingFormDisabled.value = true;
  251. });
  252. };
  253. }
  254. let resolver: any = null;
  255. function handleResolve(password) {
  256. if (resolver) resolver(password);
  257. resolver = null;
  258. }
  259. function handleReject() {
  260. modalVisible.value = false;
  261. resolver = null;
  262. }
  263. // const [warnRegister1, warnModal1] = useModal();
  264. // const [warnRegister2, warnModal2] = useModal();
  265. // const [warnRegister3, warnModal3] = useModal();
  266. const warnModal1 = ref();
  267. const warnModal2 = ref();
  268. const warnModal3 = ref();
  269. // const warnModalText1 = ref('');
  270. // const warnModalText2 = ref('');
  271. // const warnModalText3 = ref('');
  272. // 初始化 WebSocket
  273. function initWebSocket() {
  274. const token = getToken();
  275. const userStore = useUserStore();
  276. const glob = useGlobSetting();
  277. // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
  278. const url = `${glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://')}/websocket/${userStore.getUserInfo.id}?token=${token}`;
  279. connectWebSocket(url);
  280. onWebSocket((data: any) => {
  281. if (data.cmd !== 'topic' || data.topic !== 'warn') return;
  282. if (!data.msgTxt) return;
  283. const { info = '', type = '' } = JSON.parse(data.msgTxt);
  284. switch (type) {
  285. case 'o2':
  286. if (warnModal1.value) break;
  287. warnModal1.value = Modal.confirm({
  288. title: data.msgTitle,
  289. content: info,
  290. centered: true,
  291. okText: '下发调节指令',
  292. mask: true,
  293. class: 'balancePress',
  294. async onOk() {
  295. await autoControl();
  296. warnModal1.value = null;
  297. },
  298. onCancel: () => {
  299. warnModal1.value = null;
  300. },
  301. });
  302. // warnModalText1.value = info;
  303. // warnModal1.openModal();
  304. break;
  305. case 'pressure':
  306. // warnModalText1.value = info;
  307. // warnModal1.openModal();
  308. if (warnModal1.value) break;
  309. warnModal1.value = Modal.confirm({
  310. title: data.msgTitle,
  311. content: info,
  312. centered: true,
  313. okText: '下发调节指令',
  314. mask: true,
  315. class: 'balancePress',
  316. async onOk() {
  317. await autoControl();
  318. warnModal1.value = null;
  319. },
  320. onCancel: () => {
  321. warnModal1.value = null;
  322. },
  323. });
  324. break;
  325. case 'gate':
  326. if (warnModal2.value) break;
  327. warnModal2.value = Modal.warn({
  328. title: data.msgTitle,
  329. content: info,
  330. showOkBtn: false,
  331. mask: true,
  332. class: 'balancePress',
  333. onOk: () => {
  334. warnModal2.value = null;
  335. },
  336. });
  337. break;
  338. case 'fansys':
  339. if (warnModal3.value) break;
  340. warnModal3.value = Modal.warn({
  341. title: data.msgTitle,
  342. content: info,
  343. showOkBtn: false,
  344. mask: true,
  345. class: 'balancePress',
  346. style: 'top: 700px',
  347. onOk: () => {
  348. warnModal3.value = null;
  349. },
  350. });
  351. break;
  352. default:
  353. break;
  354. }
  355. });
  356. }
  357. const settingFormDisabled = ref(true);
  358. function editSettingForm() {
  359. settingFormDisabled.value = !settingFormDisabled.value;
  360. /** 如果取消了编辑模式,那么需要重置表单 */
  361. if (settingFormDisabled.value) {
  362. getAvePress();
  363. }
  364. }
  365. onMounted(() => {
  366. initWebSocket();
  367. // getMonitor()
  368. fetchConfigs('balancePressHome');
  369. getAvePress();
  370. loading.value = true;
  371. mountedThree().then(async () => {
  372. await setModelType('balancePressTun'); //balancePressBase
  373. loading.value = false;
  374. timer = null;
  375. await getMonitor(true);
  376. play('startSmoke', 'top', 30, 'open', 0);
  377. });
  378. // loading.value = false;
  379. // timer = null;
  380. // getMonitor(true);
  381. });
  382. onUnmounted(() => {
  383. destroy();
  384. if (timer) {
  385. clearTimeout(timer);
  386. }
  387. });
  388. </script>
  389. <style lang="less" scoped>
  390. @import '/@/design/vent/modal.less';
  391. @import '../../comment/less/workFace.less';
  392. @ventSpace: zxm;
  393. .monitor-container {
  394. margin-top: 60px;
  395. }
  396. .switch-button {
  397. width: 34px;
  398. height: 34px;
  399. position: fixed;
  400. // right: 5px;
  401. // bottom: 300px;
  402. z-index: 1000;
  403. background-repeat: no-repeat;
  404. background-size: 100% 100%;
  405. pointer-events: auto;
  406. transition: right 1s;
  407. }
  408. .icon-goto {
  409. --image-monitor-goto: url('/@/assets/images/company/monitor-goto.png');
  410. background-image: var(--image-monitor-goto);
  411. }
  412. .divider-line {
  413. border-bottom: 1px solid white;
  414. }
  415. </style>
  416. <style>
  417. /* .balancePress .zxm-modal-confirm-title {
  418. font-size: 20px;
  419. } */
  420. .balancePress .zxm-modal-confirm-content {
  421. font-size: 22px;
  422. }
  423. </style>