|
@@ -1,4 +1,6 @@
|
|
|
import PageContent from '@/components/PageContent';
|
|
|
+import PageTitle from '@/components/PageTitle';
|
|
|
+import TabsContent from '@/components/TabsContent';
|
|
|
import {
|
|
|
queryBackwash,
|
|
|
queryBackwashList,
|
|
@@ -20,7 +22,7 @@ import {
|
|
|
useRequest,
|
|
|
useSearchParams,
|
|
|
} from '@umijs/max';
|
|
|
-import { Button, Collapse, DatePicker, Empty, Form, Spin, Tabs } from 'antd';
|
|
|
+import { Collapse, DatePicker, Empty, Form, Spin } from 'antd';
|
|
|
import dayjs from 'dayjs';
|
|
|
import * as echarts from 'echarts';
|
|
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
@@ -121,9 +123,22 @@ const TYPE = {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-const { TabPane } = Tabs;
|
|
|
const { Panel } = Collapse;
|
|
|
const { RangePicker } = DatePicker;
|
|
|
+const DateTab = [
|
|
|
+ {
|
|
|
+ value: 'day',
|
|
|
+ label: '今日',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'week',
|
|
|
+ label: '本周',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'month',
|
|
|
+ label: '本月',
|
|
|
+ },
|
|
|
+];
|
|
|
|
|
|
function WorkAnalysisDetail(props) {
|
|
|
const navigate = useNavigate();
|
|
@@ -173,26 +188,23 @@ function WorkAnalysisDetail(props) {
|
|
|
}, []);
|
|
|
|
|
|
return (
|
|
|
- <PageContent>
|
|
|
- <div className={styles.page}>
|
|
|
- <Button type="primary" onClick={handleBackClick}>
|
|
|
- 返回
|
|
|
- </Button>
|
|
|
+ <PageContent closeable={false}>
|
|
|
+ <PageTitle returnable>返回</PageTitle>
|
|
|
+ <div className={styles.pageContent}>
|
|
|
<div className={styles.title}>
|
|
|
{parentName}:{name}
|
|
|
<span>
|
|
|
{optimizationNumber > 0 && `${optimizationNumber}项待优化`}
|
|
|
</span>
|
|
|
</div>
|
|
|
- <Tabs
|
|
|
- activeKey={active}
|
|
|
- onChange={(key) => {
|
|
|
- setCurrent([]);
|
|
|
- setActive(key);
|
|
|
- }}
|
|
|
- >
|
|
|
- {technologys?.map((item) => (
|
|
|
- <TabPane key={item} tab={TYPE[item]?.name}>
|
|
|
+ <TabsContent
|
|
|
+ center={false}
|
|
|
+ small
|
|
|
+ defaultActiveKey={active}
|
|
|
+ items={technologys.map((item) => ({
|
|
|
+ label: TYPE[item]?.name,
|
|
|
+ key: item,
|
|
|
+ children: (
|
|
|
<ListContent
|
|
|
tab={active}
|
|
|
current={active == item ? current : []}
|
|
@@ -205,9 +217,13 @@ function WorkAnalysisDetail(props) {
|
|
|
projectId={projectId}
|
|
|
eTime={eTime}
|
|
|
/>
|
|
|
- </TabPane>
|
|
|
- ))}
|
|
|
- </Tabs>
|
|
|
+ ),
|
|
|
+ }))}
|
|
|
+ onChange={(key) => {
|
|
|
+ setCurrent([]);
|
|
|
+ setActive(key);
|
|
|
+ }}
|
|
|
+ ></TabsContent>
|
|
|
</div>
|
|
|
</PageContent>
|
|
|
);
|
|
@@ -237,7 +253,7 @@ const ListContent = (props) => {
|
|
|
},
|
|
|
{
|
|
|
formatResult: (res) => {
|
|
|
- return res.list;
|
|
|
+ return res.data.list;
|
|
|
},
|
|
|
},
|
|
|
);
|
|
@@ -312,7 +328,7 @@ const ListContent = (props) => {
|
|
|
<Panel
|
|
|
style={getStyle(item.device_code)}
|
|
|
header={`${item.device_name}(${item.device_code})`}
|
|
|
- key={item.device_code}
|
|
|
+ key={`${active}_${item.device_code}`}
|
|
|
extra={getExtra(item.device_code)}
|
|
|
>
|
|
|
<ChartContent
|
|
@@ -336,6 +352,7 @@ const ChartContent = (props) => {
|
|
|
dayjs(eTime).subtract(10, 'minute'),
|
|
|
dayjs(eTime),
|
|
|
]);
|
|
|
+ const [dateActive, setDateActive] = useState();
|
|
|
const timerRef = useRef({
|
|
|
s_time: time[0].format('YYYY-MM-DD HH:mm:ss'),
|
|
|
e_time: time[1].format('YYYY-MM-DD HH:mm:ss'),
|
|
@@ -343,26 +360,16 @@ const ChartContent = (props) => {
|
|
|
const domRef = useRef(null);
|
|
|
const chartRef = useRef(null);
|
|
|
|
|
|
- const { data, loading, run } = useRequest(
|
|
|
- () => {
|
|
|
- let params = {
|
|
|
- device_code: deviceCode,
|
|
|
- page: 1,
|
|
|
- page_size: 9999,
|
|
|
- project_id: projectId,
|
|
|
- ...timerRef.current,
|
|
|
- };
|
|
|
- return TYPE[active].chart(params);
|
|
|
- },
|
|
|
- {
|
|
|
- onSuccess(data) {
|
|
|
- chartRef.current.clear();
|
|
|
- let options = getOption(data.list, active);
|
|
|
- chartRef.current.setOption(options, true);
|
|
|
- chartRef.current.resize();
|
|
|
- },
|
|
|
- },
|
|
|
- );
|
|
|
+ const { data, loading, run } = useRequest(() => {
|
|
|
+ let params = {
|
|
|
+ device_code: deviceCode,
|
|
|
+ page: 1,
|
|
|
+ page_size: 9999,
|
|
|
+ project_id: projectId,
|
|
|
+ ...timerRef.current,
|
|
|
+ };
|
|
|
+ return TYPE[active].chart(params);
|
|
|
+ });
|
|
|
|
|
|
const optimization = useMemo(() => {
|
|
|
const result = data?.list?.filter((item) => item.optimization);
|
|
@@ -387,6 +394,7 @@ const ChartContent = (props) => {
|
|
|
}, [data]);
|
|
|
|
|
|
const searchTime = (type) => {
|
|
|
+ setDateActive(type);
|
|
|
let time = [dayjs().startOf(type), dayjs()];
|
|
|
onSearch?.(time);
|
|
|
};
|
|
@@ -405,56 +413,58 @@ const ChartContent = (props) => {
|
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
|
- chartRef.current = echarts.init(domRef.current);
|
|
|
-
|
|
|
+ if (data && data.list && domRef.current) {
|
|
|
+ chartRef.current = echarts.init(domRef.current);
|
|
|
+ chartRef.current.clear();
|
|
|
+ let options = getOption(data.list, active);
|
|
|
+ chartRef.current.setOption(options, true);
|
|
|
+ chartRef.current.resize();
|
|
|
+ }
|
|
|
return () => {
|
|
|
- chartRef.current.dispose();
|
|
|
+ if (chartRef.current) {
|
|
|
+ chartRef.current.dispose();
|
|
|
+ }
|
|
|
};
|
|
|
- }, []);
|
|
|
+ }, [data, domRef.current]);
|
|
|
|
|
|
return (
|
|
|
<div className={styles.chartBox}>
|
|
|
<Form layout="inline" className={styles.form}>
|
|
|
- <div>
|
|
|
- <Form.Item label="时间">
|
|
|
- <RangePicker
|
|
|
- style={{ width: 430 }}
|
|
|
- allowClear={false}
|
|
|
- defaultValue={time}
|
|
|
- // value={time}
|
|
|
- onChange={onSearch}
|
|
|
- format="YYYY-MM-DD HH:mm:ss"
|
|
|
- ></RangePicker>
|
|
|
- </Form.Item>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <Button
|
|
|
- type="primary"
|
|
|
- onClick={() => searchTime('day')}
|
|
|
- style={{ marginRight: 10 }}
|
|
|
- >
|
|
|
- 今日
|
|
|
- </Button>
|
|
|
- <Button
|
|
|
- type="primary"
|
|
|
- onClick={() => searchTime('week')}
|
|
|
- style={{ marginRight: 10 }}
|
|
|
- >
|
|
|
- 本周
|
|
|
- </Button>
|
|
|
- <Button type="primary" onClick={() => searchTime('month')}>
|
|
|
- 本月
|
|
|
- </Button>
|
|
|
+ <RangePicker
|
|
|
+ style={{ width: 250 }}
|
|
|
+ allowClear={false}
|
|
|
+ defaultValue={time}
|
|
|
+ // value={time}
|
|
|
+ onChange={onSearch}
|
|
|
+ format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ ></RangePicker>
|
|
|
+ <div className={styles.dateTabs}>
|
|
|
+ {DateTab.map((item) => (
|
|
|
+ <div
|
|
|
+ key={item.value}
|
|
|
+ className={`${styles.dateTabsItem} ${
|
|
|
+ item.value == dateActive ? styles.active : ''
|
|
|
+ }`}
|
|
|
+ onClick={() => searchTime(item.value)}
|
|
|
+ >
|
|
|
+ {item.label}
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
</div>
|
|
|
</Form>
|
|
|
- <Spin spinning={loading}>
|
|
|
- {!data?.list && <Empty style={{ marginBottom: 40 }} />}
|
|
|
- <div
|
|
|
- ref={domRef}
|
|
|
- style={{ height: 300, display: !data?.list ? 'none' : 'block' }}
|
|
|
- />
|
|
|
- </Spin>
|
|
|
-
|
|
|
+ <div>
|
|
|
+ <Spin spinning={loading}>{!data?.list && <Empty />}</Spin>
|
|
|
+ {data?.list && (
|
|
|
+ <div
|
|
|
+ ref={domRef}
|
|
|
+ style={{
|
|
|
+ height: 300,
|
|
|
+ width: '100%',
|
|
|
+ }}
|
|
|
+ onResize={() => console.log(1)}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
{optimization && (
|
|
|
<div
|
|
|
style={{
|
|
@@ -502,20 +512,21 @@ function getOption(data = [], active) {
|
|
|
return content;
|
|
|
};
|
|
|
data?.forEach((item) => {
|
|
|
+ let time = 0;
|
|
|
if (item.bw_type == 1) {
|
|
|
+ if (item.peb_et && item.peb_st) {
|
|
|
+ time = dayjs(item.peb_st).diff(dayjs(item.peb_et), 'minutes');
|
|
|
+ }
|
|
|
// 实际冲洗
|
|
|
- data1.push(Math.ceil(item.peb_interval / 60));
|
|
|
- // TODO:冲洗
|
|
|
- data2.push(Math.ceil(item.peb_interval / 60));
|
|
|
- data3.push(null);
|
|
|
- data4.push(null);
|
|
|
+ data1.push(time);
|
|
|
+ data2.push(null);
|
|
|
xAxis.push(dayjs(item.peb_st).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
} else {
|
|
|
+ if (item.ceb_st && item.ceb_et) {
|
|
|
+ time = dayjs(item.ceb_st).diff(dayjs(item.ceb_et), 'minutes');
|
|
|
+ }
|
|
|
data1.push(null);
|
|
|
- data2.push(null);
|
|
|
- data3.push(Math.ceil(item.peb_interval / 60));
|
|
|
- // TODO:模拟冲洗
|
|
|
- data4.push(Math.ceil(item.peb_interval / 60));
|
|
|
+ data2.push(time);
|
|
|
xAxis.push(dayjs(item.ceb_st).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
}
|
|
|
});
|
|
@@ -758,15 +769,20 @@ function getOption(data = [], active) {
|
|
|
axisPointer: {
|
|
|
type: 'shadow',
|
|
|
},
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 24,
|
|
|
+ },
|
|
|
formatter,
|
|
|
},
|
|
|
legend: {
|
|
|
textStyle: {
|
|
|
- color: '#fff',
|
|
|
- fontSize: 18,
|
|
|
+ // color: '#fff',
|
|
|
+ fontSize: 24,
|
|
|
},
|
|
|
+ type: 'scroll',
|
|
|
},
|
|
|
grid: {
|
|
|
+ top: 80,
|
|
|
left: '3%',
|
|
|
right: '4%',
|
|
|
bottom: '3%',
|
|
@@ -775,48 +791,49 @@ function getOption(data = [], active) {
|
|
|
xAxis: {
|
|
|
type: 'category',
|
|
|
data: xAxis,
|
|
|
- axisLine: {
|
|
|
- lineStyle: {
|
|
|
- color: '#fff',
|
|
|
- },
|
|
|
- },
|
|
|
- splitLine: {
|
|
|
- lineStyle: {
|
|
|
- color: '#fff',
|
|
|
- },
|
|
|
+ nameTextStyle: {
|
|
|
+ fontSize: 24,
|
|
|
},
|
|
|
axisLabel: {
|
|
|
- color: '#fff',
|
|
|
+ fontSize: 24,
|
|
|
},
|
|
|
},
|
|
|
yAxis: {
|
|
|
name: yAxisName,
|
|
|
type: 'value',
|
|
|
boundaryGap: [0, 0.01],
|
|
|
- axisLine: {
|
|
|
- lineStyle: {
|
|
|
- color: '#fff',
|
|
|
- },
|
|
|
- },
|
|
|
- splitNumber: 5,
|
|
|
- splitLine: {
|
|
|
- lineStyle: {
|
|
|
- color: '#fff',
|
|
|
- },
|
|
|
+ nameTextStyle: {
|
|
|
+ fontSize: 24,
|
|
|
},
|
|
|
axisLabel: {
|
|
|
- color: '#fff',
|
|
|
+ fontSize: 24,
|
|
|
},
|
|
|
+ splitNumber: 5,
|
|
|
},
|
|
|
series,
|
|
|
};
|
|
|
if (y2AxisName) {
|
|
|
let y1 = option.yAxis;
|
|
|
let y2 = JSON.parse(JSON.stringify(y1));
|
|
|
- y2 = { ...y2, name: y2AxisName };
|
|
|
+ y1.max = getMax(data1) || 1;
|
|
|
+ y1.interval = y1.max / 5;
|
|
|
+
|
|
|
+ y2.name = y2AxisName;
|
|
|
+ y2.max = getMax(data2) || 1;
|
|
|
+ y2.interval = y2.max / 5;
|
|
|
option.yAxis = [y1, y2];
|
|
|
}
|
|
|
console.log(option);
|
|
|
return option;
|
|
|
}
|
|
|
+
|
|
|
+function getMax(arr) {
|
|
|
+ const max = Math.max(...arr);
|
|
|
+ const exponent = Math.floor(Math.log10(max));
|
|
|
+ const base = Math.pow(10, exponent);
|
|
|
+ const remainder = max % base;
|
|
|
+ const maxRoundUp = max - remainder + base;
|
|
|
+ const maxFixed = maxRoundUp.toFixed(1); // 将最大值的小数位数限制为 1
|
|
|
+ return Number(maxFixed); // 将字符串转换为数字并返回
|
|
|
+}
|
|
|
export default WorkAnalysisDetail;
|