index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import React, { useState, useEffect, useCallback, useRef } from 'react';
  2. import PageHeader from '@/sgcomponents/PageHeader';
  3. import Map from '@/sgcomponents/map';
  4. import TopNavigator from '@/sgcomponents/topNavigator';
  5. import RunNavRight from './components/topNavRight';
  6. import { FormattedMessage, history, useModel } from 'umi';
  7. import { Spin } from 'antd';
  8. import { Popover } from 'antd';
  9. import styles from './index.less';
  10. import mapstyles from '@/assets/css/map.less';
  11. import Icon from '@/tenants-ui/SgIcon';
  12. import SearchInput from '@/sgcomponents/SearchInput';
  13. import moment from 'moment';
  14. import cx from 'classnames';
  15. import { getMapList, queryDeviceTimeManage } from '@/services/sgservice/environment';
  16. type runtimeNavType = {
  17. normalRun: any;
  18. overtimeWork: number;
  19. meetingBook: number;
  20. };
  21. const Runtime: React.FC = () => {
  22. // const { maptemp6 } = equipImageMap;
  23. const { changeLastFloorId } = useModel('buildFloor');
  24. const { searchSpace } = useModel('searchInfo');
  25. const { getSpaceFunc } = useModel('spaceFunc');
  26. const [loading, setLoading] = useState<boolean>(false);
  27. const [runtimeNav, setRuntimeNav] = useState<runtimeNavType>({});
  28. const [mapList, setMapList] = useState<API.MapInfo[]>([]);
  29. const [mapSize, setMapSize] = useState<any>({});
  30. const [mapCombineList, setMapCombineList] = useState<any[]>([]);
  31. const [selFloorId, setSelFloorId] = useState<string>();
  32. const [selTime, setSelTime] = useState<string>(moment().format('YYYYMMDD'));
  33. const [spaceTimeList, setSpaceTimeList] = useState<any[]>([]);
  34. //楼层切换的回调
  35. const changeFloorId = (data: string) => {
  36. setSelFloorId(data);
  37. };
  38. const checkRecord = () => {
  39. history.push('/runtime/recordList');
  40. console.log('showR');
  41. };
  42. //时间切换的回调
  43. const changeTime = (time) => {
  44. var timeStr = time.format('YYYYMMDD');
  45. setSelTime(timeStr);
  46. };
  47. //获取地图 mapList
  48. useEffect(() => {
  49. if (selFloorId) {
  50. changeLastFloorId(selFloorId);
  51. setLoading(true);
  52. getMapList({
  53. floorId: selFloorId,
  54. //floorId: 'Fl11010802593241ec348ecb4148806b9034c8957454',
  55. projectId: '',
  56. })
  57. .then((res) => {
  58. setLoading(false);
  59. var data: API.MapInfo[] = (res.data || {}).spaceList || [];
  60. var mapSize = {
  61. width: (res.data || {}).width,
  62. height: (res.data || {}).height,
  63. };
  64. setMapSize(mapSize);
  65. setMapList(data);
  66. })
  67. .catch(() => {
  68. setLoading(false);
  69. });
  70. } else {
  71. setMapList([]);
  72. }
  73. }, [selFloorId]);
  74. const getDeviceTime = () => {
  75. queryDeviceTimeManage({
  76. floorId: selFloorId,
  77. //floorId: 'Fl11010802593241ec348ecb4148806b9034c8957454',
  78. date: selTime,
  79. })
  80. .then(function (res) {
  81. //setLoading(false);
  82. var resdata = res || {};
  83. setRuntimeNav({
  84. normalRun: resdata.workTimeNum,
  85. overtimeWork: resdata.overTimeNum,
  86. meetingBook: resdata.meetTimeNum,
  87. });
  88. var resList = res.content || [];
  89. resList.forEach((ritem) => {
  90. ritem.runTimeStatus = 'normalRun'; //正常工作
  91. var timeList = [];
  92. if (ritem.hasOwnProperty('workTimeStartTime')) {
  93. var timeStrArr = [ritem.workTimeStartTime, ritem.workTimeEndTime];
  94. timeList.push(timeStrArr);
  95. }
  96. if (ritem.hasOwnProperty('meetTime')) {
  97. ritem.runTimeStatus = 'meetingBook'; //会议预约
  98. ritem.meetTime.forEach((meetitem) => {
  99. var timeStrArr = [meetitem.meetTimeStartTime, meetitem.meetTimeEndTime];
  100. timeList.push(timeStrArr);
  101. });
  102. }
  103. if (ritem.hasOwnProperty('overTimeStartTime')) {
  104. var timeStrArr = [ritem.overTimeStartTime, ritem.overTimeEndTime];
  105. timeList.push(timeStrArr);
  106. ritem.runTimeStatus = 'overtimeWork'; //加班
  107. }
  108. ritem.showTimeList = timeList;
  109. //console.log('timeList', timeList);
  110. ritem.showTimeStr =
  111. timeList.length > 0
  112. ? timeList[0][0] +
  113. '-' +
  114. (timeList[timeList.length - 1][1] > timeList[0][1]
  115. ? timeList[timeList.length - 1][1]
  116. : timeList[0][1])
  117. : '';
  118. });
  119. setSpaceTimeList(resList);
  120. })
  121. .catch(() => {
  122. //setLoading(false);
  123. });
  124. };
  125. let setTimer = useRef<Timer>(null);
  126. //获取时间列表 spaceTimeList
  127. useEffect(() => {
  128. if (selFloorId && selTime) {
  129. //setLoading(true);
  130. getDeviceTime(); //第一次执行
  131. if (setTimer.current) {
  132. clearInterval(setTimer.current);
  133. setTimer.current = null;
  134. }
  135. //循环调接口
  136. setTimer.current = setInterval(() => {
  137. getDeviceTime();
  138. }, 10000);
  139. return () => {
  140. clearInterval(setTimer.current);
  141. };
  142. }
  143. }, [selFloorId, selTime]);
  144. useEffect(() => {
  145. //mapList,spaceTimeList 这两个数据的结合
  146. //console.log('dfsd-------');
  147. // if (mapList && mapList.length > 0 && spaceTimeList && spaceTimeList.length > 0) {
  148. var combineList: any = [];
  149. mapList.map(function (mitem) {
  150. var spaceId = mitem.spaceId;
  151. var filterSpace = spaceTimeList.filter((ele) => {
  152. return ele.id == spaceId;
  153. });
  154. var combine = Object.assign({}, mitem, filterSpace[0]);
  155. combineList.push(combine);
  156. });
  157. setMapCombineList(combineList);
  158. // }
  159. }, [mapList, spaceTimeList]);
  160. return (
  161. <>
  162. <PageHeader
  163. title={<FormattedMessage id="menu.runtime" />}
  164. action={
  165. // <div className={styles.headerRight}>
  166. // <div className={styles.check} onClick={checkRecord} style={{ display: 'none' }}>
  167. // <Icon className="" style={{ marginRight: 6 }} type="document" />
  168. // <span>查看加班记录</span>
  169. // </div>
  170. // </div>
  171. <SearchInput />
  172. }
  173. />
  174. <TopNavigator
  175. type={'runtime'}
  176. action={<RunNavRight runtimeNav={runtimeNav} changeTime={changeTime}></RunNavRight>}
  177. changeFloorId={changeFloorId}
  178. ></TopNavigator>
  179. <div className={styles.maptop}>
  180. <div className={styles.right}></div>
  181. </div>
  182. {/* <div className={styles.map}>
  183. <div className={styles.specialRoom}></div>
  184. <img src={mapImg}></img>
  185. </div> */}
  186. {/* <div
  187. className={mapstyles.house}
  188. style={{
  189. width: 180,
  190. height: 100,
  191. }}
  192. >
  193. <div className={mapstyles.allTime}>08:00-23:00</div>
  194. <div className={mapstyles.content}>
  195. <Icon className="" type="office" style={{ fontSize: 20 }}></Icon>
  196. <div className={mapstyles.name}>Jozy Zone</div>
  197. </div>
  198. </div> */}
  199. <Spin spinning={loading} wrapperClassName={mapstyles.spinnclass}>
  200. <Map
  201. mapList={mapCombineList}
  202. mapSize={mapSize}
  203. selFloorId={selFloorId}
  204. type={'runtime'}
  205. render={(item, index) => {
  206. return (
  207. <div
  208. className={mapstyles.houseWrap}
  209. key={index + 'house'}
  210. style={{
  211. left: item.left,
  212. top: item.top,
  213. width: item.width,
  214. height: item.height,
  215. }}
  216. >
  217. <div
  218. key={index + 'house'}
  219. className={cx(mapstyles.house, {
  220. [mapstyles.notclick]: !item.roomFuncType,
  221. [mapstyles.searchSel]: item.spaceId && item.spaceId === searchSpace.spaceId,
  222. })}
  223. style={{
  224. background: item.roomFuncType
  225. ? item.runTimeStatus == 'meetingBook'
  226. ? 'rgba(0, 220, 35, 0.2)'
  227. : item.runTimeStatus == 'overtimeWork'
  228. ? 'rgba(94, 139, 207, 0.2)'
  229. : 'rgba(196, 196, 196, 0.2)'
  230. : '',
  231. }}
  232. >
  233. <div className={mapstyles.allTime}>
  234. {/* {(item.timeList || []).map(function (titem: string, tindex: number) {
  235. return <span key={tindex + 'time'}>{titem},</span>;
  236. })} */}
  237. {item.showTimeList && item.showTimeList.length > 1 && (
  238. <Popover
  239. content={
  240. <div>
  241. <div className={styles.popTitle}>工作时间:</div>
  242. <div>
  243. {item.showTimeList[0][0]}-{item.showTimeList[0][1]}
  244. </div>
  245. <div className={styles.popTitle}>
  246. {item.runTimeStatus == 'overtimeWork' ? '加班时间' : '会议时间'}:
  247. </div>
  248. {(item.showTimeList || []).map((timeItem, index) => {
  249. if (index > 0) {
  250. return (
  251. <div key={'time' + index}>
  252. {timeItem[0]}-{timeItem[1]}
  253. </div>
  254. );
  255. }
  256. })}
  257. </div>
  258. }
  259. trigger="hover"
  260. style={{ color: 'none' }}
  261. >
  262. <span
  263. className={cx({
  264. [mapstyles.overworkTime]: item.runTimeStatus == 'overtimeWork',
  265. [mapstyles.meetTime]: item.runTimeStatus == 'meetingBook',
  266. })}
  267. >
  268. {item.showTimeStr}
  269. </span>
  270. </Popover>
  271. )}
  272. {item.showTimeList && item.showTimeList.length == 1 && (
  273. <span>{item.showTimeStr}</span>
  274. )}
  275. </div>
  276. <div className={mapstyles.content}>
  277. <Icon
  278. className=""
  279. type={getSpaceFunc(item.roomFuncType)}
  280. style={{ fontSize: 20 }}
  281. ></Icon>
  282. <div className={mapstyles.name}>{item.localName}</div>
  283. </div>
  284. </div>
  285. </div>
  286. );
  287. }}
  288. ></Map>
  289. </Spin>
  290. </>
  291. );
  292. };
  293. export default Runtime;