|
@@ -0,0 +1,325 @@
|
|
|
+// 能耗详情
|
|
|
+
|
|
|
+import ChartModule from '@/components/ManagementPage/chartModule';
|
|
|
+import PageContent from '@/components/PageContent';
|
|
|
+import PageTitle from '@/components/PageTitle';
|
|
|
+import {
|
|
|
+ queryAccumulativeEnergy,
|
|
|
+ queryChartList,
|
|
|
+ queryEnergyConfig,
|
|
|
+ queryEnergyWaterChart,
|
|
|
+} from '@/services/OperationManagement';
|
|
|
+import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
|
|
+import { useParams, useRequest } from '@umijs/max';
|
|
|
+import { Spin } from 'antd';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import { useMemo } from 'react';
|
|
|
+import styles from './manage.less';
|
|
|
+
|
|
|
+const EnergyCostDetail = () => {
|
|
|
+ const { projectId } = useParams();
|
|
|
+
|
|
|
+ const TIMER = 3600000;
|
|
|
+
|
|
|
+ // 全场概况
|
|
|
+ const { data: allFactoryData, loading: allFacLoading } = useRequest(
|
|
|
+ queryEnergyConfig,
|
|
|
+ {
|
|
|
+ defaultParams: [projectId],
|
|
|
+ pollingInterval: TIMER,
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ // 当日累计能耗、吨水电耗、环比
|
|
|
+ const { data: energyData, loading: energyLoading } = useRequest(
|
|
|
+ queryAccumulativeEnergy,
|
|
|
+ {
|
|
|
+ defaultParams: [projectId],
|
|
|
+ pollingInterval: TIMER,
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ // 吨水电耗折线图
|
|
|
+ const { data: chartData, loading: chartLosding } = useRequest(
|
|
|
+ queryEnergyWaterChart,
|
|
|
+ {
|
|
|
+ defaultParams: [
|
|
|
+ {
|
|
|
+ project_id: Number(projectId),
|
|
|
+ start_time: dayjs().startOf('day').format('YYYY-MM-DD 00:00:00'),
|
|
|
+ end_time: dayjs().format('YYYY-MM-DD 23:59:59'),
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ pollingInterval: TIMER,
|
|
|
+ formatResult(data) {
|
|
|
+ const tempData = data.data;
|
|
|
+ if (!tempData) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ xData: tempData?.map((item) => item.data_time) || [],
|
|
|
+ dataList: [
|
|
|
+ {
|
|
|
+ type: 0,
|
|
|
+ name: '吨水电耗',
|
|
|
+ data: tempData?.map((item) => item.value) || [],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ },
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ // 电量折线图
|
|
|
+ const { data: electricChartData, loading: electricLosding } = useRequest(
|
|
|
+ () =>
|
|
|
+ queryChartList({
|
|
|
+ project_id: Number(projectId),
|
|
|
+ metric_code: 'plant_electricity',
|
|
|
+ start_time: dayjs().startOf('day').format('YYYY-MM-DD 00:00:00'),
|
|
|
+ end_time: dayjs().format('YYYY-MM-DD 23:59:59'),
|
|
|
+ }),
|
|
|
+ {
|
|
|
+ pollingInterval: TIMER,
|
|
|
+ formatResult(data) {
|
|
|
+ if (!data?.data) return null;
|
|
|
+ const tempData = data.data;
|
|
|
+ const reversedData = tempData.reverse();
|
|
|
+ return {
|
|
|
+ xData: reversedData?.map((item) => item.data_time) || [],
|
|
|
+ dataList: [
|
|
|
+ {
|
|
|
+ type: 2,
|
|
|
+ name: '实际',
|
|
|
+ data: reversedData?.map((item) => item.value) || [],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ },
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ // 全场概况 包括两个折线图的y 轴名称
|
|
|
+ const allFactory = useMemo(() => {
|
|
|
+ const data = allFactoryData || {
|
|
|
+ voltage: '-',
|
|
|
+ transformer: '-',
|
|
|
+ capacity: '-',
|
|
|
+ runtime_capacity: '-',
|
|
|
+ voltage_unit: 'kV',
|
|
|
+ transformer_unit: '台',
|
|
|
+ capacity_unit: 'kVA',
|
|
|
+ runtime_capacity_unit: 'kVA',
|
|
|
+ energy_unit: 'kWh/t',
|
|
|
+ energy_water_unit: 'kWh',
|
|
|
+ };
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ title: '电量等级',
|
|
|
+ data: data.voltage,
|
|
|
+ unit: data.voltage_unit,
|
|
|
+ color: '#eb0ce2',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '变压器台数',
|
|
|
+ data: data.transformer,
|
|
|
+ unit: data.transformer_unit,
|
|
|
+ color: '#eb8c0c',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '装机容器',
|
|
|
+ data: data.capacity,
|
|
|
+ unit: data.capacity_unit,
|
|
|
+ color: '#0cafeb',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '运行容器',
|
|
|
+ data: data.runtime_capacity,
|
|
|
+ unit: data.runtime_capacity_unit,
|
|
|
+ color: '#50bb0a',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ }, [allFactoryData]);
|
|
|
+
|
|
|
+ const powerData = useMemo(() => {
|
|
|
+ const power = energyData || {
|
|
|
+ energy_change: '-',
|
|
|
+ energy_water_change: '-',
|
|
|
+ today_energy: '-',
|
|
|
+ today_energy_water: '-',
|
|
|
+ yesterday_energy: '-',
|
|
|
+ yesterday_energy_water: '-',
|
|
|
+ };
|
|
|
+
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ title: '当日吨水电耗',
|
|
|
+ data:
|
|
|
+ typeof power.today_energy_water == 'string'
|
|
|
+ ? power.today_energy_water
|
|
|
+ : power.today_energy_water?.toFixed(2),
|
|
|
+ unit: 'kWh/t',
|
|
|
+ color: '#eb0ce2',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '昨日吨水电耗',
|
|
|
+ data:
|
|
|
+ typeof power.yesterday_energy_water == 'string'
|
|
|
+ ? power.yesterday_energy_water
|
|
|
+ : power.yesterday_energy_water?.toFixed(2),
|
|
|
+ unit: 'kWh/t',
|
|
|
+ color: '#eb8c0c',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '环比增长',
|
|
|
+ data:
|
|
|
+ typeof power.energy_water_change == 'string'
|
|
|
+ ? power.energy_water_change
|
|
|
+ : power.energy_water_change?.toFixed(2),
|
|
|
+ unit: '%',
|
|
|
+ icon: power.energy_water_change >= 0 ? 1 : 2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '当日用电',
|
|
|
+ data: power.today_energy,
|
|
|
+ unit: 'kWh',
|
|
|
+ color: '#eb0ce2',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '昨日用电',
|
|
|
+ data: power.yesterday_energy,
|
|
|
+ unit: 'kWh',
|
|
|
+ color: '#eb8c0c',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '环比增长',
|
|
|
+ data:
|
|
|
+ typeof power.energy_change == 'string'
|
|
|
+ ? power.energy_change
|
|
|
+ : power.energy_change?.toFixed(2),
|
|
|
+ unit: '%',
|
|
|
+ icon: power.energy_change >= 0 ? 1 : 2,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ }, [energyData]);
|
|
|
+
|
|
|
+ const loading = useMemo(() => allFacLoading, [allFacLoading]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <PageContent closeable={false}>
|
|
|
+ <PageTitle returnable>能耗数据</PageTitle>
|
|
|
+ <Spin spinning={loading}>
|
|
|
+ <div className={styles.infoContainer}>
|
|
|
+ <div>
|
|
|
+ <SubTitle title="全厂概览" />
|
|
|
+ <div style={{ display: 'flex' }}>
|
|
|
+ {allFactory.map((item, index) => (
|
|
|
+ <DataCard key={`all_${index}`} {...item} type={4} />
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <SubTitle title="用电概况" />
|
|
|
+ <div style={{ display: 'flex', flexWrap: 'wrap' }}>
|
|
|
+ {powerData.map((item, index) => (
|
|
|
+ <DataCard key={`power_${index}`} {...item} type={3} />
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <SubTitle title="吨水电耗" />
|
|
|
+ <div style={{ height: '3rem' }}>
|
|
|
+ {chartData && allFactoryData && (
|
|
|
+ <ChartModule
|
|
|
+ yName={allFactoryData?.energy_water_unit || 'kWh'}
|
|
|
+ xData={chartData.xData}
|
|
|
+ dataList={chartData.dataList}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <SubTitle title="电量" />
|
|
|
+ <div style={{ height: '3rem' }}>
|
|
|
+ {electricChartData && allFactoryData && (
|
|
|
+ <ChartModule
|
|
|
+ yName={allFactoryData?.energy_unit || 'kWh/t'}
|
|
|
+ xData={electricChartData.xData}
|
|
|
+ dataList={electricChartData.dataList}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Spin>
|
|
|
+ </PageContent>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default EnergyCostDetail;
|
|
|
+
|
|
|
+const DataCard = ({ title, data, unit, icon, color, type }) => {
|
|
|
+ const width = Math.floor(100 / type - 2) + '%';
|
|
|
+ return (
|
|
|
+ <div style={{ width }} className={`${styles.itemContent} card-box`}>
|
|
|
+ <div style={{ fontSize: '0.26rem' }}>{title}</div>
|
|
|
+ <div style={{ position: 'relative' }}>
|
|
|
+ <span
|
|
|
+ style={{ color: !icon ? color : icon === 1 ? 'red' : '#50bb0a' }}
|
|
|
+ className={styles.data}
|
|
|
+ >
|
|
|
+ {data}
|
|
|
+ </span>
|
|
|
+ {unit}
|
|
|
+ {icon === 1 && (
|
|
|
+ <ArrowUpOutlined
|
|
|
+ style={{
|
|
|
+ height: '0.2rem',
|
|
|
+ color: 'red',
|
|
|
+ position: 'absolute',
|
|
|
+ fontSize: '0.34rem',
|
|
|
+ right: '0.4rem',
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {icon === 2 && (
|
|
|
+ <ArrowDownOutlined
|
|
|
+ style={{
|
|
|
+ height: '0.2rem',
|
|
|
+ color: '#50bb0a',
|
|
|
+ position: 'absolute',
|
|
|
+ fontSize: '0.36rem',
|
|
|
+ right: '0.4rem',
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const SubTitle = ({ title }) => {
|
|
|
+ return (
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ display: 'flex',
|
|
|
+ justifyContent: 'flex-start',
|
|
|
+ alignItems: 'center',
|
|
|
+ marginBottom: '0.2rem',
|
|
|
+ fontSize: '0.28rem',
|
|
|
+ fontWeight: '600',
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ width: '0.15rem',
|
|
|
+ height: '0.15rem',
|
|
|
+ background: '#0139f1',
|
|
|
+ marginRight: '0.1rem',
|
|
|
+ borderRadius: '0.16rem',
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ {title}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|