index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import React, { useState, useEffect } from 'react';
  2. import { FormattedMessage, useModel, useRequest } from 'umi';
  3. import PageHeader from '@/sgcomponents/PageHeader';
  4. import Map from '@/sgcomponents/map';
  5. import SearchInput from '@/sgcomponents/SearchInput';
  6. import TopNavigator from '@/sgcomponents/topNavigator';
  7. import ChartModal from './components/chartModal';
  8. import moment from 'moment';
  9. import { getMapList, queryEnvironmentParam } from '@/services/sgservice/environment';
  10. import { projectId } from '@/config/api.js';
  11. import { equipImageMap } from '@/config/image.js';
  12. import { Spin } from 'antd';
  13. import Icon from '@/tenants-ui/SgIcon';
  14. import cx from 'classnames';
  15. import styles from './index.less';
  16. import mapstyles from '@/assets/css/map.less';
  17. export type navigatorItem = {
  18. name: string;
  19. id: string;
  20. src: any;
  21. unit?: string;
  22. num?: number;
  23. color: string;
  24. colorStr: string;
  25. opacity?: number;
  26. indicator?: number[];
  27. [key: string]: any;
  28. };
  29. const Environment: React.FC = () => {
  30. const { searchSpace } = useModel('searchInfo');
  31. const { envir_temperature, envir_wet, envir_co2, envir_pm25, envir_jiaquan } = equipImageMap;
  32. const [showChart, setShowChart] = useState(false);
  33. const [selFloorId, setSelFloorId] = useState<string>();
  34. const [selBuildId, setSelBuildId] = useState<string>();
  35. const [showSpace, setShowSpace] = useState<API.MapInfo>({}); //当前弹框选中的空间
  36. const [navigatorList] = useState<navigatorItem[]>([
  37. {
  38. name: '温度',
  39. id: 'Tdb',
  40. src: envir_temperature,
  41. unit: '℃',
  42. color: '#E5574F',
  43. colorStr: '229,87,79,',
  44. opacity: 0.2, //透明度基数
  45. indicator: [18, 21, 24, 27, 30],
  46. fixed: 1,
  47. },
  48. {
  49. name: '湿度',
  50. id: 'RH',
  51. src: envir_wet,
  52. unit: '%',
  53. color: '#9FB7CD',
  54. colorStr: '159,183,205,',
  55. opacity: 0.2,
  56. indicator: [25, 35, 45, 55, 65],
  57. fixed: 1,
  58. },
  59. {
  60. name: 'CO₂',
  61. id: 'CO2',
  62. src: envir_co2,
  63. unit: 'ppm',
  64. color: '#00DC23',
  65. colorStr: '0,220,35,',
  66. opacity: 0.2,
  67. indicator: [500, 700, 1000, 2000, 3000],
  68. fixed: 0,
  69. },
  70. {
  71. name: 'PM2.5',
  72. id: 'PM2d5',
  73. src: envir_pm25,
  74. unit: 'ug/m³',
  75. color: '#E89E32',
  76. colorStr: '232,158,50,',
  77. opacity: 0.2,
  78. indicator: [15, 25, 35, 75, 90],
  79. fixed: 1,
  80. },
  81. {
  82. name: '甲醛',
  83. id: 'HCHO',
  84. src: envir_jiaquan,
  85. unit: 'mg/m³',
  86. color: '#140050',
  87. colorStr: '20,0,80,',
  88. opacity: 0.25,
  89. indicator: [0.02, 0.05, 0.1, 0.15], //指标梯度
  90. fixed: 2,
  91. },
  92. ]);
  93. const [loading, setLoading] = useState<boolean>(false);
  94. const [selNav, setSelNav] = useState<navigatorItem>(navigatorList[0]);
  95. const [selNavId, setSelNavId] = useState<string>(navigatorList[0].id);
  96. const [mapList, setMapList] = useState<API.MapInfo[]>([]);
  97. const [mapSize, setMapSize] = useState<any>({});
  98. const [envirMapList, setEnvirMapList] = useState<API.MapInfo[]>([]);
  99. const [mapCombineList, setMapCombineList] = useState<any[]>([]);
  100. const { getSpaceFunc } = useModel('spaceFunc');
  101. const changeFloorId = (data: string) => {
  102. setSelFloorId(data);
  103. };
  104. const changeBuildId = (data: string) => {
  105. setSelBuildId(data);
  106. };
  107. //导航切换时
  108. const navigatorChange = (item: navigatorItem) => {
  109. setSelNav(item);
  110. setSelNavId(item.id);
  111. };
  112. //根据指标的值 得到不同的透明度等级 第一级0.2 第二级0.4 依次往后
  113. const getColorOpacity = (value: number): number => {
  114. var indicator: number[] = selNav.indicator || []; //指标梯度
  115. var number = indicator.length;
  116. var res = 1;
  117. for (var i = 0; i < number; i++) {
  118. if (value >= indicator[i] && value < indicator[i + 1]) {
  119. res = i + 1;
  120. break;
  121. }
  122. }
  123. return res;
  124. };
  125. //获取地图 mapList
  126. useEffect(() => {
  127. if (selFloorId) {
  128. setLoading(true);
  129. getMapList({
  130. //floorId: 'Fl11010802593241ec348ecb4148806b9034c8957454',
  131. floorId: selFloorId,
  132. })
  133. .then((res) => {
  134. setLoading(false);
  135. var data: API.MapInfo[] = (res.data || {}).spaceList || [];
  136. var mapSize = {
  137. width: (res.data || {}).width,
  138. height: (res.data || {}).height,
  139. };
  140. setMapSize(mapSize);
  141. // data.forEach((item) => {
  142. // console.log('item', item);
  143. // });
  144. setMapList(data);
  145. })
  146. .catch(() => {
  147. setLoading(false);
  148. });
  149. } else {
  150. setMapList([]);
  151. }
  152. }, [selFloorId]);
  153. //请求环境数据
  154. useEffect(() => {
  155. if (selNavId && selFloorId) {
  156. //setLoading(true);
  157. var floorParams = [{ id: selFloorId, projectId: projectId }];
  158. var endTime = moment();
  159. var startTime = moment().subtract(30, 'minutes');
  160. var startStr = startTime.format('YYYYMMDDHHmmss');
  161. var endStr = endTime.format('YYYYMMDDHHmmss');
  162. queryEnvironmentParam(floorParams, {
  163. endTime: endStr,
  164. startTime: startStr,
  165. param: selNavId,
  166. })
  167. .then((res) => {
  168. //setLoading(false);
  169. var avgValues = (res.data || {}).avgValues;
  170. avgValues = avgValues ? avgValues.toFixed(selNav.fixed) : avgValues;
  171. var navTemp = { ...selNav, avgValues: avgValues };
  172. setSelNav(navTemp);
  173. //空间环境数据
  174. var dataSpaces = ((res.data || {}).floors[0] || {}).dataSpaces || [];
  175. setEnvirMapList(dataSpaces);
  176. })
  177. .catch(() => {
  178. // setLoading(false);
  179. });
  180. }
  181. }, [selNavId, selFloorId]);
  182. //合并空间环境数据 和 空间数据
  183. useEffect(() => {
  184. var combineList: any = [];
  185. mapList.map(function (mitem) {
  186. var spaceId = mitem.spaceId;
  187. var filterSpace = envirMapList.filter((ele) => {
  188. return ele.id == spaceId;
  189. });
  190. var combine = Object.assign({}, mitem, filterSpace[0]);
  191. combineList.push(combine);
  192. });
  193. setMapCombineList(combineList);
  194. }, [envirMapList, mapList]);
  195. const showChartModal = (item) => {
  196. if (!item.roomFuncType) return;
  197. setShowChart(true);
  198. setShowSpace(item);
  199. };
  200. let firtTime: number = 0;
  201. let lastTime: number = 0;
  202. return (
  203. <>
  204. <PageHeader
  205. title={<FormattedMessage id="menu.environment" />}
  206. action={
  207. <SearchInput />
  208. // <Input.Search
  209. // size="large"
  210. // allowClear
  211. // style={{ width: '230px' }}
  212. // placeholder={'搜索空间'}
  213. // onSearch={(s) => {
  214. // setSearchText(s);
  215. // }}
  216. // />
  217. }
  218. />
  219. <TopNavigator
  220. navigatorList={navigatorList}
  221. type={'enviroment'}
  222. navigatorChange={navigatorChange}
  223. changeFloorId={changeFloorId}
  224. changeBuildId={changeBuildId}
  225. selParamObj={selNav}
  226. ></TopNavigator>
  227. <div className={styles.maptop}>
  228. <div className={styles.right}>
  229. {(selNav.indicator || []).map((item, index) => {
  230. return (
  231. <div className={styles.indicatorBox} key={index + 'indicator'}>
  232. <div className={styles.text}>{item}</div>
  233. <div
  234. className={styles.color}
  235. style={{
  236. backgroundColor:
  237. 'rgba(' + selNav.colorStr + (selNav.opacity as number) * (index + 1) + ')',
  238. }}
  239. ></div>
  240. </div>
  241. );
  242. })}
  243. </div>
  244. </div>
  245. <Spin spinning={loading} wrapperClassName={mapstyles.spinnclass}>
  246. <Map
  247. type={'enviroment'}
  248. mapList={mapCombineList}
  249. mapSize={mapSize}
  250. selFloorId={selFloorId}
  251. render={(item: API.MapInfo, index: number) => {
  252. return (
  253. <div
  254. className={cx(mapstyles.houseWrap)}
  255. key={index + 'house'}
  256. style={{
  257. left: item.left,
  258. top: item.top,
  259. width: item.width,
  260. height: item.height,
  261. }}
  262. >
  263. <div
  264. className={cx(mapstyles.house, {
  265. [mapstyles.notclick]:
  266. !item.roomFuncType || (!item.avgValues && item.avgValues != 0),
  267. [mapstyles.searchSel]: item.spaceId && item.spaceId === searchSpace.spaceId,
  268. })}
  269. style={{
  270. background: item.roomFuncType
  271. ? item.avgValues || item.avgValues == 0
  272. ? 'rgba(' +
  273. selNav.colorStr +
  274. (selNav.opacity as number) * getColorOpacity(item.avgValues) +
  275. ')'
  276. : ''
  277. : '',
  278. }}
  279. onClick={(event) => {
  280. event.stopPropagation();
  281. if (lastTime - firtTime < 200) {
  282. showChartModal(item);
  283. }
  284. }}
  285. onMouseDown={(event) => {
  286. //event.stopPropagation();
  287. firtTime = new Date().getTime();
  288. }}
  289. onMouseUp={(event) => {
  290. //event.stopPropagation();
  291. lastTime = new Date().getTime();
  292. }}
  293. >
  294. <div className={mapstyles.content}>
  295. <div className={mapstyles.contentDiv}>
  296. <Icon
  297. className=""
  298. type={getSpaceFunc(item.roomFuncType)}
  299. style={{ fontSize: 20 }}
  300. ></Icon>
  301. <div className={mapstyles.name}>{item.localName}</div>
  302. </div>
  303. </div>
  304. </div>
  305. </div>
  306. );
  307. }}
  308. ></Map>
  309. </Spin>
  310. {/* {mapList.map(function (item, index) {
  311. return (
  312. <div
  313. key={index + 'house'}
  314. className={mapstyles.house}
  315. style={{
  316. left: item.left,
  317. top: item.top,
  318. width: item.width,
  319. height: item.height,
  320. backgroundColor:
  321. 'rgba(' +
  322. selNav.colorStr +
  323. (selNav.opacity as number) * getColorOpacity(item.value) +
  324. ')',
  325. }}
  326. >
  327. <div className={mapstyles.content}>
  328. <Icon className="" type={item.type} style={{ fontSize: 20 }}></Icon>
  329. <div className={mapstyles.name}>{item.name}</div>
  330. </div>
  331. </div>
  332. );
  333. })} */}
  334. {showChart && (
  335. <ChartModal
  336. showSpace={showSpace}
  337. selNav={selNav}
  338. onClose={() => {
  339. setShowChart(false);
  340. }}
  341. ></ChartModal>
  342. )}
  343. </>
  344. );
  345. };
  346. export default Environment;