EnvMonitor.vue 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976
  1. <script setup lang="ts">
  2. import { computed, nextTick, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
  3. import BScroll from '@better-scroll/core';
  4. import MouseWheel from '@better-scroll/mouse-wheel';
  5. import { message } from 'ant-design-vue';
  6. import ButtonTabs from '@/components/ButtonTabs.vue';
  7. import LineChart from '@/components/LineChart.vue';
  8. import SvgIcon from '@/components/SvgIcon.vue';
  9. import { useDictData } from '@/hooks/dict-data';
  10. import { useRequest } from '@/hooks/request';
  11. import { t } from '@/i18n';
  12. import {
  13. addMonitorPoint,
  14. addRegion,
  15. deleteMonitorPoint,
  16. getDeviceGroupList,
  17. getDeviceListOptions,
  18. getDeviceListSimple,
  19. getGroupRegions,
  20. getMonitorPointAlarmHistory,
  21. getMonitorPointInfo,
  22. getPageList,
  23. getRegionsPointsData,
  24. getRegionsPointsValue,
  25. queryDevicesList,
  26. regionDelete,
  27. regionUpdate,
  28. updateMonitorPoint,
  29. updateRegionMonitorPoint,
  30. } from '@/api';
  31. import { DictCode, HumitureType } from '@/constants';
  32. import AreaEditor from './AreaEditor.vue';
  33. import AreaPreview from './AreaPreview.vue';
  34. import EnvMonitorList from './EnvMonitorList.vue';
  35. import HumitureCurve from './HumitureCurve.vue';
  36. import type { CSSProperties } from 'vue';
  37. import type { Meta2dData } from '@meta2d/core';
  38. import type { FormInstance, Rule } from 'ant-design-vue/es/form';
  39. import type { DefaultOptionType, SelectValue } from 'ant-design-vue/es/select';
  40. import type {
  41. AlarmHistoryItem,
  42. DeviceGroup,
  43. DeviceGroupItem,
  44. DeviceParams,
  45. DeviceParamType,
  46. DevicesListItem,
  47. DictValue,
  48. GroupRegions,
  49. MonitoringForm,
  50. MonitoringPointData,
  51. OutdooForm,
  52. RegionNameList,
  53. RegionsPointsItem,
  54. } from '@/types';
  55. interface TimeList {
  56. time: string;
  57. integral: boolean;
  58. index: number;
  59. backgroundShow: boolean;
  60. }
  61. interface RunStatusList {
  62. id: number;
  63. name: string;
  64. }
  65. const { dictData: paramAlgOperator, getDictData: getParamAlgOperator } = useDictData(DictCode.ParamAlgOperator);
  66. const envMonitorListRef = useTemplateRef('envMonitorList');
  67. const temperatureDifference = ref<DictValue[]>([]);
  68. const oneDeviceGroup = ref<DeviceGroup[]>([]);
  69. const twoDeviceGroup = ref<DeviceGroup[]>([]);
  70. const runStatusList = ref<RunStatusList[]>([]);
  71. const inputType = ref<number>(1);
  72. const gradeOne = ref<number | undefined>(undefined);
  73. const gradeTwo = ref<number | undefined>(undefined);
  74. const monitoringPointOpen = ref<boolean>(false);
  75. const outdoorOpen = ref<boolean>(false);
  76. const regionNameOpen = ref<boolean>(false);
  77. const monitoringDataOpen = ref<boolean>(false);
  78. const regionCopyOpen = ref<boolean>(false);
  79. const regionName = ref<string>('');
  80. const regionNameEditor = ref<string>('');
  81. const groupRegions = ref<GroupRegions[]>([]);
  82. const titleRegions = ref<boolean>(true);
  83. const titleMonitoring = ref<boolean>(true);
  84. const deviceGroup = ref<DeviceGroupItem[]>([]);
  85. const returnDevicesList = ref<DevicesListItem[]>([]);
  86. const supplyDevicesList = ref<DevicesListItem[]>([]);
  87. const outdoorDevicesList = ref<DevicesListItem[]>([]);
  88. const freshDevicesList = ref<DevicesListItem[]>([]);
  89. const runDevicesList = ref<DevicesListItem[]>([]);
  90. const returnDeviceParamsList = ref<DeviceParams[]>([]);
  91. const supplyDeviceParamsList = ref<DeviceParams[]>([]);
  92. const outdoorDeviceParamsList = ref<DeviceParams[]>([]);
  93. const freshDeviceParamsList = ref<DeviceParams[]>([]);
  94. const runDeviceParamsList = ref<DeviceParamType[]>([]);
  95. const monitoringPointData = ref<MonitoringPointData[]>([]);
  96. const regionNameList = ref<RegionNameList[]>([]);
  97. const regionList = ref<RegionsPointsItem[]>([]);
  98. const monitoringList = ref<RegionsPointsItem[]>([]);
  99. const selectId = ref<number>(0);
  100. const monitoringName = ref<string>();
  101. const monitoringId = ref<number>();
  102. const formRef = ref<FormInstance>();
  103. const listDisplay = ref<boolean>(true);
  104. const timeList = ref<TimeList[]>([]);
  105. const timeLineIndex = ref<number>(0);
  106. const chooseTime = ref<string>();
  107. const alarmHistoryList = ref<AlarmHistoryItem[]>([]);
  108. const monitoringForm = ref<MonitoringForm>({
  109. name: '',
  110. tempHumidityControlMode: '2',
  111. regionId: undefined,
  112. returnDevGroupId: undefined,
  113. returnDevId: undefined,
  114. returnTempParamCode: undefined,
  115. returnHumidityParamCode: undefined,
  116. supplyDevGroupId: undefined,
  117. supplyTempParamCode: undefined,
  118. supplyHumidityParamCode: undefined,
  119. outdoorDevGroupId: undefined,
  120. outdoorDevId: undefined,
  121. outdoorTempParamCode: undefined,
  122. outdoorHumidityParamCode: undefined,
  123. tempUpper: undefined,
  124. tempLower: undefined,
  125. tempPreset: undefined,
  126. humidityUpper: undefined,
  127. humidityLower: undefined,
  128. humidityPreset: undefined,
  129. runStatusFlag: 0,
  130. supplyReturnTempDiff: undefined,
  131. supplyUpperTempDiff: undefined,
  132. runStatusDevGroupId: undefined,
  133. runStatusDevId: undefined,
  134. runStatusParamCode: undefined,
  135. runStatusConditionCode: undefined,
  136. runStatusConditionValue: undefined,
  137. });
  138. const outdooForm = ref<OutdooForm>({
  139. regionId: undefined,
  140. outsideDevGroupId: undefined,
  141. outsideDevId: undefined,
  142. outsideTempParamCode: '',
  143. outsideHumidityParamCode: '',
  144. outsideEnthalpyParamCode: '',
  145. });
  146. const headerStyle: CSSProperties = {
  147. borderBottom: 0,
  148. padding: '16px 16px 0 24px',
  149. };
  150. const footerStyle: CSSProperties = {
  151. borderTop: 0,
  152. padding: '16px 24px',
  153. };
  154. const rules: Record<string, Rule[]> = {
  155. name: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  156. regionId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  157. tempHumidityControlMode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  158. returnDevGroupId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  159. returnDevId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  160. returnTempParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  161. returnHumidityParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  162. supplyDevGroupId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  163. supplyDevId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  164. supplyTempParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  165. supplyHumidityParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  166. outdoorDevGroupId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  167. outdoorDevId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  168. outdoorTempParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  169. outdoorHumidityParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  170. runStatusFlag: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  171. supplyReturnTempDiff: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  172. supplyUpperTempDiff: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  173. };
  174. const { handleRequest } = useRequest();
  175. const getGroupRegionsList = () => {
  176. handleRequest(async () => {
  177. if (gradeTwo.value) {
  178. groupRegions.value = await getGroupRegions(gradeTwo.value);
  179. }
  180. });
  181. };
  182. const regionNameOk = () => {
  183. if (!regionName.value) {
  184. return message.warning(t('envMonitor.pleaseRegionName'));
  185. }
  186. handleRequest(async () => {
  187. if (gradeTwo.value && regionName.value) {
  188. if (titleRegions.value) {
  189. await addRegion({
  190. devGroupId: gradeTwo.value,
  191. regionName: regionName.value,
  192. });
  193. } else {
  194. if (regionNameEditor.value != regionName.value) {
  195. await regionUpdate({
  196. id: monitoringForm.value.regionId,
  197. devGroupId: gradeTwo.value,
  198. regionName: regionName.value,
  199. });
  200. }
  201. }
  202. getGroupRegionsList();
  203. if (gradeTwo.value) {
  204. getRegionsPointsList(gradeTwo.value, false);
  205. obtainRegionsPointsData(gradeTwo.value);
  206. }
  207. regionNameOpen.value = false;
  208. }
  209. });
  210. };
  211. const regionNameDelete = () => {
  212. if (!regionName.value) {
  213. return message.warning(t('envMonitor.pleaseRegionName'));
  214. }
  215. handleRequest(async () => {
  216. if (monitoringForm.value.regionId) {
  217. await regionDelete(monitoringForm.value.regionId);
  218. monitoringForm.value.regionId = undefined;
  219. getGroupRegionsList();
  220. if (gradeTwo.value) {
  221. getRegionsPointsList(gradeTwo.value, false);
  222. obtainRegionsPointsData(gradeTwo.value);
  223. }
  224. regionNameOpen.value = false;
  225. }
  226. });
  227. };
  228. const addRegionName = () => {
  229. titleRegions.value = true;
  230. regionNameOpen.value = true;
  231. regionName.value = '';
  232. };
  233. const addRegionList = (value: SelectValue, option: DefaultOptionType) => {
  234. regionNameEditor.value = option.regionName;
  235. regionName.value = option.regionName;
  236. };
  237. const editingRegionName = () => {
  238. if (monitoringForm.value.regionId) {
  239. groupRegions.value.forEach((item) => {
  240. if (item.id === monitoringForm.value.regionId) {
  241. regionName.value = item.regionName;
  242. }
  243. });
  244. titleRegions.value = false;
  245. regionNameOpen.value = true;
  246. } else {
  247. return message.warning(t('envMonitor.selectNameArea'));
  248. }
  249. };
  250. const addMonitoringPoint = () => {
  251. titleMonitoring.value = true;
  252. monitoringPointOpen.value = true;
  253. };
  254. const addAllGatewayList = (value: number) => {
  255. handleRequest(async () => {
  256. const data = await getDeviceGroupList({
  257. parentId: value,
  258. });
  259. if (data.length) {
  260. if (value === -1) {
  261. oneDeviceGroup.value = data;
  262. gradeOne.value = data[0].id;
  263. } else {
  264. twoDeviceGroup.value = data;
  265. gradeTwo.value = data[0].id;
  266. }
  267. }
  268. });
  269. };
  270. const { isLoading, handleRequest: handleEnvMonitorRequest } = useRequest();
  271. const getRegionsPointsList = (value: number, show: boolean) => {
  272. monitoringPointData.value = [];
  273. regionNameList.value = [];
  274. monitoringList.value = [];
  275. copyToRegionId.value = undefined;
  276. handleEnvMonitorRequest(async () => {
  277. let data: RegionsPointsItem[] = [];
  278. if (show) {
  279. if (chooseTime.value) {
  280. data = await getRegionsPointsValue(value, {
  281. endTime: `${getCurrentDate()} ${chooseTime.value.length > 6 ? chooseTime.value : chooseTime.value + ':00'}`,
  282. });
  283. regionList.value = data;
  284. }
  285. } else {
  286. data = await getRegionsPointsData(value);
  287. }
  288. if (data.length) {
  289. data.forEach((item) => {
  290. const { id, regionName } = item;
  291. if (item.points.length) {
  292. monitoringPointData.value.push(...item.points);
  293. monitoringList.value.push({ ...item, name: item.regionName });
  294. }
  295. regionNameList.value.push({
  296. name: regionName,
  297. id,
  298. });
  299. });
  300. if (monitoringPointData.value.length) {
  301. monitoringPointData.value.sort((item1, item2) => {
  302. // 优先级:3 > 2 > 其他
  303. const priority1 = item1.status === 3 ? 1 : item1.status === 2 ? 2 : item1.status === 1 ? 3 : 4;
  304. const priority2 = item2.status === 3 ? 1 : item2.status === 2 ? 2 : item2.status === 1 ? 3 : 4;
  305. return priority1 - priority2;
  306. });
  307. monitoringId.value = monitoringPointData.value[0].id;
  308. selectId.value = monitoringPointData.value[0].regionId;
  309. }
  310. }
  311. });
  312. };
  313. const confirmTimeLine = () => {
  314. if (gradeTwo.value) {
  315. getRegionsPointsList(gradeTwo.value, true);
  316. }
  317. };
  318. const obtainRegionsPointsData = (value: number) => {
  319. handleRequest(async () => {
  320. regionList.value = await getRegionsPointsData(value);
  321. });
  322. };
  323. const adddDeviceGroup = (value: SelectValue, option: DefaultOptionType, judgment: number) => {
  324. getDevicesGroupList(option.id, judgment, true);
  325. };
  326. const adddDevice = (value: SelectValue, option: DefaultOptionType, judgment: number) => {
  327. getDeviceParamsList(option.id, judgment, true);
  328. };
  329. const adddRunStatusDevice = (value: SelectValue, option: DefaultOptionType) => {
  330. monitoringForm.value.runStatusParamCode = undefined;
  331. monitoringForm.value.runStatusConditionCode = undefined;
  332. monitoringForm.value.runStatusConditionValue = undefined;
  333. getDeviceListOptionsList(option.id, false, '');
  334. };
  335. const getDeviceListOptionsList = (id: number, show: boolean, runStatusParamCode: string) => {
  336. handleRequest(async () => {
  337. runDeviceParamsList.value = await getDeviceListOptions(id);
  338. if (show) {
  339. runStatusList.value = [];
  340. runDeviceParamsList.value.forEach((item) => {
  341. if (item.deviceParamCode === runStatusParamCode) {
  342. inputType.value = item.type;
  343. if (item.type === 1) {
  344. item.candidates.forEach((item: string, index: number) => {
  345. runStatusList.value.push({
  346. id: index,
  347. name: item,
  348. });
  349. });
  350. }
  351. }
  352. });
  353. }
  354. });
  355. };
  356. const adddParametersDevice = (value: SelectValue, option: DefaultOptionType) => {
  357. runStatusList.value = [];
  358. inputType.value = option.type;
  359. if (option.type === 1) {
  360. option.candidates.forEach((item: string, index: number) => {
  361. runStatusList.value.push({
  362. id: index,
  363. name: item,
  364. });
  365. });
  366. }
  367. };
  368. const getDeviceParamsList = (id: number, judgment: number, show: boolean) => {
  369. handleRequest(async () => {
  370. const data = await getDeviceListSimple(id);
  371. if (judgment === HumitureType.ReturnAir) {
  372. returnDeviceParamsList.value = data;
  373. if (show) {
  374. monitoringForm.value.returnHumidityParamCode = undefined;
  375. monitoringForm.value.returnTempParamCode = undefined;
  376. }
  377. } else if (judgment === HumitureType.SupplyAir) {
  378. supplyDeviceParamsList.value = data;
  379. if (show) {
  380. monitoringForm.value.supplyHumidityParamCode = undefined;
  381. monitoringForm.value.supplyTempParamCode = undefined;
  382. }
  383. } else if (judgment === HumitureType.Outdoor) {
  384. outdoorDeviceParamsList.value = data;
  385. if (show) {
  386. outdooForm.value.outsideEnthalpyParamCode = '';
  387. outdooForm.value.outsideHumidityParamCode = '';
  388. outdooForm.value.outsideTempParamCode = '';
  389. }
  390. } else if (judgment === HumitureType.FreshAir) {
  391. freshDeviceParamsList.value = data;
  392. if (show) {
  393. monitoringForm.value.outdoorTempParamCode = undefined;
  394. monitoringForm.value.outdoorHumidityParamCode = undefined;
  395. }
  396. }
  397. });
  398. };
  399. const getDevicesGroupList = (id: number, judgment: number, show: boolean) => {
  400. handleRequest(async () => {
  401. const { records } = await queryDevicesList({
  402. pageIndex: 1,
  403. pageSize: 99999,
  404. groupId: id,
  405. });
  406. if (judgment === HumitureType.ReturnAir) {
  407. returnDevicesList.value = records;
  408. if (show) {
  409. monitoringForm.value.returnDevId = undefined;
  410. monitoringForm.value.returnHumidityParamCode = undefined;
  411. monitoringForm.value.returnTempParamCode = undefined;
  412. }
  413. } else if (judgment === HumitureType.SupplyAir) {
  414. supplyDevicesList.value = records;
  415. if (show) {
  416. monitoringForm.value.supplyDevId = undefined;
  417. monitoringForm.value.supplyHumidityParamCode = undefined;
  418. monitoringForm.value.supplyTempParamCode = undefined;
  419. }
  420. } else if (judgment === HumitureType.Outdoor) {
  421. outdoorDevicesList.value = records;
  422. if (show) {
  423. outdooForm.value.outsideDevId = undefined;
  424. outdooForm.value.outsideEnthalpyParamCode = '';
  425. outdooForm.value.outsideHumidityParamCode = '';
  426. outdooForm.value.outsideTempParamCode = '';
  427. }
  428. } else if (judgment === HumitureType.FreshAir) {
  429. freshDevicesList.value = records;
  430. if (show) {
  431. monitoringForm.value.outdoorDevId = undefined;
  432. monitoringForm.value.outdoorTempParamCode = undefined;
  433. monitoringForm.value.outdoorHumidityParamCode = undefined;
  434. }
  435. } else if (judgment === HumitureType.OperatingStatus) {
  436. runDevicesList.value = records;
  437. if (show) {
  438. monitoringForm.value.runStatusDevId = undefined;
  439. monitoringForm.value.runStatusParamCode = undefined;
  440. monitoringForm.value.runStatusConditionCode = undefined;
  441. monitoringForm.value.runStatusConditionValue = undefined;
  442. }
  443. }
  444. });
  445. };
  446. const deleteMonitoringPoint = () => {
  447. if (!titleMonitoring.value) {
  448. handleRequest(async () => {
  449. if (monitoringId.value) {
  450. await deleteMonitorPoint(monitoringId.value);
  451. if (gradeTwo.value) {
  452. getRegionsPointsList(gradeTwo.value, false);
  453. obtainRegionsPointsData(gradeTwo.value);
  454. timeLineIndex.value = timeList.value.length - 1;
  455. }
  456. closeModal();
  457. }
  458. });
  459. }
  460. monitoringPointOpen.value = false;
  461. };
  462. const saveMonitoringPoint = () => {
  463. formRef.value
  464. ?.validate()
  465. .then(() => {
  466. handleRequest(async () => {
  467. if (titleMonitoring.value) {
  468. delete monitoringForm.value.id;
  469. await addMonitorPoint(monitoringForm.value);
  470. } else {
  471. await updateMonitorPoint(monitoringForm.value);
  472. }
  473. if (gradeTwo.value) {
  474. getRegionsPointsList(gradeTwo.value, false);
  475. obtainRegionsPointsData(gradeTwo.value);
  476. }
  477. closeModal();
  478. monitoringPointOpen.value = false;
  479. });
  480. })
  481. .catch(() => {});
  482. };
  483. const getDeviceGroup = () => {
  484. handleRequest(async () => {
  485. deviceGroup.value = await getPageList();
  486. });
  487. };
  488. const offDrawer = () => {
  489. monitoringPointOpen.value = false;
  490. closeModal();
  491. };
  492. const selectClick = (id: number) => {
  493. selectId.value = id;
  494. copyToRegionId.value = undefined;
  495. };
  496. const historicalDataClick = (data: MonitoringPointData) => {
  497. monitoringName.value = data.name;
  498. monitoringId.value = data.id;
  499. selectId.value = data.regionId;
  500. monitoringDataOpen.value = true;
  501. };
  502. const editorClick = (monitoringPointId: number) => {
  503. handleRequest(async () => {
  504. const {
  505. humidityLower,
  506. humidityPreset,
  507. humidityUpper,
  508. name,
  509. regionId,
  510. returnDevGroupId,
  511. returnDevId,
  512. returnHumidityParamCode,
  513. returnTempParamCode,
  514. supplyDevGroupId,
  515. supplyDevId,
  516. supplyHumidityParamCode,
  517. supplyTempParamCode,
  518. tempHumidityControlMode,
  519. tempLower,
  520. tempPreset,
  521. tempUpper,
  522. id,
  523. outdoorDevGroupId,
  524. outdoorDevId,
  525. outdoorTempParamCode,
  526. outdoorHumidityParamCode,
  527. runStatusFlag,
  528. supplyReturnTempDiff,
  529. supplyUpperTempDiff,
  530. runStatusDevGroupId,
  531. runStatusDevId,
  532. runStatusParamCode,
  533. runStatusConditionCode,
  534. runStatusConditionValue,
  535. } = await getMonitorPointInfo(monitoringPointId);
  536. Object.assign(monitoringForm.value, {
  537. humidityLower,
  538. humidityPreset,
  539. humidityUpper,
  540. name,
  541. regionId,
  542. returnDevGroupId,
  543. returnDevId,
  544. returnHumidityParamCode,
  545. returnTempParamCode,
  546. supplyDevGroupId,
  547. supplyDevId,
  548. supplyHumidityParamCode,
  549. supplyTempParamCode,
  550. tempHumidityControlMode: String(tempHumidityControlMode),
  551. tempLower,
  552. tempPreset,
  553. tempUpper,
  554. id,
  555. outdoorDevGroupId,
  556. outdoorDevId,
  557. outdoorTempParamCode,
  558. outdoorHumidityParamCode,
  559. runStatusFlag,
  560. supplyReturnTempDiff,
  561. supplyUpperTempDiff,
  562. runStatusDevGroupId,
  563. runStatusDevId,
  564. runStatusParamCode,
  565. runStatusConditionCode,
  566. runStatusConditionValue,
  567. });
  568. monitoringId.value = id;
  569. getDevicesGroupList(returnDevGroupId, HumitureType.ReturnAir, false);
  570. getDevicesGroupList(supplyDevGroupId, HumitureType.SupplyAir, false);
  571. if (monitoringForm.value.tempHumidityControlMode === '1') {
  572. getDevicesGroupList(outdoorDevGroupId, HumitureType.FreshAir, false);
  573. }
  574. getDeviceParamsList(returnDevId, HumitureType.ReturnAir, false);
  575. getDeviceParamsList(supplyDevId, HumitureType.SupplyAir, false);
  576. if (monitoringForm.value.tempHumidityControlMode === '1') {
  577. getDeviceParamsList(outdoorDevId, HumitureType.FreshAir, false);
  578. }
  579. if (monitoringForm.value.runStatusFlag !== 0) {
  580. if (runStatusDevGroupId) {
  581. getDevicesGroupList(runStatusDevGroupId, HumitureType.OperatingStatus, false);
  582. }
  583. if (runStatusDevId) {
  584. if (runStatusParamCode) {
  585. getDeviceListOptionsList(runStatusDevId, true, runStatusParamCode);
  586. }
  587. }
  588. }
  589. titleMonitoring.value = false;
  590. monitoringPointOpen.value = true;
  591. });
  592. };
  593. const closeModal = () => {
  594. returnDevicesList.value = [];
  595. returnDeviceParamsList.value = [];
  596. supplyDevicesList.value = [];
  597. supplyDeviceParamsList.value = [];
  598. freshDevicesList.value = [];
  599. freshDeviceParamsList.value = [];
  600. runDevicesList.value = [];
  601. runDeviceParamsList.value = [];
  602. runStatusList.value = [];
  603. monitoringForm.value = {
  604. name: '',
  605. tempHumidityControlMode: '2',
  606. regionId: undefined,
  607. returnDevGroupId: undefined,
  608. returnDevId: undefined,
  609. returnTempParamCode: undefined,
  610. returnHumidityParamCode: undefined,
  611. supplyDevGroupId: undefined,
  612. supplyTempParamCode: undefined,
  613. supplyHumidityParamCode: undefined,
  614. outdoorDevGroupId: undefined,
  615. outdoorDevId: undefined,
  616. outdoorTempParamCode: undefined,
  617. outdoorHumidityParamCode: undefined,
  618. tempUpper: undefined,
  619. tempLower: undefined,
  620. tempPreset: undefined,
  621. humidityUpper: undefined,
  622. humidityLower: undefined,
  623. humidityPreset: undefined,
  624. runStatusFlag: 0,
  625. supplyReturnTempDiff: undefined,
  626. supplyUpperTempDiff: undefined,
  627. runStatusDevGroupId: undefined,
  628. runStatusDevId: undefined,
  629. runStatusParamCode: undefined,
  630. runStatusConditionCode: undefined,
  631. runStatusConditionValue: undefined,
  632. };
  633. formRef.value?.resetFields();
  634. };
  635. const addOutdoorDrawer = () => {
  636. outdoorOpen.value = true;
  637. regionList.value.forEach((item) => {
  638. const {
  639. outsideEnthalpyParamCode,
  640. outsideHumidityParamCode,
  641. outsideTempParamCode,
  642. outsideDevGroupId,
  643. outsideDevId,
  644. id,
  645. } = item;
  646. if (item.id === selectId.value) {
  647. Object.assign(outdooForm.value, {
  648. outsideEnthalpyParamCode,
  649. outsideHumidityParamCode,
  650. outsideTempParamCode,
  651. outsideDevGroupId,
  652. outsideDevId,
  653. regionId: id,
  654. });
  655. if (outsideDevGroupId) {
  656. getDevicesGroupList(outsideDevGroupId, HumitureType.Outdoor, false);
  657. } else {
  658. outdoorDevicesList.value = [];
  659. }
  660. if (outsideDevId) {
  661. getDeviceParamsList(outsideDevId, HumitureType.Outdoor, false);
  662. } else {
  663. outdoorDeviceParamsList.value = [];
  664. }
  665. }
  666. });
  667. };
  668. const saveOutdoo = () => {
  669. handleRequest(async () => {
  670. await updateRegionMonitorPoint(outdooForm.value);
  671. if (gradeTwo.value) {
  672. obtainRegionsPointsData(gradeTwo.value);
  673. }
  674. outdoorOpen.value = false;
  675. });
  676. };
  677. const offOutdoorDrawer = () => {
  678. outdoorOpen.value = false;
  679. };
  680. const offMonitoringDrawer = () => {
  681. monitoringDataOpen.value = false;
  682. };
  683. const copyRegion = () => {
  684. regionCopyOpen.value = true;
  685. };
  686. const switchDisplay = () => {
  687. listDisplay.value = !listDisplay.value;
  688. if (!listDisplay.value) {
  689. envMonitorListRef.value?.getMonitoringList();
  690. }
  691. };
  692. const scrollWrapper = ref<HTMLElement | null>(null);
  693. const scrollContent = ref<HTMLElement | null>(null); // 新增内容层 ref
  694. let bs: BScroll | null = null;
  695. const generateTimeArray = async () => {
  696. const now = new Date();
  697. const currentHour = now.getHours();
  698. const currentMinute = now.getMinutes();
  699. const minutes = [0, 10, 20, 30, 40, 50];
  700. const result = [];
  701. let index = 0;
  702. for (let hour = 0; hour <= currentHour; hour++) {
  703. for (const minute of minutes) {
  704. // 过滤超过当前时间的条目
  705. if (hour === currentHour && minute > currentMinute) break;
  706. // 生成时间字符串并添加 integral 标识
  707. const timeStr = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
  708. result.push({
  709. time: timeStr,
  710. integral: minute === 0, // 分钟为0时标记为整点
  711. index: index++,
  712. backgroundShow: false,
  713. });
  714. }
  715. }
  716. timeList.value = result;
  717. // 关键步骤:数据更新后刷新滚动
  718. await nextTick();
  719. timeLineIndex.value = timeList.value.length - 1;
  720. chooseTime.value = getCurrentTime();
  721. // 关键修复:延迟确保渲染完成
  722. setTimeout(() => {
  723. returnCurrently();
  724. }, 50); // 增加短延迟
  725. };
  726. // 时间字符串转分钟数(支持带日期和不带日期)
  727. function parseTimeToMinutes(timeStr: string): number {
  728. if (timeStr === null) return 24 * 60; // null视为次日0点
  729. if (!timeStr.trim()) return 24 * 60; // 空字符串视为次日0点
  730. const timePart = timeStr.includes(' ') ? timeStr.split(' ')[1] : timeStr;
  731. const [hours, minutes] = timePart.split(':').slice(0, 2).map(Number);
  732. return hours * 60 + minutes;
  733. }
  734. const getAlarmHistoryList = () => {
  735. handleRequest(async () => {
  736. if (gradeTwo.value) {
  737. alarmHistoryList.value = await getMonitorPointAlarmHistory(gradeTwo.value);
  738. if (alarmHistoryList.value.length) {
  739. // 核心逻辑
  740. for (const bItem of alarmHistoryList.value) {
  741. const triggerStart = parseTimeToMinutes(bItem.triggerTime);
  742. const recoverEnd = parseTimeToMinutes(bItem.recoverTime);
  743. for (const aItem of timeList.value) {
  744. const aStart = parseTimeToMinutes(aItem.time);
  745. const aEnd = aStart + 10;
  746. // 区间重叠判断(左闭右开)
  747. const isOverlap = triggerStart < aEnd && recoverEnd >= aStart;
  748. // 特殊处理:当recoverTime为空时,触发时间后的所有区间
  749. const recoverTimeString = bItem.recoverTime === null ? '' : bItem.recoverTime;
  750. const isInfiniteMode = !recoverTimeString.trim() && aStart >= triggerStart;
  751. if (isOverlap || isInfiniteMode) {
  752. aItem.backgroundShow = true;
  753. }
  754. }
  755. }
  756. } else {
  757. for (const aItem of timeList.value) {
  758. aItem.backgroundShow = false;
  759. }
  760. }
  761. }
  762. });
  763. };
  764. // 返回当前
  765. const returnCurrently = () => {
  766. bs?.refresh();
  767. if (scrollContent.value && scrollWrapper.value) {
  768. const contentWidth = scrollContent.value.scrollWidth;
  769. const wrapperWidth = scrollWrapper.value.clientWidth;
  770. const maxScrollX = contentWidth - wrapperWidth;
  771. if (maxScrollX > 0) {
  772. bs?.scrollTo(-maxScrollX, 0, 800);
  773. }
  774. timeLineIndex.value = timeList.value.length - 1;
  775. chooseTime.value = getCurrentTime();
  776. }
  777. };
  778. // 获取当前日期(格式:HH:mm)
  779. const getCurrentTime = () => {
  780. const now = new Date();
  781. const hours = String(now.getHours()).padStart(2, '0'); // 补零的小时(0~23)
  782. const minutes = String(now.getMinutes()).padStart(2, '0'); // 补零的分钟(0~59)
  783. const seconds = String(now.getSeconds()).padStart(2, '0'); // 补零的秒(0~59)
  784. return `${hours}:${minutes}:${seconds}`;
  785. };
  786. const addTimeLine = (value: TimeList) => {
  787. chooseTime.value = value.time;
  788. timeLineIndex.value = value.index;
  789. };
  790. // 获取当前日期(格式:YYYY-MM-DD)
  791. const getCurrentDate = () => {
  792. const date = new Date();
  793. const year = date.getFullYear();
  794. const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份补零
  795. const day = String(date.getDate()).padStart(2, '0'); // 日期补零
  796. return `${year}-${month}-${day}`;
  797. };
  798. // 注册鼠标滚轮插件
  799. BScroll.use(MouseWheel);
  800. // 初始化 Better-Scroll
  801. const initScroll = async () => {
  802. await nextTick(); // 等待 DOM 更新
  803. if (scrollWrapper.value) {
  804. bs?.destroy(); // 销毁旧实例避免内存泄漏
  805. bs = new BScroll(scrollWrapper.value, {
  806. scrollX: true, // 启用横向滚动
  807. scrollY: false, // 禁用纵向滚动
  808. probeType: 3, // 实时派发滚动事件
  809. mouseWheel: {
  810. speed: 20, // 滚动速度
  811. invert: false, // 是否反转滚动方向
  812. easeTime: 300, // 动画缓动时间
  813. discreteTime: 300, // 离散滚动间隔
  814. },
  815. click: true, // 启用点击事件
  816. disableMouse: false, // 不禁用鼠标控制
  817. });
  818. }
  819. };
  820. onUnmounted(() => {
  821. if (bs) {
  822. bs.destroy(); // 组件卸载时销毁实例
  823. }
  824. });
  825. watch(
  826. () => gradeOne.value,
  827. (count) => {
  828. if (count) {
  829. addAllGatewayList(count);
  830. }
  831. },
  832. );
  833. watch(
  834. () => gradeTwo.value,
  835. (count) => {
  836. if (count) {
  837. getAlarmHistoryList();
  838. getRegionsPointsList(count, false);
  839. obtainRegionsPointsData(count);
  840. getGroupRegionsList();
  841. timeLineIndex.value = timeList.value.length - 1;
  842. chooseTime.value = getCurrentTime();
  843. }
  844. },
  845. );
  846. onMounted(() => {
  847. addAllGatewayList(-1);
  848. getDeviceGroup();
  849. generateTimeArray();
  850. initScroll();
  851. handleRequest(async () => {
  852. temperatureDifference.value = [];
  853. await getParamAlgOperator();
  854. paramAlgOperator.value.forEach((item) => {
  855. if (item.dictValueId === 250 || item.dictValueId === 251) {
  856. temperatureDifference.value.push(item);
  857. }
  858. });
  859. });
  860. });
  861. const areaEditorRef = useTemplateRef('areaEditor');
  862. const areaPreviewRef = useTemplateRef('areaPreview');
  863. const currentAreaData = computed(() => {
  864. return regionList.value.find((item) => item.id === selectId.value);
  865. });
  866. const saveAreaCanvas = (canvas: string) => {
  867. handleRequest(async () => {
  868. if (gradeTwo.value) {
  869. await regionUpdate({
  870. id: selectId.value,
  871. devGroupId: gradeTwo.value,
  872. canvas,
  873. });
  874. const currentAreaData = regionList.value.find((item) => item.id === selectId.value);
  875. if (currentAreaData) {
  876. currentAreaData.canvas = canvas;
  877. }
  878. areaEditorRef.value?.hideView();
  879. }
  880. });
  881. };
  882. const highlightEnvPoint = (id: number) => {
  883. const monitorPointContainerEle = document.querySelector(`.content-monitoring-canvas-left [data-point-id="${id}"]`);
  884. monitorPointContainerEle?.scrollIntoView();
  885. monitoringId.value = id;
  886. };
  887. const copyToRegionId = ref<number>();
  888. const copyToRegionList = computed(() => {
  889. return regionNameList.value.filter((item) => item.id !== selectId.value);
  890. });
  891. const copyAreaCanvas = () => {
  892. if (!copyToRegionId.value) {
  893. message.warning(t('envMonitor.plzSelectRegion'));
  894. return;
  895. }
  896. handleRequest(async () => {
  897. if (gradeTwo.value && currentAreaData.value) {
  898. const data = JSON.parse(currentAreaData.value.canvas || '{}') as Meta2dData;
  899. if (!data.pens?.length) {
  900. message.warning(t('envMonitor.cannotCopyEmptyCanvas'));
  901. return;
  902. }
  903. // 复制画布中除开监测点控件以外的所有图元
  904. data.pens = data.pens.filter((item) => item.name !== 'monitorPoint');
  905. const canvas = JSON.stringify(data);
  906. await regionUpdate({
  907. id: copyToRegionId.value,
  908. devGroupId: gradeTwo.value,
  909. canvas,
  910. });
  911. const copyToAreaData = regionList.value.find((item) => item.id === copyToRegionId.value);
  912. if (copyToAreaData) {
  913. copyToAreaData.canvas = canvas;
  914. }
  915. regionCopyOpen.value = false;
  916. message.success(t('envMonitor.copyRegionSuccessful'));
  917. }
  918. });
  919. };
  920. </script>
  921. <template>
  922. <div>
  923. <ASpin :spinning="isLoading">
  924. <AFlex justify="space-between">
  925. <AFlex align="center">
  926. <div class="text-top">{{ $t('navigation.envMonitor') }}</div>
  927. <div v-show="listDisplay">
  928. <ASelect
  929. class="select-width select-monitoring"
  930. v-model:value="gradeOne"
  931. :options="oneDeviceGroup"
  932. :field-names="{ label: 'groupName', value: 'id' }"
  933. :placeholder="$t('common.plzSelect')"
  934. />
  935. <ASelect
  936. class="select-width"
  937. v-model:value="gradeTwo"
  938. :options="twoDeviceGroup"
  939. :field-names="{ label: 'groupName', value: 'id' }"
  940. :placeholder="$t('common.plzSelect', { name: t('createDevice.groupName') })"
  941. />
  942. </div>
  943. </AFlex>
  944. <div>
  945. <AButton class="icon-button default-button" @click="switchDisplay">
  946. <AFlex align="center">
  947. <SvgIcon name="switch" />
  948. <span>{{ listDisplay ? $t('envMonitor.listDisplay') : $t('envMonitor.cardDisplay') }} </span>
  949. </AFlex>
  950. </AButton>
  951. <AButton type="primary" class="icon-button button-monitoring" @click="addMonitoringPoint">
  952. <AFlex align="center">
  953. <SvgIcon name="plus" />
  954. <span> {{ $t('envMonitor.addInspectionPoints') }} </span>
  955. </AFlex>
  956. </AButton>
  957. </div>
  958. </AFlex>
  959. <div class="content-monitoring" v-show="listDisplay">
  960. <AFlex class="content-monitoring-top" align="flex-end">
  961. <div class="scroll-wrapper" ref="scrollWrapper">
  962. <div class="scroll-content" ref="scrollContent">
  963. <AFlex align="flex-end" class="time-line">
  964. <div>&nbsp;&nbsp;&nbsp;</div>
  965. <div v-for="item in timeList" :key="item.time">
  966. <AFlex align="flex-end" :class="item.backgroundShow ? 'background-alarm' : 'background-default'">
  967. <AFlex :vertical="true">
  968. <div v-if="item.integral" class="time-style">{{ item.time }}</div>
  969. <div @click="addTimeLine(item)">
  970. <AFlex align="flex-end" class="integral-style">
  971. <AFlex
  972. :vertical="true"
  973. justify="center"
  974. align="center"
  975. v-if="item.index === timeLineIndex"
  976. class="confirm-axis-div"
  977. >
  978. <div class="confirm-axis-circle"></div>
  979. <div class="confirm-axis"></div>
  980. </AFlex>
  981. <div v-else :class="item.integral ? 'integral' : 'integral-height'"></div>
  982. </AFlex>
  983. </div>
  984. </AFlex>
  985. </AFlex>
  986. </div>
  987. </AFlex>
  988. </div>
  989. </div>
  990. <AFlex>
  991. <AButton type="text" class="return-currently" @click="returnCurrently">{{
  992. $t('envMonitor.returnCurrent')
  993. }}</AButton>
  994. <AButton type="primary" class="timeline-confirm" @click="confirmTimeLine">{{
  995. $t('common.confirm')
  996. }}</AButton>
  997. </AFlex>
  998. </AFlex>
  999. <AFlex class="content-monitoring-canvas">
  1000. <div class="content-monitoring-canvas-left">
  1001. <div v-for="item in monitoringPointData" :key="item.id" :data-point-id="item.id">
  1002. <LineChart
  1003. :data="item"
  1004. :icon-show="true"
  1005. :monitoring-id="monitoringId"
  1006. @click="areaPreviewRef?.highlightCanvasPoint(item.id)"
  1007. @editorClick="editorClick"
  1008. @historicalDataClick="historicalDataClick"
  1009. />
  1010. </div>
  1011. </div>
  1012. <AFlex class="monitoring-img">
  1013. <AFlex v-show="regionList.length" align="center" class="list-regions">
  1014. <ButtonTabs
  1015. :data="regionNameList"
  1016. :select-id="selectId"
  1017. :width="'75px'"
  1018. :radius="'16px'"
  1019. :tooltip="true"
  1020. @selectClick="selectClick"
  1021. />
  1022. </AFlex>
  1023. <div v-show="regionList.length" class="canvas-div">
  1024. <AFlex justify="space-between" class="canvas-div-top">
  1025. <AButton class="icon-button">
  1026. <SvgIcon name="outdoor" />
  1027. {{ currentAreaData?.outSideTemperature || '-' }}℃|{{ currentAreaData?.outSideHumidity || '-' }}%
  1028. </AButton>
  1029. <AFlex>
  1030. <div @click="areaEditorRef?.showView">
  1031. <AFlex justify="center" align="center" class="button-icon">
  1032. <SvgIcon name="edit-o" />
  1033. </AFlex>
  1034. </div>
  1035. <div @click="copyRegion">
  1036. <AFlex justify="center" align="center" class="button-icon">
  1037. <SvgIcon name="copy" />
  1038. </AFlex>
  1039. </div>
  1040. </AFlex>
  1041. </AFlex>
  1042. <div class="canvas-content">
  1043. <AButton class="icon-button icon-button-margin home-temp-humidity-button">
  1044. <SvgIcon name="home" />
  1045. {{ currentAreaData?.avgTemperature || '-' }}℃|{{ currentAreaData?.avgHumidity || '-' }}%
  1046. </AButton>
  1047. <AreaPreview
  1048. v-if="regionList.length"
  1049. ref="areaPreview"
  1050. :area-data="currentAreaData"
  1051. @highlight-env-point="highlightEnvPoint"
  1052. />
  1053. </div>
  1054. </div>
  1055. </AFlex>
  1056. </AFlex>
  1057. </div>
  1058. <EnvMonitorList
  1059. ref="envMonitorList"
  1060. v-show="!listDisplay"
  1061. :monitor-data="monitoringList"
  1062. :monitoring-point-data="monitoringPointData"
  1063. />
  1064. <ADrawer
  1065. width="600"
  1066. :open="monitoringPointOpen"
  1067. :closable="false"
  1068. class="drawer-monitoring"
  1069. :header-style="headerStyle"
  1070. :footer-style="footerStyle"
  1071. >
  1072. <template #title
  1073. >{{ titleMonitoring ? $t('envMonitor.addInspectionPoints') : $t('envMonitor.editorialMonitoringPoint') }}
  1074. </template>
  1075. <template #extra>
  1076. <SvgIcon class="off-icon" @click="offDrawer" name="close" />
  1077. </template>
  1078. <AForm ref="formRef" class="form-ref" :model="monitoringForm" layout="vertical" :rules="rules">
  1079. <AFormItem name="name">
  1080. <AInput
  1081. v-model:value="monitoringForm.name"
  1082. class="input-wdith region-bottom"
  1083. :placeholder="$t('common.pleaseEnter')"
  1084. />
  1085. </AFormItem>
  1086. <AFormItem :label="$t('envMonitor.region')" name="regionId">
  1087. <AFlex align="center">
  1088. <ASelect
  1089. class="input-wdith"
  1090. v-model:value="monitoringForm.regionId"
  1091. :options="groupRegions"
  1092. :field-names="{ label: 'regionName', value: 'id' }"
  1093. :placeholder="$t('common.plzSelect')"
  1094. @change="addRegionList"
  1095. />
  1096. <div @click="editingRegionName">
  1097. <AFlex justify="center" align="center" class="button-flex">
  1098. <SvgIcon name="edit-o" />
  1099. </AFlex>
  1100. </div>
  1101. <div @click="addRegionName">
  1102. <AFlex justify="center" align="center" class="button-flex button-plus">
  1103. <SvgIcon name="plus" />
  1104. </AFlex>
  1105. </div>
  1106. </AFlex>
  1107. </AFormItem>
  1108. <AFormItem :label="t('envMonitor.humidityTemperatureControl')" name="tempHumidityControlMode">
  1109. <ARadioGroup v-model:value="monitoringForm.tempHumidityControlMode" class="radio-group">
  1110. <ARadio value="2">{{ $t('envMonitor.returnControl') }}</ARadio>
  1111. <!-- <ARadio value="1">{{ $t('envMonitor.supplyControl') }}</ARadio> -->
  1112. </ARadioGroup>
  1113. </AFormItem>
  1114. <AFlex justify="space-between">
  1115. <div>
  1116. <AFormItem
  1117. class="form-item"
  1118. :label="$t('envMonitor.returnTemperatureAndhumidity')"
  1119. name="returnDevGroupId"
  1120. >
  1121. <ASelect
  1122. class="input-wdith"
  1123. v-model:value="monitoringForm.returnDevGroupId"
  1124. :options="twoDeviceGroup"
  1125. :field-names="{ label: 'groupName', value: 'id' }"
  1126. :placeholder="$t('common.plzSelect', { name: t('createDevice.groupName') })"
  1127. @change="(value, option) => adddDeviceGroup(value, option, HumitureType.ReturnAir)"
  1128. />
  1129. </AFormItem>
  1130. <AFormItem name="returnDevId">
  1131. <ASelect
  1132. class="input-wdith"
  1133. v-model:value="monitoringForm.returnDevId"
  1134. :options="returnDevicesList"
  1135. :field-names="{ label: 'deviceName', value: 'id' }"
  1136. :placeholder="$t('common.plzSelect', { name: t('deviceList.equipmentName') })"
  1137. @change="(value, option) => adddDevice(value, option, HumitureType.ReturnAir)"
  1138. />
  1139. </AFormItem>
  1140. <AFormItem name="returnTempParamCode">
  1141. <ASelect
  1142. class="input-wdith"
  1143. v-model:value="monitoringForm.returnTempParamCode"
  1144. :options="returnDeviceParamsList"
  1145. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1146. :placeholder="
  1147. $t('common.plzSelect', { name: t('envMonitor.temperature') + t('createDevice.parameters') })
  1148. "
  1149. />
  1150. </AFormItem>
  1151. <AFormItem name="returnHumidityParamCode">
  1152. <ASelect
  1153. class="input-wdith"
  1154. v-model:value="monitoringForm.returnHumidityParamCode"
  1155. :options="returnDeviceParamsList"
  1156. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1157. :placeholder="
  1158. $t('common.plzSelect', { name: t('envMonitor.humidity') + t('createDevice.parameters') })
  1159. "
  1160. />
  1161. </AFormItem>
  1162. </div>
  1163. <div>
  1164. <AFormItem :label="$t('envMonitor.supplyTemperatureAndhumidity')" name="supplyDevGroupId">
  1165. <ASelect
  1166. class="input-wdith"
  1167. v-model:value="monitoringForm.supplyDevGroupId"
  1168. :options="twoDeviceGroup"
  1169. :field-names="{ label: 'groupName', value: 'id' }"
  1170. :placeholder="$t('common.plzSelect', { name: t('createDevice.groupName') })"
  1171. @change="(value, option) => adddDeviceGroup(value, option, HumitureType.SupplyAir)"
  1172. />
  1173. </AFormItem>
  1174. <AFormItem name="supplyDevId">
  1175. <ASelect
  1176. class="input-wdith"
  1177. v-model:value="monitoringForm.supplyDevId"
  1178. :options="supplyDevicesList"
  1179. :field-names="{ label: 'deviceName', value: 'id' }"
  1180. :placeholder="$t('common.plzSelect', { name: t('deviceList.equipmentName') })"
  1181. @change="(value, option) => adddDevice(value, option, HumitureType.SupplyAir)"
  1182. />
  1183. </AFormItem>
  1184. <AFormItem name="supplyTempParamCode">
  1185. <ASelect
  1186. class="input-wdith"
  1187. v-model:value="monitoringForm.supplyTempParamCode"
  1188. :options="supplyDeviceParamsList"
  1189. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1190. :placeholder="
  1191. $t('common.plzSelect', { name: t('envMonitor.temperature') + t('createDevice.parameters') })
  1192. "
  1193. />
  1194. </AFormItem>
  1195. <AFormItem name="supplyHumidityParamCode">
  1196. <ASelect
  1197. class="input-wdith"
  1198. v-model:value="monitoringForm.supplyHumidityParamCode"
  1199. :options="supplyDeviceParamsList"
  1200. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1201. :placeholder="
  1202. $t('common.plzSelect', { name: t('envMonitor.humidity') + t('createDevice.parameters') })
  1203. "
  1204. />
  1205. </AFormItem>
  1206. </div>
  1207. </AFlex>
  1208. <div v-if="monitoringForm.tempHumidityControlMode === '1'">
  1209. <AFormItem
  1210. class="form-item"
  1211. :label="t('envMonitor.newAirTemperatureAndHumidityMeter')"
  1212. name="outdoorDevGroupId"
  1213. >
  1214. <ASelect
  1215. class="input-wdith"
  1216. v-model:value="monitoringForm.outdoorDevGroupId"
  1217. :options="twoDeviceGroup"
  1218. :field-names="{ label: 'groupName', value: 'id' }"
  1219. :placeholder="$t('common.plzSelect', { name: t('createDevice.groupName') })"
  1220. @change="(value, option) => adddDeviceGroup(value, option, HumitureType.FreshAir)"
  1221. />
  1222. </AFormItem>
  1223. <AFormItem name="outdoorDevId">
  1224. <ASelect
  1225. class="input-wdith"
  1226. v-model:value="monitoringForm.outdoorDevId"
  1227. :options="freshDevicesList"
  1228. :field-names="{ label: 'deviceName', value: 'id' }"
  1229. :placeholder="$t('common.plzSelect', { name: t('deviceList.equipmentName') })"
  1230. @change="(value, option) => adddDevice(value, option, HumitureType.FreshAir)"
  1231. />
  1232. </AFormItem>
  1233. <AFormItem name="outdoorTempParamCode">
  1234. <ASelect
  1235. class="input-wdith"
  1236. v-model:value="monitoringForm.outdoorTempParamCode"
  1237. :options="freshDeviceParamsList"
  1238. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1239. :placeholder="
  1240. $t('common.plzSelect', { name: t('envMonitor.temperature') + t('createDevice.parameters') })
  1241. "
  1242. />
  1243. </AFormItem>
  1244. <AFormItem name="outdoorHumidityParamCode">
  1245. <ASelect
  1246. class="input-wdith"
  1247. v-model:value="monitoringForm.outdoorHumidityParamCode"
  1248. :options="freshDeviceParamsList"
  1249. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1250. :placeholder="$t('common.plzSelect', { name: t('envMonitor.humidity') + t('createDevice.parameters') })"
  1251. />
  1252. </AFormItem>
  1253. </div>
  1254. <AFlex>
  1255. <div class="spacing-right">
  1256. <AFormItem
  1257. :label="
  1258. monitoringForm.tempHumidityControlMode === '1'
  1259. ? $t('envMonitor.fanTemperatureSetting')
  1260. : $t('envMonitor.indoorTemperatureConfiguration')
  1261. "
  1262. >
  1263. <AFlex align="center">
  1264. <AInputNumber
  1265. class="input-number-width"
  1266. :placeholder="$t('common.pleaseEnter')"
  1267. v-model:value="monitoringForm.tempUpper"
  1268. :min="0"
  1269. :max="999"
  1270. />
  1271. <div class="configure-text">{{ $t('envMonitor.upperLimitValue') }}</div>
  1272. </AFlex>
  1273. </AFormItem>
  1274. <AFormItem>
  1275. <AFlex align="center">
  1276. <AInputNumber
  1277. class="input-number-width"
  1278. :placeholder="$t('common.pleaseEnter')"
  1279. v-model:value="monitoringForm.tempLower"
  1280. :min="0"
  1281. :max="999"
  1282. />
  1283. <div class="configure-text">{{ $t('envMonitor.lowerLimitValue') }}</div>
  1284. </AFlex>
  1285. </AFormItem>
  1286. <AFormItem>
  1287. <AFlex align="center">
  1288. <AInputNumber
  1289. class="input-number-width"
  1290. v-model:value="monitoringForm.tempPreset"
  1291. :min="0"
  1292. :max="999"
  1293. :placeholder="$t('common.pleaseEnter')"
  1294. />
  1295. <div class="configure-text">{{ $t('envMonitor.limitValue') }}</div>
  1296. </AFlex>
  1297. </AFormItem>
  1298. </div>
  1299. <div>
  1300. <AFormItem
  1301. :label="
  1302. monitoringForm.tempHumidityControlMode === '1'
  1303. ? t('envMonitor.fanAirHumiditySetting')
  1304. : $t('envMonitor.indoorHumiditySetting')
  1305. "
  1306. >
  1307. <AFlex align="center">
  1308. <AInputNumber
  1309. class="input-number-width"
  1310. v-model:value="monitoringForm.humidityUpper"
  1311. :min="0"
  1312. :max="999"
  1313. :placeholder="$t('common.pleaseEnter')"
  1314. />
  1315. <div class="configure-text">{{ $t('envMonitor.upperLimitValue') }}</div>
  1316. </AFlex>
  1317. </AFormItem>
  1318. <AFormItem>
  1319. <AFlex align="center">
  1320. <AInputNumber
  1321. class="input-number-width"
  1322. v-model:value="monitoringForm.humidityLower"
  1323. :min="0"
  1324. :max="999"
  1325. :placeholder="$t('common.pleaseEnter')"
  1326. />
  1327. <div class="configure-text">{{ $t('envMonitor.lowerLimitValue') }}</div>
  1328. </AFlex>
  1329. </AFormItem>
  1330. <AFormItem>
  1331. <AFlex align="center">
  1332. <AInputNumber
  1333. class="input-number-width"
  1334. v-model:value="monitoringForm.humidityPreset"
  1335. :min="0"
  1336. :max="999"
  1337. :placeholder="$t('common.pleaseEnter')"
  1338. />
  1339. <div class="configure-text">{{ $t('envMonitor.limitValue') }}</div>
  1340. </AFlex>
  1341. </AFormItem>
  1342. </div>
  1343. </AFlex>
  1344. <AFormItem :label="t('envMonitor.monitoringPointStatusConfiguration')" name="runStatusFlag">
  1345. <ARadioGroup v-model:value="monitoringForm.runStatusFlag" class="radio-group">
  1346. <ARadio :value="0">{{ t('envMonitor.temperatureDifferenceJudgment') }}</ARadio>
  1347. <ARadio :value="1">{{ t('envMonitor.operationStatusDetermination') }}</ARadio>
  1348. </ARadioGroup>
  1349. </AFormItem>
  1350. <AFlex v-if="monitoringForm.runStatusFlag === 0">
  1351. <AFormItem name="supplyReturnTempDiff">
  1352. <AFlex align="center" class="spacing">
  1353. <AInputNumber
  1354. class="input-number-width"
  1355. v-model:value="monitoringForm.supplyReturnTempDiff"
  1356. :min="0"
  1357. :max="999"
  1358. :placeholder="$t('common.pleaseEnter')"
  1359. />
  1360. <div class="configure-text">{{ t('envMonitor.returnAirTemperatureDifference') }}</div>
  1361. </AFlex>
  1362. </AFormItem>
  1363. <AFormItem name="supplyUpperTempDiff">
  1364. <AFlex align="center">
  1365. <AInputNumber
  1366. class="input-number-width"
  1367. v-model:value="monitoringForm.supplyUpperTempDiff"
  1368. :min="0"
  1369. :max="999"
  1370. :placeholder="$t('common.pleaseEnter')"
  1371. />
  1372. <div class="configure-text">{{ t('envMonitor.upperLimitAirSupplyTemperatureDifference') }}</div>
  1373. </AFlex>
  1374. </AFormItem>
  1375. </AFlex>
  1376. <AFlex justify="space-between" wrap="wrap" v-else>
  1377. <AFormItem name="runStatusDevGroupId">
  1378. <ASelect
  1379. class="input-wdith"
  1380. v-model:value="monitoringForm.runStatusDevGroupId"
  1381. :options="twoDeviceGroup"
  1382. :field-names="{ label: 'groupName', value: 'id' }"
  1383. :placeholder="$t('common.plzSelect', { name: t('createDevice.groupName') })"
  1384. @change="(value, option) => adddDeviceGroup(value, option, HumitureType.OperatingStatus)"
  1385. />
  1386. </AFormItem>
  1387. <AFormItem name="runStatusDevId">
  1388. <ASelect
  1389. class="input-wdith"
  1390. v-model:value="monitoringForm.runStatusDevId"
  1391. :options="runDevicesList"
  1392. :field-names="{ label: 'deviceName', value: 'id' }"
  1393. :placeholder="$t('common.plzSelect', { name: t('deviceList.equipmentName') })"
  1394. @change="(value, option) => adddRunStatusDevice(value, option)"
  1395. />
  1396. </AFormItem>
  1397. <AFormItem name="runStatusParamCode">
  1398. <ASelect
  1399. class="input-wdith"
  1400. v-model:value="monitoringForm.runStatusParamCode"
  1401. :options="runDeviceParamsList"
  1402. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1403. :placeholder="$t('common.plzSelect', { name: t('alarmManage.equipmentParameters') })"
  1404. @change="(value, option) => adddParametersDevice(value, option)"
  1405. />
  1406. </AFormItem>
  1407. <AFormItem name="runStatusConditionCode">
  1408. <ASelect
  1409. class="input-wdith"
  1410. v-model:value="monitoringForm.runStatusConditionCode"
  1411. :options="inputType === 1 ? temperatureDifference : paramAlgOperator"
  1412. :placeholder="$t('common.plzSelect', { name: t('alarmManage.operator') })"
  1413. :field-names="{ label: 'dictValue', value: 'dictValue' }"
  1414. />
  1415. </AFormItem>
  1416. <AFormItem v-if="inputType === 1" name="runStatusConditionValue">
  1417. <ASelect
  1418. class="input-wdith"
  1419. v-model:value="monitoringForm.runStatusConditionValue"
  1420. :options="runStatusList"
  1421. :placeholder="$t('common.plzSelect')"
  1422. :field-names="{ label: 'name', value: 'name' }"
  1423. />
  1424. </AFormItem>
  1425. <AFormItem v-else name="runStatusConditionValue">
  1426. <AInputNumber
  1427. class="input-wdith"
  1428. v-model:value="monitoringForm.runStatusConditionValue"
  1429. :min="0"
  1430. :max="999"
  1431. :placeholder="$t('common.pleaseEnter')"
  1432. />
  1433. </AFormItem>
  1434. </AFlex>
  1435. </AForm>
  1436. <template #footer>
  1437. <AFlex justify="flex-end" :gap="16">
  1438. <AButton class="default-button" @click="deleteMonitoringPoint">{{ $t('common.delete') }}</AButton>
  1439. <AButton type="primary" @click="saveMonitoringPoint">{{ $t('common.save') }}</AButton>
  1440. </AFlex>
  1441. </template>
  1442. </ADrawer>
  1443. <ADrawer
  1444. class="drawer-monitoring"
  1445. width="304"
  1446. :open="outdoorOpen"
  1447. :closable="false"
  1448. :header-style="headerStyle"
  1449. :footer-style="footerStyle"
  1450. >
  1451. <template #title>{{ $t('envMonitor.outdoorTemperatureAndHumidity') }}</template>
  1452. <template #extra>
  1453. <SvgIcon class="off-icon" @click="offOutdoorDrawer" name="close" />
  1454. </template>
  1455. <AForm ref="formOutdoorRef" :model="outdooForm" layout="vertical">
  1456. <AFormItem :label="$t('envMonitor.outdoorTemperatureAndHumidityMeter')" name="outsideDevGroupId">
  1457. <ASelect
  1458. class="input-wdith"
  1459. v-model:value="outdooForm.outsideDevGroupId"
  1460. :options="twoDeviceGroup"
  1461. :field-names="{ label: 'groupName', value: 'id' }"
  1462. :placeholder="$t('common.plzSelect', { name: t('createDevice.groupName') })"
  1463. @change="(value, option) => adddDeviceGroup(value, option, HumitureType.Outdoor)"
  1464. />
  1465. </AFormItem>
  1466. <AFormItem name="outsideDevId">
  1467. <ASelect
  1468. class="input-wdith"
  1469. v-model:value="outdooForm.outsideDevId"
  1470. :options="outdoorDevicesList"
  1471. :field-names="{ label: 'deviceName', value: 'id' }"
  1472. :placeholder="$t('common.plzSelect', { name: t('deviceList.equipmentName') })"
  1473. @change="(value, option) => adddDevice(value, option, HumitureType.Outdoor)"
  1474. />
  1475. </AFormItem>
  1476. <AFormItem name="outsideTempParamCode">
  1477. <ASelect
  1478. class="input-wdith"
  1479. v-model:value="outdooForm.outsideTempParamCode"
  1480. :options="outdoorDeviceParamsList"
  1481. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1482. :placeholder="
  1483. $t('common.plzSelect', { name: t('envMonitor.temperature') + t('createDevice.parameters') })
  1484. "
  1485. />
  1486. </AFormItem>
  1487. <AFormItem name="outsideHumidityParamCode">
  1488. <ASelect
  1489. class="input-wdith"
  1490. v-model:value="outdooForm.outsideHumidityParamCode"
  1491. :options="outdoorDeviceParamsList"
  1492. :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
  1493. :placeholder="$t('common.plzSelect', { name: t('envMonitor.humidity') + t('createDevice.parameters') })"
  1494. />
  1495. </AFormItem>
  1496. <AFormItem name="outsideEnthalpyParamCode">
  1497. <ASelect
  1498. class="input-wdith"
  1499. v-model:value="outdooForm.outsideEnthalpyParamCode"
  1500. :placeholder="$t('common.plzSelect', { name: t('envMonitor.hanValue') })"
  1501. >
  1502. <ASelectOption value="温度">{{ t('envMonitor.temperature') }}</ASelectOption>
  1503. <ASelectOption value="湿度">{{ t('envMonitor.humidity') }}</ASelectOption>
  1504. </ASelect>
  1505. </AFormItem>
  1506. </AForm>
  1507. <template #footer>
  1508. <AFlex justify="flex-end" :gap="16">
  1509. <AButton type="primary" @click="saveOutdoo">{{ $t('common.save') }}</AButton>
  1510. </AFlex>
  1511. </template>
  1512. </ADrawer>
  1513. <ADrawer
  1514. width="612"
  1515. :open="monitoringDataOpen"
  1516. :closable="false"
  1517. class="drawer-monitoring"
  1518. :header-style="headerStyle"
  1519. :footer-style="footerStyle"
  1520. >
  1521. <template #title>{{ monitoringName }}</template>
  1522. <template #extra>
  1523. <SvgIcon class="off-icon" @click="offMonitoringDrawer" name="close" />
  1524. </template>
  1525. <HumitureCurve
  1526. :monitoring-id="monitoringId"
  1527. :monitoring-data="monitoringPointData"
  1528. :set-show="true"
  1529. :width="'580px'"
  1530. :height="'700px'"
  1531. />
  1532. </ADrawer>
  1533. <AModal
  1534. v-model:open="regionNameOpen"
  1535. :title="titleRegions ? $t('envMonitor.addArea') : $t('envMonitor.editArea')"
  1536. :footer="null"
  1537. width="460px"
  1538. :mask-closable="false"
  1539. :keyboard="false"
  1540. >
  1541. <div class="region-name">{{ $t('envMonitor.regionName') }}</div>
  1542. <AInput v-model:value="regionName" :placeholder="$t('common.pleaseEnter')" />
  1543. <AFlex justify="flex-end" class="region-name-top">
  1544. <AButton v-if="!titleRegions" class="default-button" @click="regionNameDelete">{{
  1545. $t('common.delete')
  1546. }}</AButton>
  1547. <AButton class="default-button cancel-button" @click="regionNameOpen = false">{{
  1548. $t('common.cancel')
  1549. }}</AButton>
  1550. <AButton type="primary" @click="regionNameOk">{{ $t('common.confirm') }}</AButton>
  1551. </AFlex>
  1552. </AModal>
  1553. <AModal
  1554. v-model:open="regionCopyOpen"
  1555. :title="$t('envMonitor.copyPanel')"
  1556. :footer="null"
  1557. width="460px"
  1558. :mask-closable="false"
  1559. :keyboard="false"
  1560. >
  1561. <div class="region-name">{{ $t('envMonitor.selectCopyArea') }}</div>
  1562. <ASelect
  1563. v-model:value="copyToRegionId"
  1564. style="width: 100%"
  1565. :options="copyToRegionList"
  1566. :field-names="{ label: 'name', value: 'id' }"
  1567. :placeholder="$t('common.plzSelect')"
  1568. />
  1569. <AFlex justify="flex-end" class="region-name-top">
  1570. <AButton class="default-button cancel-button" @click="regionCopyOpen = false">{{
  1571. $t('common.cancel')
  1572. }}</AButton>
  1573. <AButton type="primary" @click="copyAreaCanvas">{{ $t('common.confirm') }}</AButton>
  1574. </AFlex>
  1575. </AModal>
  1576. <AreaEditor
  1577. ref="areaEditor"
  1578. :area-data="currentAreaData"
  1579. @open-outdoor-drawer="addOutdoorDrawer"
  1580. @save-area-canvas="saveAreaCanvas"
  1581. />
  1582. </ASpin>
  1583. </div>
  1584. </template>
  1585. <style lang="scss" scoped>
  1586. .spacing {
  1587. margin-right: 74px;
  1588. }
  1589. .spacing-right {
  1590. margin-right: 102px;
  1591. }
  1592. .background-default {
  1593. height: 40px;
  1594. background-color: #fff;
  1595. }
  1596. .background-alarm {
  1597. height: 40px;
  1598. background-color: rgb(245 108 108 / 15%);
  1599. }
  1600. .confirm-axis-div {
  1601. margin-left: -3px;
  1602. }
  1603. .confirm-axis-circle {
  1604. width: 10px;
  1605. height: 10px;
  1606. background: #32bac0;
  1607. border-radius: 50%;
  1608. }
  1609. .return-currently {
  1610. margin-left: 10px;
  1611. color: #32bac0;
  1612. }
  1613. .timeline-confirm {
  1614. width: 76px;
  1615. height: 32px;
  1616. margin-right: 24px;
  1617. margin-left: 10px;
  1618. border-radius: 16px;
  1619. }
  1620. .scroll-wrapper {
  1621. position: relative;
  1622. width: 100%;
  1623. overflow: hidden;
  1624. }
  1625. .scroll-content {
  1626. display: inline-block; /* 关键:横向布局 */
  1627. white-space: nowrap; /* 禁止内容换行 */
  1628. }
  1629. .time-style {
  1630. margin-left: -10px;
  1631. font-size: 10px;
  1632. font-style: normal;
  1633. font-weight: 400;
  1634. color: rgb(0 0 0 / 50%);
  1635. text-align: left;
  1636. }
  1637. .time-line {
  1638. height: 39px;
  1639. border-bottom: 1px solid #979797;
  1640. }
  1641. .confirm-axis {
  1642. width: 1px;
  1643. height: 20px;
  1644. border: 1px solid #32bac0;
  1645. }
  1646. .integral-style {
  1647. width: 31px;
  1648. height: 20px;
  1649. cursor: pointer;
  1650. }
  1651. .integral-height {
  1652. width: 1px;
  1653. height: 5px;
  1654. border: 1px solid #979797;
  1655. }
  1656. .integral {
  1657. width: 1px;
  1658. height: 10px;
  1659. border: 1px solid #979797;
  1660. }
  1661. .icon-button-margin {
  1662. margin: 16px 0 0 16px;
  1663. }
  1664. .canvas-div-top {
  1665. margin-bottom: 16px;
  1666. margin-left: 16px;
  1667. }
  1668. .canvas-div {
  1669. width: 820px;
  1670. }
  1671. .button-icon {
  1672. width: 32px;
  1673. height: 32px;
  1674. margin-left: 12px;
  1675. font-size: 16px;
  1676. color: var(--antd-color-primary);
  1677. cursor: pointer;
  1678. background: #fff;
  1679. border: 1px solid #32bac0;
  1680. border-radius: 4px;
  1681. }
  1682. .canvas-content {
  1683. position: relative;
  1684. width: 820px;
  1685. height: 660px;
  1686. background: #f5f7fa;
  1687. border-radius: 12px;
  1688. outline: 1px solid var(--antd-color-primary);
  1689. }
  1690. .home-temp-humidity-button {
  1691. position: absolute;
  1692. }
  1693. .list-regions {
  1694. height: 100%;
  1695. margin-right: 16px;
  1696. }
  1697. .content-monitoring-canvas-left {
  1698. width: 260px;
  1699. padding-right: 30px;
  1700. padding-bottom: 24px;
  1701. overflow: hidden;
  1702. overflow: hidden auto; /* 隐藏水平滚动条 */ /* 只显示垂直滚动条 */
  1703. }
  1704. .monitoring-img {
  1705. width: 100%;
  1706. height: 100%;
  1707. background-image: radial-gradient(circle, #d8d8d8 1px, #fff 1px);
  1708. background-position: center center;
  1709. background-size: 15px 15px;
  1710. }
  1711. .content-monitoring-canvas {
  1712. height: calc(100% - 45px);
  1713. padding-top: 24px;
  1714. }
  1715. .content-monitoring-top {
  1716. height: 40px;
  1717. }
  1718. .drawer-monitoring .form-ref .ant-form-item .ant-form-item-label > label {
  1719. color: #666;
  1720. }
  1721. .configure-text {
  1722. margin-left: 12px;
  1723. font-size: 14px;
  1724. font-style: normal;
  1725. font-weight: 400;
  1726. line-height: 22px;
  1727. color: #666;
  1728. text-align: left;
  1729. }
  1730. .radio-group {
  1731. margin: 8px 0 10px;
  1732. }
  1733. .region-bottom {
  1734. margin-bottom: 8px;
  1735. }
  1736. .drawer-monitoring .ant-form-item {
  1737. margin-bottom: 16px;
  1738. }
  1739. .input-number-width {
  1740. width: 140px;
  1741. // margin-bottom: 16px;
  1742. }
  1743. .segmented-monitoring {
  1744. width: 196px;
  1745. margin-bottom: 24px;
  1746. }
  1747. .off-icon {
  1748. cursor: pointer;
  1749. }
  1750. .cancel-button {
  1751. margin: 0 16px;
  1752. }
  1753. .region-name-top {
  1754. margin-top: 40px;
  1755. }
  1756. .region-name {
  1757. margin-top: 16px;
  1758. margin-bottom: 5px;
  1759. color: #666;
  1760. }
  1761. .button-plus {
  1762. margin-left: 12px !important;
  1763. font-size: 16px;
  1764. }
  1765. .button-flex {
  1766. width: 32px;
  1767. height: 32px;
  1768. margin-left: 16px;
  1769. cursor: pointer;
  1770. background: #fff;
  1771. border: 1px solid #d9d9d9;
  1772. border-radius: 4px;
  1773. }
  1774. .input-wdith {
  1775. width: 256px;
  1776. }
  1777. .button-monitoring {
  1778. margin-left: 16px;
  1779. }
  1780. .content-monitoring {
  1781. height: calc(100vh - 85px);
  1782. // min-height: 100%;
  1783. padding: 24px 0 0 24px; // 上、右、下、左
  1784. margin-top: 16px;
  1785. // overflow: hidden;
  1786. background-color: #fff;
  1787. border-radius: 16px;
  1788. }
  1789. .select-monitoring {
  1790. margin-right: 16px;
  1791. margin-left: 32px;
  1792. }
  1793. .select-width {
  1794. width: 192px;
  1795. }
  1796. .text-top {
  1797. font-size: 20px;
  1798. font-style: normal;
  1799. font-weight: 500;
  1800. line-height: 32px;
  1801. color: rgb(0 0 0 / 85%);
  1802. text-align: left;
  1803. }
  1804. </style>