Browse Source

Merge branch 'develop' of http://120.55.44.4:10080/xujunjie/gt_client_pad into develop

Renxy 1 year ago
parent
commit
0f4199f953

+ 1 - 1
src/pages/SmartOps/Analysis.js

@@ -184,7 +184,7 @@ const Analysis = (props) => {
                   onClick: () => onSelectRow(record, index),
                 })}
                 pagination={false}
-                scroll={{ y: document.body.clientHeight - 542 }}
+                scroll={{ y: document.body.clientHeight - 730 }}
               />
             ),
           };

+ 3 - 1
src/pages/SmartOps/HistoryRecord.js

@@ -1,4 +1,5 @@
 import PageContent from '@/components/PageContent';
+import PageTitle from '@/components/PageTitle';
 import { getHistoryRecord } from '@/services/SmartOps';
 import { GetTokenFromUrl } from '@/utils/utils';
 import { useNavigate, useParams, useRequest } from '@umijs/max';
@@ -121,7 +122,7 @@ const HistoryRecord = (props) => {
     };
     switch (key) {
       case 'date':
-        if (value.length === 2) {
+        if (value?.length === 2) {
           tempParams.start_time = dayjs(value[0]).format('YYYY-MM-DD 00:00:00');
           tempParams.end_time = dayjs(value[1]).format('YYYY-MM-DD 23:59:59');
           console.log(
@@ -161,6 +162,7 @@ const HistoryRecord = (props) => {
 
   return (
     <PageContent>
+      <PageTitle returnable>历史记录</PageTitle>
       <Spin spinning={loading}>
         <div className={styles.searchContent}>
           {/* <Button

+ 3 - 1
src/pages/SmartOps/OperationRecord.js

@@ -5,6 +5,7 @@ import { Button, DatePicker, Select, Spin, Table } from 'antd';
 import dayjs from 'dayjs';
 import { useEffect, useState } from 'react';
 import styles from './index.less';
+import PageTitle from '@/components/PageTitle';
 
 const { RangePicker } = DatePicker;
 const { Option } = Select;
@@ -148,7 +149,7 @@ const OperationRecord = (props) => {
         tempParams[key] = value;
         break;
       case 'date':
-        if (value.length === 2) {
+        if (value?.length === 2) {
           tempParams.s_time = dayjs(value[0]).format('YYYY-MM-DD 00:00:00');
           tempParams.e_time = dayjs(value[1]).format('YYYY-MM-DD 23:59:59');
         } else {
@@ -181,6 +182,7 @@ const OperationRecord = (props) => {
 
   return (
     <PageContent>
+      <PageTitle returnable>操作记录</PageTitle>
       <Spin spinning={loading}>
         <div className={styles.searchContent}>
           {/* <Button

+ 133 - 116
src/pages/SmartOps/WorkAnalysisDetail.js

@@ -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;

+ 59 - 20
src/pages/SmartOps/WorkAnalysisDetail.less

@@ -1,13 +1,18 @@
 .title {
-  background-color: #6eb3f3;
   display: flex;
   justify-content: space-between;
   align-items: center;
-  font-size: 28px;
-  height: 66px;
-  color: #213b58;
-  margin: 1% 0;
-  padding: 0 12px;
+  font-size: 32px;
+  color: #4a90e2;
+  padding: 40px 20px;
+  margin-top: 52px;
+
+  background: #d9e7f9;
+  box-shadow: 0px 0px 12px 7px rgba(40, 94, 120, 0.03);
+  border-radius: 16px;
+  span {
+    color: #f5a623;
+  }
 }
 
 .form {
@@ -16,28 +21,56 @@
   align-items: center;
   justify-content: space-between;
 }
-
-.page {
+.dateTabs {
+  display: flex;
+  border: 1px solid #d5d5d5;
+  height: 60px;
+  .dateTabsItem {
+    width: 128px;
+    text-align: center;
+    cursor: pointer;
+    border-right: 1px solid #d5d5d5;
+    line-height: 60px;
+    font-size: 24px;
+    font-weight: 400;
+    color: #4a4a4a;
+    &:last-child {
+      border-right: none;
+    }
+    &.active {
+      background: #4a90e2;
+      color: #fff;
+    }
+  }
+}
+.chartBox {
+  padding-bottom: 40px;
+}
+.pageContent {
   :global {
+    .ant-collapse {
+      border: none !important;
+    }
     .ant-collapse > .ant-collapse-item {
-      border: 1px solid #329bfe;
-      background: #2466a4;
-      padding: 0 15px;
+      border-radius: 8px;
+      box-shadow: 0px 0px 8px 2px rgba(191, 191, 191, 0.2);
+      border: 1px solid #eee;
+      background: #4a4a4a;
+      padding: 0 30px;
       margin-bottom: 30px;
-      border-radius: 5px;
-      &.ant-collapse-item-active > .ant-collapse-header {
-        border-bottom: 1px solid #7a9dcd;
-      }
       > .ant-collapse-header {
         background: transparent;
-        color: #fff;
-        height: 62px;
-        font-size: 22px;
+        color: #4a4a4a;
+        height: 108px;
+        font-size: 28px;
         padding: 0;
         border-bottom: 1px solid transparent;
+        display: flex;
+        align-items: center;
         .ant-collapse-arrow {
-          font-size: 22px;
+          font-size: 28px;
           right: 0;
+          color: #c0c2c8;
         }
         .ant-collapse-extra {
           position: absolute;
@@ -45,9 +78,15 @@
         }
       }
     }
+    .ant-collapse-expand-icon {
+      order: 0 !important;
+    }
     .ant-collapse-content {
-      padding: 15px 0;
+      padding: 0;
       border-top: none;
     }
+    .ant-collapse-content-box {
+      padding: 0 !important;
+    }
   }
 }

+ 1 - 1
src/pages/SmartOps/components/VideoAnalysis.js

@@ -41,7 +41,7 @@ function VideoAnalysis(props) {
       <div
         id="videoContent"
         className={styles.page}
-        style={{ height: 'calc(100vh - 422px)', overflow: 'auto' }}
+        style={{ height: 'calc(100vh - 580px)', overflow: 'auto' }}
       >
         {data?.list?.length > 0 ? (
           data?.list?.map((item) => (

+ 3 - 3
src/pages/SmartOps/components/WorkAnalysis.js

@@ -18,9 +18,9 @@ function WorkAnalysis(props) {
   };
   return (
     <Spin spinning={loading}>
-      <div style={{ height: 'calc(100vh - 422px)', overflow: 'auto' }}>
+      <div style={{ height: 'calc(100vh - 580px)', overflow: 'auto' }}>
         {project_categorys?.map((item) => (
-          <div className={styles.box} key={item.type}>
+          <div className={`${styles.box} card-box`} key={item.type}>
             <div className={styles.title}>{item.name}</div>
             <ul className={styles.list}>
               {item.childs?.map((cItem) => (
@@ -28,7 +28,7 @@ function WorkAnalysis(props) {
                   <div className={styles.listTitle}>{cItem.name}</div>
                   <div className={styles.btn} onClick={() => toDetail(cItem)}>
                     {cItem.optimizationNumber == 0 ? (
-                      <span style={{ color: '#11EEE4' }}>暂无优化</span>
+                      <span style={{ color: '#12CEB3' }}>暂无优化</span>
                     ) : (
                       <span style={{ color: '#F5A623' }}>
                         可优化({cItem.optimizationNumber})

+ 11 - 10
src/pages/SmartOps/components/WorkAnalysis.less

@@ -1,14 +1,14 @@
 .box {
-  background: #064779;
-  padding: 22px;
   border-radius: 5px;
   padding-bottom: 5px;
-  margin-bottom: 16px;
+  margin-bottom: 25px;
 }
 .title {
-  font-size: 28px;
-  color: #329bfe;
-  line-height: 38px;
+  font-size: 30px;
+  color: #4a90e2;
+  line-height: 40px;
+  padding-left: 30px;
+  padding-top: 36px;
 }
 .list {
   margin: 0;
@@ -18,15 +18,16 @@
     display: flex;
     justify-content: space-between;
     align-items: center;
-    font-size: 24px;
-    border-bottom: 1px solid #2a6fa3;
-    padding: 15px 0;
+    font-size: 26px;
+    border-bottom: 1px solid #dbdbdb;
+    padding: 20px 0;
+    padding-left: 38px;
     &:last-child {
       border-bottom: none;
     }
   }
   .listTitle {
-    color: #fff;
+    color: #4a4a4a;
   }
   .btn {
     cursor: pointer;

+ 4 - 4
src/pages/SmartOps/index.js

@@ -15,7 +15,7 @@ import {
   useRequest,
   useSearchParams,
 } from '@umijs/max';
-import { Button, Tabs } from 'antd';
+import { Tabs } from 'antd';
 import dayjs from 'dayjs';
 import { useEffect, useMemo, useRef, useState } from 'react';
 import Analysis from './Analysis';
@@ -275,8 +275,8 @@ function SmartOps(props) {
 
   return (
     <PageContent>
-      <PageTitle>智慧分析</PageTitle>
-      {time && (
+      <PageTitle returnable={time}>智慧分析</PageTitle>
+      {/* {time && (
         <Button
           type="primary"
           style={{ marginBottom: 20 }}
@@ -284,7 +284,7 @@ function SmartOps(props) {
         >
           返回
         </Button>
-      )}
+      )} */}
       <div className={`card-box ${styles.topContent}`}>
         <div className={styles.titleContent}>
           <span className={styles.time}>{showTime}</span>

+ 4 - 3
src/pages/SmartOps/index.less

@@ -146,6 +146,7 @@
   color: #4a4a4a;
   font-size: 24px;
   white-space: nowrap;
+  margin-top: 40px;
   :global {
     .ant-select {
       margin: 0 40px 0 10px;
@@ -166,12 +167,12 @@
 }
 
 .tableSelect {
-  background-color: #2466a4;
+  background: rgba(145, 192, 238, 0.16) !important;
 }
 .tabContent {
   :global {
-    .ant-table-tbody > tr:nth-child(2n):not(.ant-table-expanded-row) {
-      background-image: url('~@/assets/tbodyBg1.png');
+    .ant-table-tbody > tr:nth-child(even) {
+      background: inherit;
     }
   }
 }

+ 12 - 12
src/services/SmartOps.js

@@ -279,14 +279,14 @@ export async function querySimulationProfit(data) {
   let res = await request(
     `/api/simulations/v1/profit/summary?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 export async function conditionEstimate(params) {
   let res = await request(`/api/energy/v1/condition/estimate`, {
     method: 'POST',
     data: params,
   });
-  return res?.data;
+  return res;
 }
 
 // 项目大水量冲洗设计:拉取设计列表
@@ -294,13 +294,13 @@ export async function queryDesignWashList(data) {
   let res = await request(
     `/api/simulations/v1/design/wash/list?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 
 // 运行记录:拉取大水量冲洗
 export async function queryDesignWash(data) {
   let res = await request(`/api/simulations/v1/record/wash?${stringify(data)}`);
-  return res?.data;
+  return res;
 }
 
 // 项目拉取非氧化杀菌列表
@@ -308,13 +308,13 @@ export async function queryDesignNobList(data) {
   let res = await request(
     `/api/simulations/v1/design/nob/list?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 
 // 运行记录:拉取非氧化杀菌运行记录
 export async function queryDesignNob(data) {
   let res = await request(`/api/simulations/v1/record/nob?${stringify(data)}`);
-  return res?.data;
+  return res;
 }
 
 // 项目泵设计:拉取设计列表  type膜类型 mf | uf | nf | ro
@@ -322,13 +322,13 @@ export async function queryPumpList(data) {
   let res = await request(
     `/api/simulations/v1/design/pump/list?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 
 // 运行记录:拉取泵运行记录  type膜类型 mf | uf | nf | ro
 export async function queryPump(data) {
   let res = await request(`/api/simulations/v1/record/pump?${stringify(data)}`);
-  return res?.data;
+  return res;
 }
 
 // 水厂工况
@@ -396,7 +396,7 @@ export async function queryMembraneList(data) {
   let res = await request(
     `/api/simulations/v1/design/membrane/list?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 
 // 运行记录:拉取非氧化杀菌运行记录  type膜类型 mf | uf | nf | ro
@@ -404,7 +404,7 @@ export async function queryMembrane(data) {
   let res = await request(
     `/api/simulations/v1/record/membrane?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 
 // 项目药剂设计:拉取设计列表  药剂类型 pac|nob|hci|sbs|anti
@@ -412,13 +412,13 @@ export async function queryDrugList(data) {
   let res = await request(
     `/api/simulations/v1/design/drug/list?${stringify(data)}`,
   );
-  return res?.data;
+  return res;
 }
 
 // 运行记录:拉取药剂记录  药剂类型 pac|nob|hci|sbs|anti
 export async function queryDrug(data) {
   let res = await request(`/api/simulations/v1/record/drug?${stringify(data)}`);
-  return res?.data;
+  return res;
 }
 
 // 子任务列表