index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. import { getPendingList } from '@/services/message';
  2. import { getComparisonData } from '@/services/OperationManagement';
  3. import { queryConditionSnapshot } from '@/services/SmartOps';
  4. import { getToken, UnityAction } from '@/utils/utils';
  5. import { LoadingOutlined } from '@ant-design/icons';
  6. import { connect, useParams, useRequest } from '@umijs/max';
  7. import dayjs from 'dayjs';
  8. import { useEffect } from 'react';
  9. import { getScadaPage } from '../../services/OperationManagement';
  10. import styles from './index.less';
  11. const HomePage = (props) => {
  12. const { projectId } = useParams();
  13. const { data } = useRequest(queryConditionSnapshot, {
  14. defaultParams: [{ project_id: projectId }],
  15. });
  16. const getPositionPst = (e) => {
  17. const width = document.body.clientWidth;
  18. const height = document.body.clientHeight;
  19. const xPst = (e.clientX / width).toFixed(2);
  20. const yPst = (e.clientY / height).toFixed(2);
  21. return xPst + '-' + yPst;
  22. };
  23. const webMouseEvent = {
  24. onMouseUp: (e) => {
  25. UnityAction.sendMsg('PointerOut', getPositionPst(e));
  26. },
  27. onMouseDown: (e) => {
  28. UnityAction.sendMsg('PointerIn', getPositionPst(e));
  29. },
  30. };
  31. useEffect(() => {
  32. localStorage.width = document.documentElement.getBoundingClientRect().width;
  33. window.refreshRem();
  34. }, []);
  35. return (
  36. <div className={styles.content} {...webMouseEvent}>
  37. <CenterContent data={data} />
  38. <LeftContent data={data} />
  39. <RightContent data={data} />
  40. </div>
  41. );
  42. };
  43. const LeftContent = (props) => {
  44. const { data } = props;
  45. return (
  46. <div className={styles.left}>
  47. {/* <SmartWork data={data} /> */}
  48. <WaterAmt data={data} />
  49. <WaterQuality data={data} />
  50. <Backlog />
  51. {/* <Backlog /> */}
  52. </div>
  53. );
  54. };
  55. const CenterContent = (props) => {
  56. const { data } = props;
  57. return (
  58. <div className={styles.centerBox}>
  59. <SmartWork data={data} />
  60. <SelfInspection />
  61. {/* <Backlog />
  62. <Scada /> */}
  63. </div>
  64. );
  65. };
  66. const RightContent = (props) => {
  67. const { data } = props;
  68. return (
  69. <div className={styles.right}>
  70. {/* <SelfInspection /> */}
  71. <Electric data={data} />
  72. <Medicine />
  73. <Scada />
  74. {/* <Scada /> */}
  75. </div>
  76. );
  77. };
  78. const getValue = (str) => {
  79. const result = str?.match(/.*?(\d+(?:\.\d+)?)\D*$/);
  80. if (result && result[1]) return result[1];
  81. return 0;
  82. };
  83. // 水厂工况
  84. const SmartWork = (props) => {
  85. const { data } = props;
  86. return (
  87. <div
  88. className={styles.smartWork}
  89. onClick={() => UnityAction.sendMsg('menuItem', '工况管理')}
  90. >
  91. <Title title="水厂工况" />
  92. <div className={styles.scoreBox}>
  93. <div className={styles.circle}>
  94. <div className={styles.score}>{data?.score}</div>
  95. <div className={styles.grade}>{data?.grade}</div>
  96. </div>
  97. <div className={styles.scoreTitle}>
  98. 当前运行{data?.grade},可继续优化
  99. </div>
  100. </div>
  101. <div className={styles.time}>
  102. {dayjs(data?.clac_time).format('YYYY-MM-DD HH:mm')}
  103. </div>
  104. </div>
  105. );
  106. };
  107. // 水量监测
  108. const WaterAmt = (props) => {
  109. const { data } = props;
  110. const { projectId } = useParams();
  111. return (
  112. <div
  113. className={styles.waterAmt}
  114. onClick={() => UnityAction.sendMsg('menuItem', '水量监测')}
  115. >
  116. <Title title="水量监测" />
  117. <div className={styles.boxTip}>当前进水稳定,出水稳定</div>
  118. <ul>
  119. <li>
  120. <div className={styles.value}>{getValue(data?.fwa)}</div>
  121. <div className={styles.btn1}>进水量(m³/h)</div>
  122. </li>
  123. <li>
  124. <div className={styles.value}>{getValue(data?.dwa)}</div>
  125. <div className={styles.btn2}>产水量(m³/h)</div>
  126. </li>
  127. </ul>
  128. </div>
  129. );
  130. };
  131. // 水质监测
  132. const WaterQuality = (props) => {
  133. const { data } = props;
  134. const { projectId } = useParams();
  135. return (
  136. <div
  137. className={styles.waterQuality}
  138. onClick={() => UnityAction.sendMsg('menuItem', '水质监测')}
  139. >
  140. <Title title="水质监测" />
  141. <div className={styles.boxTip}>水质监测较好</div>
  142. <ul>
  143. <li>
  144. <div className={styles.valueLong}>{getValue(data?.dsan)}</div>
  145. <div className={styles.btn1}>出水余氯(ppm)</div>
  146. </li>
  147. <li>
  148. <div className={styles.valueLong}>{getValue(data?.dtur)}</div>
  149. <div className={styles.btn2}>出水浊度(NTU)</div>
  150. </li>
  151. </ul>
  152. </div>
  153. );
  154. };
  155. // 系统自检
  156. const SelfInspection = connect(({ eqSelfInspection, loading }) => ({
  157. autoReport: eqSelfInspection.autoReport,
  158. loading: loading.models['eqSelfInspection'],
  159. }))((props) => {
  160. const { autoReport, dispatch, loading } = props;
  161. const { projectId } = useParams();
  162. const renderStatus = () => {
  163. if (loading) return <LoadingOutlined />;
  164. if (autoReport.Status > 0) {
  165. return (
  166. <span className={styles.text} style={{ color: '#FE5850' }}>
  167. 异常
  168. </span>
  169. );
  170. }
  171. return (
  172. <span className={styles.text} style={{ color: '' }}>
  173. 正常
  174. </span>
  175. );
  176. };
  177. useEffect(() => {
  178. dispatch({
  179. type: 'eqSelfInspection/getAutoPatrol',
  180. payload: {
  181. projectId,
  182. },
  183. });
  184. }, []);
  185. return (
  186. <div
  187. className={styles.selfInspection}
  188. onClick={() => UnityAction.sendMsg('menuItem', '系统自检')}
  189. >
  190. <Title title="系统自检" />
  191. <div className={styles.selfCon}>
  192. <div className={styles.circle}>{renderStatus()}</div>
  193. <div className={styles.texting}>自检中</div>
  194. </div>
  195. <div className={styles.time}>
  196. {dayjs(autoReport.CreatedTime).format('YYYY-MM-DD HH:mm')}
  197. </div>
  198. {/* <div className={styles.insTag}>自检中</div> */}
  199. {/* <div className={styles.insStatus}>{renderStatus()}</div>
  200. <div className={styles.time} style={{ marginBottom: 30 }}>
  201. {dayjs(autoReport.CreatedTime).format('YYYY-MM-DD HH:mm')}
  202. </div> */}
  203. </div>
  204. );
  205. });
  206. // 能耗监测
  207. const Electric = (props) => {
  208. const { data } = props;
  209. const { projectId } = useParams();
  210. return (
  211. <div
  212. className={styles.electric}
  213. onClick={() => UnityAction.sendMsg('menuItem', '能耗监测')}
  214. >
  215. <Title title="能耗监测" />
  216. <ul>
  217. <li>
  218. <div className={styles.value}>{getValue(data?.elec)}</div>
  219. <div className={styles.btn1}>用电量(KWh/h)</div>
  220. </li>
  221. </ul>
  222. </div>
  223. );
  224. };
  225. // 药耗监测
  226. const Medicine = () => {
  227. const { projectId } = useParams();
  228. const time = dayjs().format('YYYY-MM');
  229. const { data } = useRequest(getComparisonData, {
  230. defaultParams: [
  231. {
  232. project_id: projectId,
  233. start: time,
  234. end: time,
  235. type: 1,
  236. flag: 1,
  237. },
  238. ],
  239. formatResult(res) {
  240. return res[0];
  241. },
  242. });
  243. return (
  244. <div
  245. className={styles.medicine}
  246. onClick={() => UnityAction.sendMsg('menuItem', '药耗监测')}
  247. >
  248. <Title title="药耗监测" />
  249. <ul>
  250. <li>
  251. <div className={styles.valueLong}>
  252. {data?.value?.toFixed(2) || '-'}
  253. </div>
  254. <div className={styles.btn1}>当月吨水药成本(元)</div>
  255. </li>
  256. </ul>
  257. </div>
  258. );
  259. };
  260. // 工艺监控
  261. const Scada = () => {
  262. const { projectId } = useParams();
  263. const { data } = useRequest(getScadaPage, {
  264. defaultParams: [{ project_id: projectId }],
  265. formatResult: (res) => {
  266. let domain = location.host.includes('pad.greentech.com.cn')
  267. ? 'https://metawant.greentech.com.cn/'
  268. : 'http://47.96.12.136:8788/';
  269. const token = getToken();
  270. const pageList = res?.filter((item) => item.hide);
  271. const urls = pageList.map(
  272. (item) =>
  273. `${domain}smart-water/scada/index.html#/3dview/${projectId}/${item.id}?JWT-TOKEN=${token}&hideTitle=true&pauseLoadRealTimeData=true`,
  274. );
  275. return urls.splice(0, 1);
  276. },
  277. });
  278. return (
  279. <div
  280. className={styles.scadaMain}
  281. onClick={() => UnityAction.sendMsg('menuItem', '工艺监控')}
  282. >
  283. <Title title="工艺监控" />
  284. <div style={{ width: '707px', height: '279px' }}>
  285. {data?.map((url) => (
  286. <iframe
  287. key={url}
  288. style={{
  289. width: '707px',
  290. height: '279px',
  291. borderRadius: '0 0 44px 0',
  292. }}
  293. frameborder="0"
  294. src={url}
  295. />
  296. ))}
  297. <div className={styles.mask}></div>
  298. </div>
  299. </div>
  300. );
  301. };
  302. // 待办事项
  303. const Backlog = (props) => {
  304. const { projectId } = useParams();
  305. const { data, loading } = useRequest(getPendingList, {
  306. defaultParams: [{ project_id: projectId }],
  307. });
  308. const handleClick = (item) => {
  309. if (item.type === 0) {
  310. // task
  311. UnityAction.sendMsg('OpenTaskModal', `mandate_id=${item.origin_id}`);
  312. } else {
  313. // order
  314. UnityAction.sendMsg(
  315. 'OpenWorkOrderModal',
  316. `order_id=${item.origin_id}&order_type=${item.origin_type}`,
  317. );
  318. }
  319. };
  320. return (
  321. <div
  322. className={styles.backlogMain}
  323. onClick={() => UnityAction.sendMsg('menuItem', '待办事项')}
  324. >
  325. <Title title={<div style={{ display: 'flex' }}>待办事项</div>} />
  326. <div className={styles.backlog}>
  327. <div>
  328. {data?.map((item) => (
  329. <div
  330. key={item.connect}
  331. className={styles.item}
  332. onClick={(e) => {
  333. e.stopPropagation();
  334. handleClick(item);
  335. }}
  336. >
  337. <div className={styles.createTime}>
  338. {dayjs(item.time).format('MM-DD HH:mm')}
  339. </div>
  340. <div className={styles.titleCon}>
  341. <div className={styles.point} />
  342. <div className={styles.titleText}>{item.title}</div>
  343. </div>
  344. <div className={styles.bottomCon}>{item.content}</div>
  345. </div>
  346. ))}
  347. </div>
  348. </div>
  349. </div>
  350. );
  351. };
  352. const Title = ({ title }) => {
  353. return (
  354. <div className={styles.titleContent}>
  355. <div className={styles.line} />
  356. <div className={styles.boxTitle}>{title}</div>
  357. </div>
  358. );
  359. };
  360. const Box = ({ title, children, onClick, small }) => {
  361. return (
  362. <div
  363. className={`${styles.box} ${small ? '' : styles.boxH}`}
  364. onClick={onClick}
  365. >
  366. <div className={styles.titleContent}>
  367. <div className={styles.line} />
  368. <div className={styles.boxTitle}>{title}</div>
  369. </div>
  370. {/* <span className={styles.boxTitle}>
  371. <div className={styles.line}></div>
  372. {title}
  373. </span> */}
  374. {children}
  375. </div>
  376. );
  377. };
  378. export default HomePage;