Sfoglia il codice sorgente

感知分析接口联调

Renxy 1 anno fa
parent
commit
f40d2ec11f

+ 2 - 2
.umirc.ts

@@ -26,8 +26,8 @@ export default defineConfig({
   ],
   proxy: {
     '/api': {
-      target: 'http://47.96.12.136:8888/',
-      // target: 'http://47.96.12.136:8788/',
+      // target: 'http://47.96.12.136:8888/',
+      target: 'http://47.96.12.136:8788/',
       // target: 'http://120.55.44.4:8903/',
       // target: 'https://work.greentech.com.cn/',
       changeOrigin: true,

+ 8 - 1
src/pages/Center/index.js

@@ -1,4 +1,5 @@
 import { version } from '@/constants';
+import { UnityAction } from '@/utils/utils';
 import { useModel, useNavigate, useParams } from '@umijs/max';
 import styles from './index.less';
 const Center = () => {
@@ -15,6 +16,10 @@ const Center = () => {
     navigate(`/smart-report/${projectId}`);
   };
 
+  const handleLogOutClick = () => {
+    UnityAction.sendMsg('Logout');
+  };
+
   return (
     <div className={styles.page}>
       <div className={styles.head}>
@@ -41,7 +46,9 @@ const Center = () => {
         <div className={styles.lineItem}>问题反馈备份</div>
         <div className={styles.lineItem}>个人设置</div>
       </div>
-      <div className={styles.loginOut}>退出登录</div>
+      <div className={styles.loginOut} onClick={handleLogOutClick}>
+        退出登录
+      </div>
     </div>
   );
 };

+ 298 - 45
src/pages/SmartOps/components/VideoAnalysis.js

@@ -1,5 +1,8 @@
+import ModuleTitle from '@/components/ManagementPage/moduleTitle';
+import TabsContent from '@/components/TabsContent';
+import ThresholdDetail from '@/components/ThresholdDetail';
 import { UnityAction } from '@/utils/utils';
-import { Collapse, Empty, Spin, Tabs } from 'antd';
+import { Collapse, Spin, Table, Tabs } from 'antd';
 import { useEffect, useState } from 'react';
 import ThresholdBar from './ThresholdBar';
 import styles from './VideoAnalysis.less';
@@ -8,7 +11,12 @@ const { TabPane } = Tabs;
 const { Panel } = Collapse;
 
 function VideoAnalysis(props) {
-  const { data, loading } = props;
+  const { videoNum, data, videoData, loading } = props;
+  const [tab, setTab] = useState('1');
+  const allCount = Object.values(videoData).reduce(
+    (total, item) => total + item?.length,
+    0,
+  );
 
   const [prevKey, setPrevKey] = useState();
   const [selectedName, setSelectedName] = useState('');
@@ -37,47 +45,44 @@ function VideoAnalysis(props) {
     }
   };
 
+  const onTabChange = (tab) => {
+    setTab(tab);
+    // UnityAction.sendMsg('ProcessAnalysisType', tab);
+  };
+
   return (
     <Spin spinning={loading}>
-      <div
-        id="videoContent"
-        className={styles.page}
-        style={{ height: 'calc(100vh - 580px)', overflow: 'auto' }}
-      >
-        {data?.list?.length > 0 ? (
-          data?.list?.map((item) => (
-            <div data-name={item.device_name}>
-              <Collapse
-                defaultActiveKey={[item.id]}
-                key={item.id}
-                className={
-                  selectedName == item.device_name || prevKey == item.id
-                    ? styles.tableSelect
-                    : styles.table
-                }
-                expandIcon={() => (
-                  <div className={styles.typeText}>视频报警</div>
-                )}
-                onChange={(e) => {
-                  handleCollapse(item.id);
-                }}
-              >
-                <Panel header={item.device_name} key={item.id}>
-                  <AnalysisContent item={item} />
-                </Panel>
-              </Collapse>
-            </div>
-          ))
-        ) : (
-          <Empty />
-        )}
-      </div>
+      <TabsContent
+        small={true}
+        center={false}
+        defaultActiveKey="1"
+        items={[
+          {
+            label: `异常(${videoNum})`,
+            key: '1',
+            children: (
+              <AnalysisContent
+                data={data}
+                videoData={videoData}
+                selectedName={selectedName}
+                prevKey={prevKey}
+              />
+            ),
+          },
+          {
+            label: `全部(${allCount})`,
+            key: '2',
+            children: <AllContent data={data} videoData={videoData} />,
+          },
+        ]}
+        onChange={onTabChange}
+      />
     </Spin>
   );
 }
 
-function AnalysisContent({ item }) {
-  const handleImgClick = () => {
+function AnalysisContent({ data, selectedName, prevKey }) {
+  const handleImgClick = (item) => {
     localStorage.setItem('preview', JSON.stringify(item.data));
     UnityAction.sendMsg('SensorPic');
   };
@@ -94,7 +99,7 @@ function AnalysisContent({ item }) {
               <img
                 className={styles.img}
                 src={item.url}
-                onClick={handleImgClick}
+                onClick={() => handleImgClick(item)}
               />
             </div>
           </>
@@ -138,13 +143,261 @@ function AnalysisContent({ item }) {
   };
 
   return (
-    <div className={styles.box}>
-      <div className={styles.item}>
-        {renderContent(3, item)}
-        {/* <div className={styles.content}>
-          {item.event_type}
-          <img className={styles.img} src={item.url} onClick={handleImgClick} />
-        </div> */}
+    <div
+      className={styles.page}
+      style={{ height: 'calc(100vh - 630px)', overflow: 'auto' }}
+    >
+      {data?.length > 0 ? (
+        data?.map((item) => (
+          <div data-name={item.device_name}>
+            <Collapse
+              defaultActiveKey={[item.id]}
+              key={item.id}
+              className={
+                selectedName == item.device_name || prevKey == item.id
+                  ? styles.tableSelect
+                  : styles.table
+              }
+              expandIcon={() => <div className={styles.typeText}>视频报警</div>}
+              onChange={(e) => {
+                handleCollapse(item.id);
+              }}
+            >
+              <Panel header={item.device_name} key={item.id}>
+                <div className={styles.box}>
+                  <div className={styles.item}>{renderContent(1, item)}</div>
+                </div>
+              </Panel>
+            </Collapse>
+          </div>
+        ))
+      ) : (
+        <Empty />
+      )}
+    </div>
+  );
+}
+
+function AllContent({ data = [], videoData = {} }) {
+  const { environment_list = [], fluid_level_list = [] } = videoData;
+  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+  const columns1 = [
+    {
+      title: '设备名称',
+      render: (record) => (
+        <div>
+          {record.device_name}({record.device_code})
+        </div>
+      ),
+    },
+    {
+      title: '参数',
+      dataIndex: 'patrol_name',
+      key: 'patrol_name',
+    },
+    {
+      title: '设定值范围',
+      render: (record) => (
+        <ThresholdDetail
+          current={record.value || 0}
+          data={{ JsonNumThreshold: record?.json_num_threshold, Type: 2 }}
+          // onClick={() => onClickThreshold(record)}
+        />
+      ),
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      render: (status) => {
+        switch (status) {
+          case -1:
+          case 0:
+            return (
+              <div>
+                <i
+                  className={styles.iconStatus}
+                  style={{ background: '#12CEB3' }}
+                ></i>
+                正常
+              </div>
+            );
+          case 1:
+            return (
+              <div>
+                <i
+                  className={styles.iconStatus}
+                  style={{ background: '#FE5850' }}
+                ></i>
+                异常
+              </div>
+            );
+          case 2:
+            return (
+              <div>
+                <i
+                  className={styles.iconStatus}
+                  style={{ background: '#FFE26D' }}
+                ></i>
+                警告
+              </div>
+            );
+        }
+      },
+    },
+  ];
+  const columns2 = [
+    {
+      title: '设备名称',
+      render: (record) => (
+        <div>
+          {record.device_name}({record.device_code})
+        </div>
+      ),
+    },
+    {
+      title: '液位数',
+      dataIndex: 'origin_value',
+      key: 'origin_value',
+    },
+    {
+      title: '差值',
+      dataIndex: 'value',
+      key: 'value',
+    },
+    {
+      title: '设定值范围',
+      render: (record) => (
+        <ThresholdDetail
+          current={record.value || 0}
+          data={{ JsonNumThreshold: record?.json_num_threshold, Type: 2 }}
+          // onClick={() => onClickThreshold(record)}
+        />
+      ),
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      render: (status) => {
+        switch (status) {
+          case -1:
+          case 0:
+            return (
+              <div>
+                <i
+                  className={styles.iconStatus}
+                  style={{ background: '#12CEB3' }}
+                ></i>
+                正常
+              </div>
+            );
+          case 1:
+            return (
+              <div>
+                <i
+                  className={styles.iconStatus}
+                  style={{ background: '#FE5850' }}
+                ></i>
+                异常
+              </div>
+            );
+          case 2:
+            return (
+              <div>
+                <i
+                  className={styles.iconStatus}
+                  style={{ background: '#FFE26D' }}
+                ></i>
+                警告
+              </div>
+            );
+        }
+      },
+    },
+  ];
+  const columns3 = [
+    {
+      title: '名称',
+      render: (record) => (
+        <div>
+          {record.device_name}({record.device_code})
+        </div>
+      ),
+    },
+    {
+      title: '描述',
+      dataIndex: 'event_type',
+      key: 'event_type',
+    },
+    {
+      title: '图片',
+      render: (item) => (
+        <img
+          className={styles.img}
+          src={item.url}
+          onClick={() => handleImgClick(item)}
+        />
+      ),
+    },
+  ];
+
+  const onSelectRow = (record, index) => {
+    const selectedList = [...selectedRowKeys];
+    if (selectedList[0] === index) return;
+    selectedList[0] = index;
+    setSelectedRowKeys(selectedList);
+    UnityAction.sendMsg('SynDev', record.DeviceCode);
+  };
+
+  const setRowClassName = (record, index) => {
+    return index === selectedRowKeys[0] ||
+      record.DeviceCode == selectedRowKeys[0]
+      ? styles.tableSelect
+      : '';
+  };
+
+  return (
+    <div
+      className={styles.page}
+      style={{ height: 'calc(100vh - 630px)', overflow: 'auto' }}
+    >
+      <div className={`card-box ${styles.box}`}>
+        <ModuleTitle title="环境监测" />
+        <Table
+          dataSource={environment_list}
+          columns={columns1}
+          // rowClassName={setRowClassName}
+          // onRow={(record, index) => ({
+          //   onClick: () => onSelectRow(record, index),
+          // })}
+          pagination={false}
+          scroll={{ y: 400 }}
+        />
+      </div>
+      <div className={`card-box ${styles.box}`}>
+        <ModuleTitle title="液位检测" />
+        <Table
+          dataSource={fluid_level_list}
+          columns={columns2}
+          // rowClassName={setRowClassName}
+          // onRow={(record, index) => ({
+          //   onClick: () => onSelectRow(record, index),
+          // })}
+          pagination={false}
+          scroll={{ y: 400 }}
+        />
+      </div>
+      <div className={`card-box ${styles.box}`}>
+        <ModuleTitle title="感知监测" />
+        <Table
+          dataSource={data}
+          columns={columns3}
+          // rowClassName={setRowClassName}
+          // onRow={(record, index) => ({
+          //   onClick: () => onSelectRow(record, index),
+          // })}
+          pagination={false}
+          scroll={{ y: 400 }}
+        />
       </div>
     </div>
   );

+ 12 - 0
src/pages/SmartOps/components/VideoAnalysis.less

@@ -25,6 +25,14 @@
     }
   }
 }
+.iconStatus {
+  width: 20px;
+  height: 20px;
+  vertical-align: middle;
+  margin-right: 10px;
+  border-radius: 50%;
+  display: inline-block;
+}
 
 .img {
   width: 120px;
@@ -52,6 +60,10 @@
   .textNormal {
     color: #4a90e2;
   }
+  .box {
+    padding: 16px;
+    margin-bottom: 20px;
+  }
 
   :global {
     .ant-collapse > .ant-collapse-item {

+ 62 - 33
src/pages/SmartOps/index.js

@@ -6,7 +6,7 @@ import {
   queryProjectConfig,
   querySimulationProfit,
 } from '@/services/SmartOps';
-import { getCameraList, getDetail } from '@/services/dumu';
+import { getDetail, getPatrolPerception } from '@/services/dumu';
 import { GetTokenFromUrl, UnityAction } from '@/utils/utils';
 import {
   connect,
@@ -39,6 +39,7 @@ function SmartOps(props) {
   const time = searchParams.get('time');
   const idList = searchParams.get('idList');
   const patrolId = searchParams.get('patrolId');
+  const [videoNum, setVideoNum] = useState(0);
 
   const [tableData, setTableData] = useState([]);
   const signalRef = useRef();
@@ -97,7 +98,7 @@ function SmartOps(props) {
         routeId: patrolId || reportData.PatrolId,
       },
       callback: (data) => {
-        console.log(data);
+        // console.log(data);
         const message = data?.extendWarningAllData?.map((item) => {
           return {
             DeviceCode: item.DeviceCode,
@@ -147,43 +148,67 @@ function SmartOps(props) {
   const optimizationNumber = workAnalysisRequest?.optimizationNumber || 0;
 
   //感知分析
+  const {
+    data: videoData,
+    loading: loadingVideo,
+    run: runVideo,
+  } = useRequest(
+    () =>
+      getPatrolPerception({
+        project_id: projectId * 1,
+        patrol_id: patrolId || reportData.PatrolId,
+      }),
+    {
+      onSuccess: (data) => {
+        if (data.dumu_list?.length > 0) {
+          setTableData(data?.dumu_list);
+          data.dumu_list.forEach((item) => {
+            detailRun(item.id, { signal: signalRef.current.signal });
+          });
+        }
+        const count1 = data.dumu_list?.length || 0;
+        const count2 =
+          data.environment_list?.filter((item) => item.status)?.length || 0;
+        const count3 =
+          data.fluid_level_list?.filter((item) => item.status)?.length || 0;
+        setVideoNum(count1 + count2 + count3);
+      },
+    },
+  );
+
   const { run: detailRun } = useRequest(getDetail, {
     manual: true,
     fetchKey: (id) => id,
     cacheKey: (id) => id,
     onSuccess: (data) => {
-      var item = tableData?.list?.find((child) => child.id === data.id);
+      var item = tableData?.find((child) => child.id === data.id);
       if (item) {
         item.url = base64ToImageUrl(data.event_bg);
         item.data = data;
       }
-      var data = {
-        list: [...tableData?.list],
-        pagination: tableData?.pagination,
-      };
-      setTableData(data);
+      setTableData([...tableData]);
     },
   });
-  const { run, loading: loadingVideo } = useRequest(
-    () =>
-      getCameraList(projectId, {
-        s_time: dayjs().subtract(10, 'month').format('YYYY-MM-DD HH:mm:ss'), //sTime,
-        e_time: eTime,
-        pageSize: 999,
-      }),
-    {
-      manual: true,
-      onSuccess: (data) => {
-        setTableData(data);
-        sendUnityMsg(data?.list);
-        // data?.list?.forEach(item => {
-        //   detailRun(item.id, { signal: signalRef.current.signal });
-        // });
-      },
-    },
-  );
+  // const { run, loading: loadingVideo } = useRequest(
+  //   () =>
+  //     getCameraList(projectId, {
+  //       s_time: dayjs().subtract(10, 'month').format('YYYY-MM-DD HH:mm:ss'), //sTime,
+  //       e_time: eTime,
+  //       pageSize: 999,
+  //     }),
+  //   {
+  //     manual: true,
+  //     onSuccess: (data) => {
+  //       setTableData(data);
+  //       sendUnityMsg(data?.list);
+  //       // data?.list?.forEach(item => {
+  //       //   detailRun(item.id, { signal: signalRef.current.signal });
+  //       // });
+  //     },
+  //   },
+  // );
 
-  const videoAnalysisNumber = tableData?.pagination?.total || 0;
+  // const videoAnalysisNumber = tableData?.pagination?.total || 0;
   const AnalysisNumber = list?.pagenation?.total || 0;
 
   function base64ToImageUrl(base64String) {
@@ -245,7 +270,8 @@ function SmartOps(props) {
     if (!eTime) return;
     initDate();
     runWork();
-    run();
+    // run();
+    runVideo();
     getProfit();
   }, [eTime]);
 
@@ -308,9 +334,7 @@ function SmartOps(props) {
             </div>
             <div className={styles.item3}>
               感知分析:
-              {videoAnalysisNumber > 0
-                ? `${videoAnalysisNumber}项可优化`
-                : '暂无优化'}
+              {videoNum > 0 ? `${videoNum}项可优化` : '暂无优化'}
             </div>
           </div>
         </div>
@@ -345,10 +369,15 @@ function SmartOps(props) {
               children: <Analysis />,
             },
             {
-              label: `感知分析(${loadingVideo ? '-' : videoAnalysisNumber})`,
+              label: `感知分析(${loadingVideo ? '-' : videoNum})`,
               key: '3',
               children: (
-                <VideoAnalysis data={tableData} loading={loadingVideo} />
+                <VideoAnalysis
+                  videoNum={videoNum}
+                  data={tableData}
+                  videoData={videoData}
+                  loading={loadingVideo}
+                />
               ),
             },
           ]}

+ 5 - 0
src/services/dumu.js

@@ -53,3 +53,8 @@ export async function getDetail(detailId, options) {
   const res = await request(`/api/v1/dumu/detail/${detailId}`, options);
   return res;
 }
+//获取感知分析数据
+export async function getPatrolPerception(params) {
+  const res = await request(`/api/v1/patrol/perception?${stringify(params)}`);
+  return res;
+}