|
@@ -0,0 +1,822 @@
|
|
|
+import PageContent from '@/components/PageContent';
|
|
|
+import {
|
|
|
+ queryBackwash,
|
|
|
+ queryBackwashList,
|
|
|
+ queryDesignNob,
|
|
|
+ queryDesignNobList,
|
|
|
+ queryDesignWash,
|
|
|
+ queryDesignWashList,
|
|
|
+ queryDrug,
|
|
|
+ queryDrugList,
|
|
|
+ queryMembrane,
|
|
|
+ queryMembraneList,
|
|
|
+ queryPump,
|
|
|
+ queryPumpList,
|
|
|
+} from '@/services/SmartOps';
|
|
|
+import { UnityAction } from '@/utils/utils';
|
|
|
+import {
|
|
|
+ useNavigate,
|
|
|
+ useParams,
|
|
|
+ useRequest,
|
|
|
+ useSearchParams,
|
|
|
+} from '@umijs/max';
|
|
|
+import { Button, Collapse, DatePicker, Empty, Form, Spin, Tabs } from 'antd';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import * as echarts from 'echarts';
|
|
|
+import { useEffect, useMemo, useRef, useState } from 'react';
|
|
|
+import styles from './WorkAnalysisDetail.less';
|
|
|
+
|
|
|
+const TYPE = {
|
|
|
+ td_uf: {
|
|
|
+ name: '超滤膜组',
|
|
|
+ device: (params) => queryMembraneList({ ...params, type: 'uf' }),
|
|
|
+ chart: (params) => queryMembrane({ ...params, type: 'uf' }),
|
|
|
+ },
|
|
|
+ td_mf: {
|
|
|
+ name: '微滤膜',
|
|
|
+ device: (params) => queryMembraneList({ ...params, type: 'mf' }),
|
|
|
+ chart: (params) => queryMembrane({ ...params, type: 'mf' }),
|
|
|
+ },
|
|
|
+ td_nf: {
|
|
|
+ name: '纳滤膜',
|
|
|
+ device: (params) => queryMembraneList({ ...params, type: 'nf' }),
|
|
|
+ chart: (params) => queryMembrane({ ...params, type: 'nf' }),
|
|
|
+ },
|
|
|
+ td_ro: {
|
|
|
+ name: '反渗透膜',
|
|
|
+ device: (params) => queryMembraneList({ ...params, type: 'ro' }),
|
|
|
+ chart: (params) => queryMembrane({ ...params, type: 'ro' }),
|
|
|
+ },
|
|
|
+ tdr_pac: {
|
|
|
+ name: '絮凝剂投加',
|
|
|
+ device: (params) => queryDrugList({ ...params, type: 'pac' }),
|
|
|
+ chart: (params) => queryDrug({ ...params, type: 'pac' }),
|
|
|
+ },
|
|
|
+ tdr_hci: {
|
|
|
+ name: 'HCI投加',
|
|
|
+ device: (params) => queryDrugList({ ...params, type: 'hci' }),
|
|
|
+ chart: (params) => queryDrug({ ...params, type: 'hci' }),
|
|
|
+ },
|
|
|
+ tdr_nob: {
|
|
|
+ name: '非氧化杀菌剂投加',
|
|
|
+ device: (params) => queryDrugList({ ...params, type: 'nob' }),
|
|
|
+ chart: (params) => queryDrug({ ...params, type: 'nob' }),
|
|
|
+ },
|
|
|
+ tt_backwash: {
|
|
|
+ name: '反冲洗记录',
|
|
|
+ device: queryBackwashList,
|
|
|
+ chart: queryBackwash,
|
|
|
+ },
|
|
|
+ tt_wash: {
|
|
|
+ name: '大水量冲洗记录',
|
|
|
+ device: queryDesignWashList,
|
|
|
+ chart: queryDesignWash,
|
|
|
+ },
|
|
|
+ tt_nob: {
|
|
|
+ name: '非氧化杀菌记录',
|
|
|
+ device: queryDesignNobList,
|
|
|
+ chart: queryDesignNob,
|
|
|
+ },
|
|
|
+ td_pump_nf: {
|
|
|
+ name: '纳滤水泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_nf' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_nf' }),
|
|
|
+ },
|
|
|
+ td_pump_uf: {
|
|
|
+ name: '超滤水泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_uf' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_uf' }),
|
|
|
+ },
|
|
|
+ td_pump_ro: {
|
|
|
+ // td_pump: {
|
|
|
+ name: '反渗透水泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_ro' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_ro' }),
|
|
|
+ },
|
|
|
+ td_pump_mf: {
|
|
|
+ name: '微滤水泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_mf' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_mf' }),
|
|
|
+ },
|
|
|
+ td_pump_nf_drug: {
|
|
|
+ name: '加药泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_nf_drug' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_nf_drug' }),
|
|
|
+ },
|
|
|
+ td_pump_uf_drug: {
|
|
|
+ name: '加药泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_uf_drug' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_uf_drug' }),
|
|
|
+ },
|
|
|
+ td_pump_ro_drug: {
|
|
|
+ // td_pump: {
|
|
|
+ name: '加药泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_ro_drug' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_ro_drug' }),
|
|
|
+ },
|
|
|
+ td_pump_mf_drug: {
|
|
|
+ name: '加药泵',
|
|
|
+ device: (params) => queryPumpList({ ...params, stage: 'td_pump_mf_drug' }),
|
|
|
+ chart: (params) => queryPump({ ...params, stage: 'td_pump_mf_drug' }),
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+const { TabPane } = Tabs;
|
|
|
+const { Panel } = Collapse;
|
|
|
+const { RangePicker } = DatePicker;
|
|
|
+
|
|
|
+function WorkAnalysisDetail(props) {
|
|
|
+ const navigate = useNavigate();
|
|
|
+ const { projectId } = useParams();
|
|
|
+ const [searchParams, setSearchParams] = useSearchParams();
|
|
|
+ const eTime = searchParams.get('eTime');
|
|
|
+
|
|
|
+ const workAnalysis = useMemo(() => {
|
|
|
+ let workAnalysis = {
|
|
|
+ technologys: [],
|
|
|
+ optimizationItems: {},
|
|
|
+ optimizationNumber: 0,
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ workAnalysis = JSON.parse(sessionStorage.workAnalysis);
|
|
|
+ workAnalysis.technologys = workAnalysis.technologys.filter((item) => {
|
|
|
+ if (!TYPE[item]) console.log(item);
|
|
|
+ return TYPE[item];
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+ return workAnalysis;
|
|
|
+ }, []);
|
|
|
+ const {
|
|
|
+ technologys,
|
|
|
+ optimizationItems,
|
|
|
+ optimizationNumber,
|
|
|
+ parentName,
|
|
|
+ name,
|
|
|
+ } = workAnalysis;
|
|
|
+
|
|
|
+ const [active, setActive] = useState(technologys[0]);
|
|
|
+ const [current, setCurrent] = useState([]);
|
|
|
+ const [selected, setSelected] = useState('');
|
|
|
+
|
|
|
+ const handleBackClick = () => {
|
|
|
+ UnityAction.sendMsg('ProcessAnalysisDetailBack');
|
|
|
+ navigate(-1);
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ UnityAction.addEventListener('SynDev', (deviceCode) =>
|
|
|
+ setCurrent([deviceCode]),
|
|
|
+ );
|
|
|
+ return () => UnityAction.off('SynDev');
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <PageContent>
|
|
|
+ <div className={styles.page}>
|
|
|
+ <Button type="primary" onClick={handleBackClick}>
|
|
|
+ 返回
|
|
|
+ </Button>
|
|
|
+ <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}>
|
|
|
+ <ListContent
|
|
|
+ tab={active}
|
|
|
+ current={active == item ? current : []}
|
|
|
+ setCurrent={setCurrent}
|
|
|
+ selected={selected}
|
|
|
+ setSelected={setSelected}
|
|
|
+ name={name}
|
|
|
+ active={item}
|
|
|
+ optimizationItems={optimizationItems}
|
|
|
+ projectId={projectId}
|
|
|
+ eTime={eTime}
|
|
|
+ />
|
|
|
+ </TabPane>
|
|
|
+ ))}
|
|
|
+ </Tabs>
|
|
|
+ </div>
|
|
|
+ </PageContent>
|
|
|
+ );
|
|
|
+}
|
|
|
+const ListContent = (props) => {
|
|
|
+ const {
|
|
|
+ tab,
|
|
|
+ projectId,
|
|
|
+ active,
|
|
|
+ optimizationItems = {},
|
|
|
+ name,
|
|
|
+ current,
|
|
|
+ setCurrent,
|
|
|
+ eTime,
|
|
|
+ selected,
|
|
|
+ setSelected,
|
|
|
+ } = props;
|
|
|
+
|
|
|
+ const { data, loading, run } = useRequest(
|
|
|
+ () => {
|
|
|
+ let params = {
|
|
|
+ page: 1,
|
|
|
+ page_size: 99999,
|
|
|
+ project_id: projectId,
|
|
|
+ };
|
|
|
+ return TYPE[active]?.device(params);
|
|
|
+ },
|
|
|
+ {
|
|
|
+ formatResult: (res) => {
|
|
|
+ return res.list;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (tab == active && data) {
|
|
|
+ sendMsg();
|
|
|
+ }
|
|
|
+ UnityAction.on('SynDev', selectedItem);
|
|
|
+ return () => UnityAction.off('SynDev');
|
|
|
+ }, [tab, active, data]);
|
|
|
+
|
|
|
+ const selectedItem = (e) => {
|
|
|
+ setSelected(e);
|
|
|
+ setCurrent([...current, e]);
|
|
|
+ };
|
|
|
+
|
|
|
+ //通知unity切换tab发送tab数据
|
|
|
+ const sendMsg = () => {
|
|
|
+ const SysDevs = {};
|
|
|
+ data?.forEach((item) => {
|
|
|
+ SysDevs[item.device_code] =
|
|
|
+ optimizationItems?.[`${active}:${item.device_code}`] || 0;
|
|
|
+ });
|
|
|
+ const msg = { SysName: name, SysDevs };
|
|
|
+ UnityAction.sendMsg('ProcessAnalysisDetail', JSON.stringify(msg));
|
|
|
+ };
|
|
|
+
|
|
|
+ const activeKeys = useMemo(() => {
|
|
|
+ if (!data) return [];
|
|
|
+ return current.filter((deviceCode) =>
|
|
|
+ data.some((item) => item.device_code == deviceCode),
|
|
|
+ );
|
|
|
+ }, [data, current]);
|
|
|
+
|
|
|
+ const handleClick = (keys) => {
|
|
|
+ // 判断是开启还是关闭
|
|
|
+ // 设置当前选中行
|
|
|
+ if (keys.length > current.length) {
|
|
|
+ const code = keys[keys.length - 1];
|
|
|
+ UnityAction.sendMsg('SynDev', code);
|
|
|
+ setSelected(code);
|
|
|
+ } else if (current.length > 0) {
|
|
|
+ const item = current.find(
|
|
|
+ (item) => keys.findIndex((cur) => cur == item) == -1,
|
|
|
+ );
|
|
|
+ setSelected(item);
|
|
|
+ }
|
|
|
+ setCurrent(keys);
|
|
|
+ };
|
|
|
+
|
|
|
+ const getExtra = (deviceCode) => {
|
|
|
+ if (optimizationItems?.[`${active}:${deviceCode}`]) {
|
|
|
+ return <span style={{ color: '#F5A623' }}>可优化</span>;
|
|
|
+ } else {
|
|
|
+ return <span style={{ color: '#11EEE4' }}>暂无优化</span>;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const getStyle = (code) => {
|
|
|
+ return code == selected ? { backgroundColor: '#1b73c5' } : null;
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Spin spinning={loading} style={{ minHeight: 300 }}>
|
|
|
+ <Collapse
|
|
|
+ activeKey={current}
|
|
|
+ expandIconPosition="right"
|
|
|
+ onChange={handleClick}
|
|
|
+ >
|
|
|
+ {data?.map((item) => (
|
|
|
+ <Panel
|
|
|
+ style={getStyle(item.device_code)}
|
|
|
+ header={`${item.device_name}(${item.device_code})`}
|
|
|
+ key={item.device_code}
|
|
|
+ extra={getExtra(item.device_code)}
|
|
|
+ >
|
|
|
+ <ChartContent
|
|
|
+ active={active}
|
|
|
+ deviceCode={item.device_code}
|
|
|
+ projectId={projectId}
|
|
|
+ eTime={eTime}
|
|
|
+ />
|
|
|
+ </Panel>
|
|
|
+ ))}
|
|
|
+ </Collapse>
|
|
|
+ </Spin>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const ChartContent = (props) => {
|
|
|
+ const { deviceCode, projectId, active, eTime } = props;
|
|
|
+ const [visible, setVisible] = useState(false);
|
|
|
+ const [params, setParams] = useState(null);
|
|
|
+ const [time, setTime] = useState([
|
|
|
+ dayjs(eTime).subtract(10, 'minute'),
|
|
|
+ dayjs(eTime),
|
|
|
+ ]);
|
|
|
+ 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'),
|
|
|
+ });
|
|
|
+ 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 optimization = useMemo(() => {
|
|
|
+ const result = data?.list?.filter((item) => item.optimization);
|
|
|
+ if (result?.length > 0) {
|
|
|
+ const lastItem = result[result.length - 1];
|
|
|
+ const arr = [
|
|
|
+ 'ro_wash_interval',
|
|
|
+ 'peb_interval',
|
|
|
+ 'pac_fr',
|
|
|
+ 'ro_nob_interva',
|
|
|
+ ];
|
|
|
+ const valueList = Object.entries(lastItem.optimization)
|
|
|
+ .map(([key, item]) => {
|
|
|
+ if (!arr.includes(key)) return null;
|
|
|
+ return item.remark;
|
|
|
+ })
|
|
|
+ .filter((item) => item);
|
|
|
+ if (valueList.length == 0) return '';
|
|
|
+ return `【${lastItem.c_time}】${valueList.join(',')}`;
|
|
|
+ }
|
|
|
+ return '';
|
|
|
+ }, [data]);
|
|
|
+
|
|
|
+ const searchTime = (type) => {
|
|
|
+ let time = [dayjs().startOf(type), dayjs()];
|
|
|
+ onSearch?.(time);
|
|
|
+ };
|
|
|
+
|
|
|
+ const onSearch = (time) => {
|
|
|
+ console.log(time);
|
|
|
+ if (time && time.length == 2) {
|
|
|
+ let s_time, e_time;
|
|
|
+ s_time = time[0].format('YYYY-MM-DD HH:mm:ss');
|
|
|
+ e_time = time[1].format('YYYY-MM-DD HH:mm:ss');
|
|
|
+
|
|
|
+ timerRef.current = { s_time, e_time };
|
|
|
+ // setTime(time);
|
|
|
+ run();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ chartRef.current = echarts.init(domRef.current);
|
|
|
+
|
|
|
+ return () => {
|
|
|
+ chartRef.current.dispose();
|
|
|
+ };
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ 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>
|
|
|
+ </div>
|
|
|
+ </Form>
|
|
|
+ <Spin spinning={loading}>
|
|
|
+ {!data?.list && <Empty style={{ marginBottom: 40 }} />}
|
|
|
+ <div
|
|
|
+ ref={domRef}
|
|
|
+ style={{ height: 300, display: !data?.list ? 'none' : 'block' }}
|
|
|
+ />
|
|
|
+ </Spin>
|
|
|
+
|
|
|
+ {optimization && (
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ fontSize: 22,
|
|
|
+ color: '#fff',
|
|
|
+ textIndent: 30,
|
|
|
+ padding: '10px 0',
|
|
|
+ flexShrink: 1,
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {optimization}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* <MembraneModal visible={visible} onCancel={() => setVisible(false)} params={params} /> */}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+function getOption(data = [], active) {
|
|
|
+ let formatter,
|
|
|
+ yAxisName = '',
|
|
|
+ y2AxisName = '',
|
|
|
+ series = [],
|
|
|
+ xAxis = [];
|
|
|
+ var data1 = [],
|
|
|
+ data2 = [],
|
|
|
+ data3 = [],
|
|
|
+ data4 = [];
|
|
|
+ switch (active) {
|
|
|
+ case 'tt_backwash':
|
|
|
+ yAxisName = '清洗周期/Min';
|
|
|
+ formatter = (params) => {
|
|
|
+ let item = data[params[0].dataIndex];
|
|
|
+ let content = '';
|
|
|
+ if (item.bw_type == 1) {
|
|
|
+ // PEB
|
|
|
+ content += 'PEB 反洗开始时间:' + item.peb_st;
|
|
|
+ content += '<br />PEB 反洗结束时间:' + item.peb_et;
|
|
|
+ } else {
|
|
|
+ // CEB
|
|
|
+ content += 'CEB 反洗开始时间:' + item.ceb_st;
|
|
|
+ content += '<br />CEB 反洗结束时间:' + item.ceb_et;
|
|
|
+ content += '<br />CEB 清洗剂浓度' + item.ceb_ppm;
|
|
|
+ }
|
|
|
+ return content;
|
|
|
+ };
|
|
|
+ data?.forEach((item) => {
|
|
|
+ if (item.bw_type == 1) {
|
|
|
+ // 实际冲洗
|
|
|
+ data1.push(Math.ceil(item.peb_interval / 60));
|
|
|
+ // TODO:冲洗
|
|
|
+ data2.push(Math.ceil(item.peb_interval / 60));
|
|
|
+ data3.push(null);
|
|
|
+ data4.push(null);
|
|
|
+ xAxis.push(dayjs(item.peb_st).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ } else {
|
|
|
+ data1.push(null);
|
|
|
+ data2.push(null);
|
|
|
+ data3.push(Math.ceil(item.peb_interval / 60));
|
|
|
+ // TODO:模拟冲洗
|
|
|
+ data4.push(Math.ceil(item.peb_interval / 60));
|
|
|
+ xAxis.push(dayjs(item.ceb_st).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '物理实际冲洗',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '物理模拟冲洗',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '化学实际冲洗',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '化学模拟冲洗',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data4,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ case 'tt_wash':
|
|
|
+ yAxisName = '清洗周期/Min';
|
|
|
+ formatter = (params) => {
|
|
|
+ let item = data[params[0].dataIndex];
|
|
|
+ let content = '';
|
|
|
+ content += '反洗开始时间:' + item.st;
|
|
|
+ content += '<br />反洗结束时间:' + item.et;
|
|
|
+ return content;
|
|
|
+ };
|
|
|
+ data?.forEach((item) => {
|
|
|
+ // 实际冲洗
|
|
|
+ data1.push(Math.ceil(item.interval / 60));
|
|
|
+ // TODO:模拟冲洗
|
|
|
+ data2.push(Math.ceil(item.interval / 60));
|
|
|
+ xAxis.push(dayjs(item.st).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '实际冲洗',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '模拟冲洗',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data2,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ case 'tt_nob':
|
|
|
+ yAxisName = '杀菌周期/Min';
|
|
|
+ formatter = (params) => {
|
|
|
+ let item = data[params[0].dataIndex];
|
|
|
+ let content = '';
|
|
|
+ content += '杀菌开始时间:' + (item.st || '-');
|
|
|
+ content += '<br />杀菌结束时间:' + (item.et || '-');
|
|
|
+ return content;
|
|
|
+ };
|
|
|
+ var data1 = [],
|
|
|
+ data2 = [];
|
|
|
+ data?.forEach((item) => {
|
|
|
+ // 实际冲洗
|
|
|
+ data1.push(Math.ceil(item.interval / 60));
|
|
|
+ // TODO:模拟冲洗
|
|
|
+ data2.push(Math.ceil(item.interval / 60));
|
|
|
+ xAxis.push(dayjs(item.st).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '实际',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '模拟',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data2,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ case 'tdr_hci':
|
|
|
+ case 'tdr_nob':
|
|
|
+ case 'tdr_pac':
|
|
|
+ yAxisName = '投加量';
|
|
|
+ data?.forEach((item) => {
|
|
|
+ // 实际冲洗
|
|
|
+ data1.push(Math.ceil(item.fr / 60));
|
|
|
+ // TODO:模拟冲洗
|
|
|
+ data2.push(Math.ceil(item.fcoa / 60));
|
|
|
+ xAxis.push(dayjs(item.c_time).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '实际物理投加量',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '理论物理投加量',
|
|
|
+ type: 'bar',
|
|
|
+ barMaxWidth: '20px',
|
|
|
+ data: data2,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'td_uf':
|
|
|
+ case 'td_mf':
|
|
|
+ case 'td_nf':
|
|
|
+ yAxisName = '渗透率';
|
|
|
+ data?.forEach((item) => {
|
|
|
+ // 实际跨膜压差
|
|
|
+ data1.push(item.std_tmp);
|
|
|
+ // 模拟跨膜压差
|
|
|
+ data2.push(item.std_permeability);
|
|
|
+ xAxis.push(dayjs(item.c_time).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '标准跨膜压差',
|
|
|
+ type: 'line',
|
|
|
+ data: data1,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '标准渗透率',
|
|
|
+ type: 'line',
|
|
|
+ data: data2,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ case 'td_ro':
|
|
|
+ yAxisName = '跨膜压差';
|
|
|
+ data?.forEach((item) => {
|
|
|
+ // 实际跨膜压差
|
|
|
+ data1.push(item.extend['1st_Stage_DP']);
|
|
|
+ data2.push(item.extend['2nd_Stage_DP']);
|
|
|
+ // 模拟跨膜压差
|
|
|
+ data3.push(item.stabilize_extend['1st_Stage_DP']);
|
|
|
+ data4.push(item.stabilize_extend['2nd_Stage_DP']);
|
|
|
+ xAxis.push(dayjs(item.c_time).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '实际一段跨膜压差',
|
|
|
+ type: 'line',
|
|
|
+ data: data1,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '实际二段跨膜压差',
|
|
|
+ type: 'line',
|
|
|
+ data: data2,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '模拟一段跨膜压差',
|
|
|
+ type: 'line',
|
|
|
+ data: data3,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '模拟二段跨膜压差',
|
|
|
+ type: 'line',
|
|
|
+ data: data4,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ case 'td_pump_nf':
|
|
|
+ case 'td_pump_uf':
|
|
|
+ case 'td_pump_ro':
|
|
|
+ // case 'td_pump':
|
|
|
+ case 'td_pump_mf':
|
|
|
+ case 'td_pump_nf_drug':
|
|
|
+ case 'td_pump_mf_drug':
|
|
|
+ case 'td_pump_mf_drug':
|
|
|
+ case 'td_pump_mf_drug':
|
|
|
+ yAxisName = '频率 Hz';
|
|
|
+ y2AxisName = '电流 A';
|
|
|
+ data?.forEach((item) => {
|
|
|
+ // 实际跨膜压差
|
|
|
+ data1.push(item.frequency);
|
|
|
+ data2.push(item.current);
|
|
|
+ xAxis.push(dayjs(item.c_time).format('YYYY-MM-DD HH:mm:ss'));
|
|
|
+ });
|
|
|
+ series = [
|
|
|
+ {
|
|
|
+ name: '频率',
|
|
|
+ type: 'line',
|
|
|
+ data: data1,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '电流',
|
|
|
+ type: 'line',
|
|
|
+ data: data2,
|
|
|
+ yAxisIndex: 1,
|
|
|
+ showSymbol: false,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 过滤失效数据
|
|
|
+ xAxis.forEach((time, index) => {
|
|
|
+ if (time === 'Invalid date') {
|
|
|
+ xAxis[index] = null;
|
|
|
+ data1[index] = null;
|
|
|
+ data2[index] = null;
|
|
|
+ data3[index] = null;
|
|
|
+ data4[index] = null;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ xAxis = xAxis.filter((item) => item);
|
|
|
+ data1 = data1.filter((item) => !isNaN(item));
|
|
|
+ data2 = data2.filter((item) => !isNaN(item));
|
|
|
+ data3 = data3.filter((item) => !isNaN(item));
|
|
|
+ data4 = data4.filter((item) => !isNaN(item));
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ color: ['#FFC800', '#30EDFD', '#4096ff', '#ff4d4f', '#ffa940'],
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'shadow',
|
|
|
+ },
|
|
|
+ formatter,
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ textStyle: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 18,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ bottom: '3%',
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: xAxis,
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: '#fff',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: '#fff',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: '#fff',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ name: yAxisName,
|
|
|
+ type: 'value',
|
|
|
+ boundaryGap: [0, 0.01],
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: '#fff',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ splitNumber: 5,
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: '#fff',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: '#fff',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ series,
|
|
|
+ };
|
|
|
+ if (y2AxisName) {
|
|
|
+ let y1 = option.yAxis;
|
|
|
+ let y2 = JSON.parse(JSON.stringify(y1));
|
|
|
+ y2 = { ...y2, name: y2AxisName };
|
|
|
+ option.yAxis = [y1, y2];
|
|
|
+ }
|
|
|
+ console.log(option);
|
|
|
+ return option;
|
|
|
+}
|
|
|
+export default WorkAnalysisDetail;
|