EnergyCostComparison.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // 能耗监测
  2. import ChartModule from '@/components/ManagementPage/chartModule';
  3. import PageContent from '@/components/PageContent';
  4. import PageTitle from '@/components/PageTitle';
  5. import { getComparisonData } from '@/services/OperationManagement';
  6. import { queryConditionSnapshot } from '@/services/SmartOps';
  7. import { UnityAction } from '@/utils/utils';
  8. import { LineChartOutlined } from '@ant-design/icons';
  9. import { history, useParams, useRequest } from '@umijs/max';
  10. import { message } from 'antd';
  11. import dayjs from 'dayjs';
  12. import { useEffect, useState } from 'react';
  13. import styles from './manage.less';
  14. const typeParams = [
  15. {
  16. // 计划吨水电耗
  17. type: '5',
  18. flag: '0',
  19. },
  20. {
  21. // 实际吨水电耗
  22. type: '5',
  23. flag: '1',
  24. },
  25. {
  26. // 计划用电量
  27. type: '6',
  28. flag: '0',
  29. },
  30. {
  31. // 实际用电量
  32. type: '6',
  33. flag: '1',
  34. },
  35. ];
  36. const CostComparison = () => {
  37. const [open, setOpen] = useState(false);
  38. return (
  39. <PageContent closeable={false}>
  40. <PageTitle onReturn={() => UnityAction.sendMsg('menuItem', '首页')}>
  41. 能耗数据
  42. <div
  43. onClick={(e) => {
  44. e.stopPropagation();
  45. setOpen(!open);
  46. }}
  47. style={{ marginLeft: '0.1rem' }}
  48. className={`password-eye ${open ? 'open' : ''}`}
  49. />
  50. </PageTitle>
  51. <EnergyCost open={open} showTip />
  52. </PageContent>
  53. );
  54. };
  55. export default CostComparison;
  56. export const EnergyCost = ({ open, detailClick, showTip }) => {
  57. const { projectId } = useParams();
  58. const [chartData, setChartData] = useState([]);
  59. const [curElecPerCost, setElecPerCost] = useState(0); // 当前月实际吨水电耗
  60. const [curElecUsed, setCurElecUsed] = useState(0); // 当前月实际用电量
  61. const defaultTime = {
  62. s_time: dayjs().subtract(1, 'years').format('YYYY-MM'),
  63. e_time: dayjs().format('YYYY-MM'),
  64. };
  65. const defaultParams = {
  66. project_id: projectId,
  67. start: defaultTime.s_time,
  68. end: defaultTime.e_time,
  69. };
  70. const getValue = (str) => {
  71. const result = str?.match(/.*?(\d+(?:\.\d+)?)\D*$/);
  72. if (result && result[1]) return result[1];
  73. return 0;
  74. };
  75. const { data: snapshot } = useRequest(queryConditionSnapshot, {
  76. defaultParams: [{ project_id: projectId }],
  77. formatResult: (result) => {
  78. const elec = Number(getValue(result.data.elec_unit));
  79. let resultText = `当前电耗持平理论值 ${
  80. result?.data?.elec_unit_theory || 0
  81. }KWh/m³`;
  82. if (elec) {
  83. if (elec > result.data.elec_unit_theory) {
  84. resultText = `当前电耗高于理论值 ${result.data.elec_unit_theory}KWh/m³`;
  85. }
  86. if (elec === result.data.elec_unit_theory) {
  87. resultText = `当前电耗持平理论值 ${result.data.elec_unit_theory}KWh/m³`;
  88. }
  89. if (elec < result.data.elec_unit_theory) {
  90. resultText = `当前电耗低于理论值 ${result.data.elec_unit_theory}KWh/m³`;
  91. }
  92. }
  93. return { ...result.data, resultText };
  94. },
  95. });
  96. const getChartData = () => {
  97. // 构建请求列表
  98. const queryList = [];
  99. for (let index = 0; index < 4; index++) {
  100. queryList.push(
  101. getComparisonData({ ...defaultParams, ...typeParams[index] }),
  102. );
  103. }
  104. // 获取四组数据
  105. return Promise.all(queryList).catch(() => {
  106. message.error('请求数据失败');
  107. });
  108. };
  109. const getFixed = (maxValue) => {
  110. // 如果小于1,则保留最后两位不为0的数字
  111. // 如果大于1小于10,则保留三位
  112. // 大于10,保留两位
  113. // 大于100,保留一位
  114. // 大于1000,不保留
  115. if (maxValue === 0) {
  116. return 2;
  117. }
  118. let fixed = 0;
  119. if (maxValue < 1) {
  120. const decimal = maxValue.toFixed(100).toString().split('.')[1];
  121. const decimalArr = decimal.split('');
  122. for (let index = 0; index < decimalArr.length; index++) {
  123. if (decimalArr[index] === '0') {
  124. fixed++;
  125. } else {
  126. break;
  127. }
  128. }
  129. fixed += 2;
  130. } else if (maxValue < 10) {
  131. fixed = 3;
  132. } else if (maxValue < 100) {
  133. fixed = 2;
  134. } else if (maxValue < 1000) {
  135. fixed = 1;
  136. }
  137. return fixed;
  138. };
  139. const createChartData = async () => {
  140. const result = await getChartData().catch(() => {
  141. message.error('获取数据失败');
  142. });
  143. if (result && result.length) {
  144. const [planElecPerCost, actualElecPerCost, planElecUsed, actualElecUsed] =
  145. result;
  146. const elecPerCost = { yName: 'kwh/m³' };
  147. const elecUsed = { yName: 'kWh' };
  148. elecPerCost.xData = [
  149. ...new Set(
  150. [
  151. ...planElecPerCost.map((item) => item.month),
  152. ...actualElecPerCost.map((item) => item.month),
  153. ].map((item) => item),
  154. ),
  155. ].sort();
  156. // let year = `${dayjs(elecPerCost.xData[0]).year()}`;
  157. // elecPerCost.xData = [];
  158. // for (let index = 0; index < 12; index++) {
  159. // elecPerCost.xData.push(`${year}-${dayjs().month(index).format('MM')}`);
  160. // }
  161. // 确定保留的小数点
  162. const elecPerCostValue = [...planElecPerCost, ...actualElecPerCost]
  163. .map((item) => item.value)
  164. .reduce((a, b) => Math.max(a, b));
  165. const elecPerCostFixed = getFixed(elecPerCostValue);
  166. elecPerCost.dataList = [
  167. {
  168. type: 0,
  169. yIndex: 1,
  170. name: '计划吨水电耗',
  171. data: elecPerCost.xData.map((month) => {
  172. const pItem = planElecPerCost.find((item) => item.month === month);
  173. if (pItem) {
  174. return pItem.value.toFixed(elecPerCostFixed);
  175. }
  176. return 0;
  177. }),
  178. },
  179. {
  180. type: 0,
  181. yIndex: 1,
  182. name: '实际吨水电耗',
  183. data: elecPerCost.xData.map((month) => {
  184. const aItem = actualElecPerCost.find(
  185. (item) => item.month === month,
  186. );
  187. if (aItem) {
  188. return aItem.value.toFixed(elecPerCostFixed);
  189. }
  190. return 0;
  191. }),
  192. },
  193. ];
  194. elecUsed.xData = [
  195. ...new Set(
  196. [
  197. ...planElecUsed.map((item) => item.month),
  198. ...actualElecUsed.map((item) => item.month),
  199. ].map((item) => item),
  200. ),
  201. ].sort();
  202. // let year = `${dayjs(elecUsed.xData[0]).year()}`;
  203. // elecUsed.xData = [];
  204. // for (let index = 0; index < 12; index++) {
  205. // elecUsed.xData.push(`${year}-${dayjs().month(index).format('MM')}`);
  206. // }
  207. // 确定保留的小数点
  208. const elecUsedMaxValue = [...planElecUsed, ...actualElecUsed]
  209. .map((item) => item.value)
  210. .reduce((a, b) => Math.max(a, b));
  211. const elecUsedFixed = getFixed(elecUsedMaxValue);
  212. elecUsed.dataList = [
  213. {
  214. type: 3,
  215. yIndex: 1,
  216. name: '计划用电量',
  217. data: elecUsed.xData.map((month) => {
  218. const pItem = planElecUsed.find((item) => item.month === month);
  219. if (pItem) {
  220. return pItem.value.toFixed(elecUsedFixed);
  221. }
  222. return 0;
  223. }),
  224. },
  225. {
  226. type: 3,
  227. yIndex: 1,
  228. name: '实际用电量',
  229. data: elecUsed.xData.map((month) => {
  230. const aItem = actualElecUsed.find((item) => item.month === month);
  231. if (aItem) {
  232. return aItem.value.toFixed(elecUsedFixed);
  233. }
  234. return 0;
  235. }),
  236. },
  237. ];
  238. elecUsed.chartType = 'bar';
  239. setChartData([elecPerCost, elecUsed]);
  240. let curElecPerCost = actualElecPerCost?.find((item) =>
  241. dayjs().isSame(item?.month, 'month'),
  242. );
  243. if (curElecPerCost)
  244. setElecPerCost(curElecPerCost?.value.toFixed(elecPerCostFixed));
  245. let curElecUsed = actualElecUsed?.find((item) =>
  246. dayjs().isSame(item?.month, 'month'),
  247. );
  248. if (curElecUsed)
  249. setCurElecUsed(curElecUsed?.value.toFixed(elecUsedFixed));
  250. } else {
  251. setChartData([]);
  252. }
  253. };
  254. useEffect(() => {
  255. createChartData();
  256. }, []);
  257. const goEnergyDetail = () => {
  258. if (detailClick) {
  259. detailClick();
  260. } else {
  261. history.push(`/home/energy/detail/${projectId}`);
  262. }
  263. };
  264. return (
  265. <div
  266. className="content-tab"
  267. style={{ padding: '0.2rem', position: 'relative', marginTop: '0.1rem' }}
  268. >
  269. {showTip && <div className={styles.pageTip}>{snapshot?.resultText}</div>}
  270. <div className="card-box" style={{ padding: '0.1rem 0' }}>
  271. <LineChartOutlined
  272. style={{
  273. fontSize: '0.4rem',
  274. position: 'absolute',
  275. right: '0.3rem',
  276. color: '#0139f1',
  277. }}
  278. onClick={goEnergyDetail}
  279. />
  280. <div className={styles.curEnergyCost}>
  281. <div
  282. className={styles.item}
  283. style={{
  284. borderRight: '1px solid #eaeaea',
  285. borderBottom: '1px solid #eaeaea',
  286. }}
  287. >
  288. <div className={styles.value}>
  289. {open ? getValue(snapshot?.elec_unit || '') : '***'}
  290. <span className={styles.unit}>kWh/t</span>
  291. </div>
  292. <div className={styles.name}>近一小时吨水电耗</div>
  293. </div>
  294. <div
  295. className={styles.item}
  296. style={{
  297. borderBottom: '1px solid #eaeaea',
  298. }}
  299. >
  300. <div className={styles.value}>
  301. {open ? getValue(snapshot?.elec || '') : '***'}
  302. <span className={styles.unit}>kWh</span>
  303. </div>
  304. <div className={styles.name}>近一小时用电量</div>
  305. </div>
  306. <div
  307. className={styles.item}
  308. style={{
  309. borderRight: '1px solid #eaeaea',
  310. }}
  311. >
  312. <div className={styles.value}>
  313. {open ? curElecPerCost : '***'}
  314. <span className={styles.unit}>kWh/t</span>
  315. </div>
  316. <div className={styles.name}>当月吨水电耗</div>
  317. </div>
  318. <div className={styles.item}>
  319. <div className={styles.value}>
  320. {open ? curElecUsed : '***'}
  321. <span className={styles.unit}>kWh</span>
  322. </div>
  323. <div className={styles.name}>当月用电量</div>
  324. </div>
  325. </div>
  326. </div>
  327. {chartData.length !== 0 && (
  328. <div
  329. className="card-box"
  330. style={{
  331. height: '9.2rem',
  332. display: 'flex',
  333. flexDirection: 'column',
  334. justifyContent: 'space-between',
  335. padding: '0.6rem 0 0.4rem',
  336. marginTop: '0.4rem',
  337. }}
  338. >
  339. <div style={{ height: '3.5rem' }}>
  340. <ChartModule {...chartData[0]} />
  341. </div>
  342. <div style={{ height: '3.5rem' }}>
  343. <ChartModule {...chartData[1]} />
  344. </div>
  345. </div>
  346. )}
  347. </div>
  348. );
  349. };