DeviceCtrlModal.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. <script setup lang="ts">
  2. import { computed, ref, watch } from 'vue';
  3. import { useRouter } from 'vue-router';
  4. import { Modal } from 'ant-design-vue';
  5. import SvgIcon from '@/components/SvgIcon.vue';
  6. import { useRequest } from '@/hooks/request';
  7. import { useViewVisible } from '@/hooks/view-visible';
  8. import { t } from '@/i18n';
  9. import { getGroupModuleDevData, updateGroupModuleDevData } from '@/api';
  10. import { waitTime } from '@/utils';
  11. import { DevParamChillerUnit, DevParamCoolingPump, DevParamCoolingTower } from '@/constants/device-params';
  12. import { DeviceType } from '../device-work-status/device-card';
  13. import type { EquipmentDetailsItem } from '@/types';
  14. interface Props {
  15. info?: EquipmentDetailsItem;
  16. }
  17. const props = defineProps<Props>();
  18. defineEmits<{
  19. openDevBatchExe: [];
  20. }>();
  21. const { visible, showView, hideView } = useViewVisible();
  22. const { isLoading, handleRequest } = useRequest();
  23. const deviceRealTimeData = ref<Record<string, number | string | undefined>>({});
  24. const deviceType = computed(() => {
  25. return props.info?.deviceQueryVo.deviceType;
  26. });
  27. const disableStartStopCtrl = computed(() => {
  28. const { isLocale, isAuto, isDisable } = getDeviceStatus();
  29. return isLocale || isAuto || isDisable;
  30. });
  31. const startStopTip = computed(() => {
  32. const { isLocale, isAuto, isDisable } = getDeviceStatus();
  33. const tips: string[] = [];
  34. if (isLocale) {
  35. tips.push(t('realTimeMonitor.startStopControlTipLocal'));
  36. }
  37. if (isAuto) {
  38. tips.push(t('realTimeMonitor.startStopControlTipAuto'));
  39. }
  40. if (isDisable) {
  41. tips.push(t('realTimeMonitor.startStopControlTipDisable'));
  42. }
  43. let tipText = '';
  44. tips.forEach((item, index) => {
  45. tipText += `${index + 1}. ${item};\n`;
  46. });
  47. return tipText;
  48. });
  49. const getDeviceStatus = () => {
  50. const { localRemoteStatus, manualAutoStatus, disableEnableStatus } = deviceRealTimeData.value;
  51. return {
  52. isLocale: localRemoteStatus === '本地',
  53. isAuto: manualAutoStatus === 1,
  54. isDisable: disableEnableStatus === 0,
  55. };
  56. };
  57. watch(visible, () => {
  58. if (visible.value) {
  59. getDeviceData();
  60. } else {
  61. deviceRealTimeData.value = {};
  62. }
  63. });
  64. const getDeviceData = () => {
  65. handleRequest(async () => {
  66. if (!props.info?.deviceQueryVo) {
  67. return;
  68. }
  69. const { id, deviceType } = props.info.deviceQueryVo;
  70. const data = await getGroupModuleDevData(id, deviceType);
  71. data.dataList.forEach((item) => {
  72. deviceRealTimeData.value[item.dataCode] = item.value;
  73. });
  74. });
  75. };
  76. const updateDeviceData = (paramCode: string, value?: string | number | null) => {
  77. handleRequest(async () => {
  78. if (!props.info?.deviceQueryVo) {
  79. return;
  80. }
  81. const { id } = props.info.deviceQueryVo;
  82. try {
  83. if (value !== undefined && value !== null) {
  84. await updateGroupModuleDevData(id, paramCode, value);
  85. }
  86. // eslint-disable-next-line no-useless-catch
  87. } catch (err) {
  88. throw err;
  89. } finally {
  90. await waitTime();
  91. getDeviceData();
  92. }
  93. });
  94. };
  95. const handleDisableEnableSwitch = () => {
  96. const { disableEnableStatus } = deviceRealTimeData.value;
  97. const title = disableEnableStatus ? t('common.disable') : t('common.enable');
  98. const value = disableEnableStatus ? 0 : 1;
  99. Modal.confirm({
  100. title: t('realTimeMonitor.confirmSwitchToMode', { mode: title }),
  101. closable: true,
  102. centered: true,
  103. onOk() {
  104. updateDeviceData('disableEnableStatus', value);
  105. },
  106. });
  107. };
  108. const handleAutoManualSwitch = () => {
  109. const { manualAutoStatus } = deviceRealTimeData.value;
  110. const title = manualAutoStatus ? t('common.manual') : t('common.automatic');
  111. const content = manualAutoStatus
  112. ? t('realTimeMonitor.confirmSwitchToManualTip')
  113. : t('realTimeMonitor.confirmSwitchToAutoTip');
  114. const value = manualAutoStatus ? 0 : 1;
  115. Modal.confirm({
  116. title: t('realTimeMonitor.confirmSwitchToMode', { mode: title }),
  117. content,
  118. closable: true,
  119. centered: true,
  120. onOk() {
  121. updateDeviceData('manualAutoStatus', value);
  122. },
  123. });
  124. };
  125. const handleStartStopSwitch = () => {
  126. const { startStopOrder } = deviceRealTimeData.value;
  127. const title = startStopOrder ? t('common.confirmClose') : t('common.confirmOpen');
  128. const value = startStopOrder ? 0 : 1;
  129. Modal.confirm({
  130. title: title + props.info?.deviceQueryVo.deviceName,
  131. closable: true,
  132. centered: true,
  133. onOk() {
  134. updateDeviceData('startStopOrder', value);
  135. },
  136. });
  137. };
  138. const router = useRouter();
  139. const goDevWorkStatus = () => {
  140. if (!props.info?.deviceQueryVo) {
  141. return;
  142. }
  143. const { id, groupId, deviceType } = props.info.deviceQueryVo;
  144. router.push({
  145. path: `/ai-smart-ctrl/device-group/${groupId}`,
  146. query: {
  147. tab: 'deviceWorkStatus',
  148. deviceId: id,
  149. deviceType,
  150. r: Date.now(),
  151. },
  152. });
  153. };
  154. defineExpose({
  155. showView,
  156. hideView,
  157. });
  158. </script>
  159. <template>
  160. <AModal
  161. v-model:open="visible"
  162. wrap-class-name="hvac-modal"
  163. :closable="false"
  164. :centered="true"
  165. :width="460"
  166. :footer="null"
  167. >
  168. <template #title>
  169. <div class="dev-ctrl-modal-header">
  170. <span>{{ info?.deviceQueryVo.deviceName }}</span>
  171. <span class="dev-ctrl-modal-operate" @click="goDevWorkStatus">
  172. {{ $t('common.viewMore') }}
  173. <SvgIcon name="right" />
  174. </span>
  175. </div>
  176. </template>
  177. <template v-if="deviceType === DeviceType.冷水主机">
  178. <div class="dev-ctrl-modal-item">
  179. <span>{{ $t('realTimeMonitor.chilledWaterOutletTemperature') }}</span>
  180. <span>{{ deviceRealTimeData[DevParamChillerUnit.冷冻水出水温度] ?? '-' }}℃</span>
  181. </div>
  182. <div class="dev-ctrl-modal-item">
  183. <span>{{ $t('realTimeMonitor.loadRate') }}</span>
  184. <span>{{ deviceRealTimeData[DevParamChillerUnit.负载率] ?? '-' }}%</span>
  185. </div>
  186. <div class="dev-ctrl-modal-item">
  187. <span>{{ $t('realTimeMonitor.activePower') }}</span>
  188. <span>{{ deviceRealTimeData[DevParamChillerUnit.有功功率] ?? '-' }}kW</span>
  189. </div>
  190. </template>
  191. <template v-if="deviceType === DeviceType.冷却塔">
  192. <div class="dev-ctrl-modal-item">
  193. <span>{{ $t('realTimeMonitor.localRemoteStatus') }}</span>
  194. <span>{{ deviceRealTimeData[DevParamCoolingTower.本地远程状态] ?? '-' }}</span>
  195. </div>
  196. <div class="dev-ctrl-modal-item">
  197. <span>{{ $t('realTimeMonitor.activePower') }}</span>
  198. <span>{{ deviceRealTimeData[DevParamCoolingTower.有功功率] ?? '-' }}kW</span>
  199. </div>
  200. <div class="dev-ctrl-modal-item">
  201. <span>{{ $t('realTimeMonitor.runningTime') }}</span>
  202. <span>{{ deviceRealTimeData[DevParamCoolingTower.运行时间] ?? '-' }}{{ $t('common.hour') }}</span>
  203. </div>
  204. </template>
  205. <template v-if="deviceType === DeviceType.冷冻泵 || deviceType === DeviceType.冷却泵">
  206. <div class="dev-ctrl-modal-item">
  207. <span>{{ $t('realTimeMonitor.localRemoteStatus') }}</span>
  208. <span>{{ deviceRealTimeData[DevParamCoolingPump.本地远程状态] ?? '-' }}</span>
  209. </div>
  210. <div class="dev-ctrl-modal-item">
  211. <span>{{ $t('realTimeMonitor.activePower') }}</span>
  212. <span>{{ deviceRealTimeData[DevParamCoolingPump.有功功率] ?? '-' }}kW</span>
  213. </div>
  214. <div class="dev-ctrl-modal-item">
  215. <span>{{ $t('realTimeMonitor.runningTime') }}</span>
  216. <span>{{ deviceRealTimeData[DevParamCoolingPump.运行时间] ?? '-' }}{{ $t('common.hour') }}</span>
  217. </div>
  218. </template>
  219. <div class="dev-ctrl-modal-separator"></div>
  220. <div class="dev-ctrl-modal-item">
  221. <span></span>
  222. <span class="dev-ctrl-modal-operate" @click="$emit('openDevBatchExe')">
  223. {{ $t('common.batchExecution') }}
  224. <SvgIcon name="right" />
  225. </span>
  226. </div>
  227. <div class="dev-ctrl-modal-item">
  228. <span>{{ $t('realTimeMonitor.enableDisable') }}</span>
  229. <ASwitch
  230. :checked="deviceRealTimeData.disableEnableStatus"
  231. :checked-value="1"
  232. :un-checked-value="0"
  233. @click="handleDisableEnableSwitch"
  234. />
  235. </div>
  236. <div class="dev-ctrl-modal-item">
  237. <span>{{ $t('realTimeMonitor.autoManual') }}</span>
  238. <ASwitch
  239. :checked="deviceRealTimeData.manualAutoStatus"
  240. :checked-value="1"
  241. :un-checked-value="0"
  242. @click="handleAutoManualSwitch"
  243. />
  244. </div>
  245. <div class="dev-ctrl-modal-item">
  246. <span>{{ $t('realTimeMonitor.startStopControl') }}</span>
  247. <span class="dev-ctrl-modal-start-stop-right">
  248. <ATooltip overlay-class-name="hvac-tooltip">
  249. <template #title>{{ startStopTip }}</template>
  250. <SvgIcon v-show="disableStartStopCtrl" name="info-cirlce-o" />
  251. </ATooltip>
  252. <ASwitch
  253. :checked="deviceRealTimeData.startStopOrder"
  254. :checked-value="1"
  255. :un-checked-value="0"
  256. :disabled="disableStartStopCtrl"
  257. @click="handleStartStopSwitch"
  258. />
  259. </span>
  260. </div>
  261. <template v-if="deviceType === DeviceType.冷水主机">
  262. <div class="dev-ctrl-modal-item">
  263. <span>{{ $t('realTimeMonitor.chilledWaterOutletSetValue') }}</span>
  264. <AInputNumber
  265. class="dev-ctrl-chiller-input"
  266. v-model:value="deviceRealTimeData[DevParamChillerUnit.冷冻水出水温度设定值]"
  267. :controls="false"
  268. @change="updateDeviceData(DevParamChillerUnit.冷冻水出水温度设定值, $event)"
  269. />
  270. </div>
  271. <div class="dev-ctrl-modal-item">
  272. <span>{{ $t('realTimeMonitor.loadRateLimitSetValue') }}</span>
  273. <AInputNumber
  274. class="dev-ctrl-chiller-input"
  275. v-model:value="deviceRealTimeData[DevParamChillerUnit.负载率限制设定值]"
  276. :controls="false"
  277. @change="updateDeviceData(DevParamChillerUnit.负载率限制设定值, $event)"
  278. />
  279. </div>
  280. </template>
  281. <ASpin v-if="isLoading" class="center-loading" :spinning="true" />
  282. </AModal>
  283. </template>
  284. <style lang="scss" scoped>
  285. .dev-ctrl-modal-header {
  286. display: flex;
  287. align-items: center;
  288. justify-content: space-between;
  289. }
  290. .dev-ctrl-modal-item {
  291. display: flex;
  292. align-items: center;
  293. justify-content: space-between;
  294. line-height: 24px;
  295. > span {
  296. &:first-child {
  297. color: var(--antd-color-text-secondary);
  298. }
  299. &:last-child {
  300. color: var(--antd-color-text);
  301. }
  302. }
  303. > span.dev-ctrl-modal-operate {
  304. color: var(--antd-color-primary);
  305. }
  306. & + & {
  307. margin-top: 16px;
  308. }
  309. }
  310. .dev-ctrl-modal-separator {
  311. margin-block: 16px;
  312. border: 1px solid #e4e7ed;
  313. }
  314. .dev-ctrl-modal-operate {
  315. display: flex;
  316. align-items: center;
  317. font-size: 14px;
  318. font-weight: 500;
  319. color: var(--antd-color-primary);
  320. cursor: pointer;
  321. i {
  322. margin-left: 8px;
  323. font-size: 12px;
  324. }
  325. }
  326. .dev-ctrl-modal-start-stop-right {
  327. display: flex;
  328. align-items: center;
  329. i {
  330. margin-right: 8px;
  331. font-size: 12px;
  332. color: #999;
  333. }
  334. }
  335. .dev-ctrl-chiller-input {
  336. width: 120px;
  337. }
  338. </style>