소스 검색

feat(merge): merge xyh

Next xyh
Lind 3 년 전
부모
커밋
4c9bf19d29

+ 2 - 1
src/components/BadgeStatus/index.tsx

@@ -1,4 +1,5 @@
 import { Badge } from 'antd';
+import React from 'react';
 
 /**
  * 状态色
@@ -14,7 +15,7 @@ export enum StatusColorEnum {
 export type StatusColorType = keyof typeof StatusColorEnum;
 
 export interface BadgeStatusProps {
-  text: string;
+  text: string | React.ReactNode;
   status: string | number;
   /**
    * 自定义status值颜色

+ 40 - 39
src/components/Player/ScreenPlayer.tsx

@@ -11,7 +11,7 @@ import {
   CaretRightOutlined,
   PlusOutlined,
   MinusOutlined,
-  AudioOutlined,
+  // AudioOutlined,
 } from '@ant-design/icons';
 
 type Player = {
@@ -22,18 +22,19 @@ type Player = {
 interface ScreenProps {
   url?: string;
   id?: string;
+  channelId?: string;
   /**
    *
    * @param id 当前选中播发视频ID
    * @param type 当前操作动作
    */
-  onMouseDown?: (id: string, type: string) => void;
+  onMouseDown?: (id: string, channelId: string, type: string) => void;
   /**
    *
    * @param id 当前选中播发视频ID
    * @param type 当前操作动作
    */
-  onMouseLeave?: (id: string, type: string) => void;
+  onMouseUp?: (id: string, channelId: string, type: string) => void;
 }
 
 export default (props: ScreenProps) => {
@@ -126,13 +127,13 @@ export default (props: ScreenProps) => {
           <div
             className={'direction-item up'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'UP');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'UP');
               }
             }}
           >
@@ -141,13 +142,13 @@ export default (props: ScreenProps) => {
           <div
             className={'direction-item right'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'RIGHT');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'RIGHT');
               }
             }}
           >
@@ -156,13 +157,13 @@ export default (props: ScreenProps) => {
           <div
             className={'direction-item left'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'LEFT');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'LEFT');
               }
             }}
           >
@@ -171,13 +172,13 @@ export default (props: ScreenProps) => {
           <div
             className={'direction-item down'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'DOWN');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'DOWN');
               }
             }}
           >
@@ -186,30 +187,30 @@ export default (props: ScreenProps) => {
           <div
             className={'direction-audio'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'AUDIO');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'AUDIO');
               }
             }}
           >
-            <AudioOutlined />
+            {/*<AudioOutlined />*/}
           </div>
         </div>
         <div className={'zoom'}>
           <div
             className={'zoom-item zoom-in'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'ZOOM_IN');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'ZOOM_IN');
               }
             }}
           >
@@ -218,13 +219,13 @@ export default (props: ScreenProps) => {
           <div
             className={'zoom-item zoom-out'}
             onMouseDown={() => {
-              if (props.onMouseDown && props.id) {
-                props.onMouseDown(props.id, '');
+              if (props.onMouseDown && props.id && props.channelId) {
+                props.onMouseDown(props.id, props.channelId, 'ZOOM_OUT');
               }
             }}
-            onMouseLeave={() => {
-              if (props.onMouseLeave && props.id) {
-                props.onMouseLeave(props.id, '');
+            onMouseUp={() => {
+              if (props.onMouseUp && props.id && props.channelId) {
+                props.onMouseUp(props.id, props.channelId, 'ZOOM_OUT');
               }
             }}
           >

+ 35 - 1
src/components/ProTableCard/CardItems/device.tsx

@@ -3,15 +3,49 @@ import React from 'react';
 import type { DeviceInstance } from '@/pages/device/Instance/typings';
 import { BadgeStatus } from '@/components';
 import { StatusColorEnum } from '@/components/BadgeStatus';
-import '@/style/common.less';
+// import classNames from 'classnames';
+import '../index.less';
 
 export interface DeviceCardProps extends DeviceInstance {
   actions?: React.ReactNode[];
   avatarSize?: number;
+  children: React.ReactNode;
 }
 
 export default (props: DeviceCardProps) => {
+  // const [maskShow, setMaskShow] = useState(false)
+  //
+  // const maskClassName = classNames('card-mask', { show: maskShow })
   return (
+    // <div className={'iot-card'}>
+    //   <div className={'card-warp'}>
+    //     <div
+    //       className={'card-content'}
+    //       onMouseEnter={() => {setMaskShow(true)}}
+    //       onMouseLeave={() => {setMaskShow(false)}}
+    //     >
+    //       {
+    //         props.children
+    //       }
+    //       <div
+    //         className={
+    //           classNames(
+    //             'card-state',
+    //             {
+    //
+    //             }
+    //           )
+    //         }
+    //       >
+    //         <div className={'card-state-content'}></div>
+    //       </div>
+    //     </div>
+    //     <div className={maskClassName}></div>
+    //   </div>
+    //   <div className={'card-tools'}>
+    //
+    //   </div>
+    // </div>
     <Card style={{ width: '100%' }} cover={null} actions={props.actions}>
       <div className={'pro-table-card-item'}>
         <div className={'card-item-avatar'}>

+ 63 - 0
src/components/ProTableCard/index.less

@@ -71,3 +71,66 @@
     }
   }
 }
+
+@border-color: #e6e6e6;
+
+.iot-card {
+  width: 100%;
+
+  .card-warp {
+    position: relative;
+    border: 1px solid @border-color;
+
+    .card-content {
+      position: relative;
+      padding: 30px 12px 12px 30px;
+      overflow: hidden;
+
+      .card-state {
+        position: absolute;
+        top: 0;
+        right: 0;
+        display: flex;
+        justify-content: center;
+        width: 100px;
+        padding: 8px 0;
+        background-color: @info-color-deprecated-bg;
+        transform: skewX(45deg);
+
+        &.success {
+          background-color: @success-color-deprecated-bg;
+        }
+
+        &.warning {
+          background-color: @warning-color-deprecated-bg;
+        }
+
+        &.error {
+          background-color: @error-color-deprecated-bg;
+        }
+
+        .card-state-content {
+          transform: skewX(-45deg);
+        }
+      }
+    }
+
+    .card-mask {
+      position: absolute;
+      top: 0;
+      left: 0;
+      display: none;
+      align-items: center;
+      justify-content: center;
+      width: 100%;
+      height: 100%;
+      color: #fff;
+      background-color: rgba(#000, 0.5);
+      cursor: pointer;
+
+      &.show {
+        display: flex;
+      }
+    }
+  }
+}

+ 75 - 69
src/pages/media/Device/index.tsx

@@ -1,3 +1,4 @@
+// 视频设备列表
 import { PageContainer } from '@ant-design/pro-layout';
 import { useRef } from 'react';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
@@ -7,6 +8,8 @@ import BaseCrud from '@/components/BaseCrud';
 import BaseService from '@/utils/BaseService';
 import type { DeviceItem } from '@/pages/media/Device/typings';
 import { useIntl } from '@@/plugin-locale/localeExports';
+import { BadgeStatus } from '@/components';
+import { StatusColorEnum } from '@/components/BadgeStatus';
 
 export const service = new BaseService<DeviceItem>('media/device');
 const Device = () => {
@@ -26,81 +29,83 @@ const Device = () => {
         defaultMessage: '名称',
       }),
     },
-    {
-      dataIndex: 'transport',
-      title: intl.formatMessage({
-        id: 'pages.media.device.transport',
-        defaultMessage: '信令传输',
-      }),
-    },
-    {
-      dataIndex: 'streamMode',
-      title: intl.formatMessage({
-        id: 'pages.media.device.streamMode',
-        defaultMessage: '流传输模式',
-      }),
-    },
-    {
-      dataIndex: 'channelNumber',
-      title: intl.formatMessage({
-        id: 'pages.media.device.channelNumber',
-        defaultMessage: '通道数',
-      }),
-    },
-    {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
-    },
-    {
-      dataIndex: 'host',
-      title: 'IP',
-    },
-    {
-      dataIndex: '端口',
-      title: intl.formatMessage({
-        id: 'pages.media.device.port',
-        defaultMessage: '端口',
-      }),
-    },
-    {
-      dataIndex: 'manufacturer',
-      title: intl.formatMessage({
-        id: 'pages.media.device.manufacturer',
-        defaultMessage: '设备厂家',
-      }),
-    },
-    {
-      dataIndex: 'model',
-      title: intl.formatMessage({
-        id: 'pages.media.device.model',
-        defaultMessage: '型号',
-      }),
-    },
-    {
-      dataIndex: 'firmware',
-      title: intl.formatMessage({
-        id: 'pages.media.device.firmware',
-        defaultMessage: '固件版本',
-      }),
-    },
-    {
-      dataIndex: 'networkType',
-      title: intl.formatMessage({
-        id: 'pages.table.type',
-        defaultMessage: '类型',
-      }),
-    },
+    // {
+    //   dataIndex: 'transport',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.transport',
+    //     defaultMessage: '信令传输',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'streamMode',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.streamMode',
+    //     defaultMessage: '流传输模式',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'channelNumber',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.channelNumber',
+    //     defaultMessage: '通道数',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'host',
+    //   title: 'IP',
+    // },
+    // {
+    //   dataIndex: '端口',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.port',
+    //     defaultMessage: '端口',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'manufacturer',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.manufacturer',
+    //     defaultMessage: '设备厂家',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'model',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.model',
+    //     defaultMessage: '型号',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'firmware',
+    //   title: intl.formatMessage({
+    //     id: 'pages.media.device.firmware',
+    //     defaultMessage: '固件版本',
+    //   }),
+    // },
+    // {
+    //   dataIndex: 'networkType',
+    //   title: intl.formatMessage({
+    //     id: 'pages.table.type',
+    //     defaultMessage: '类型',
+    //   }),
+    // },
     {
       dataIndex: 'state',
       title: intl.formatMessage({
         id: 'pages.searchTable.titleStatus',
         defaultMessage: '状态',
       }),
-      render: (text, record) => record.state.value,
+      render: (text, record) => (
+        <BadgeStatus
+          status={record.state.value}
+          statusNames={{
+            online: StatusColorEnum.success,
+            offline: StatusColorEnum.error,
+            notActive: StatusColorEnum.processing,
+          }}
+          text={text}
+        />
+      ),
     },
     {
       title: intl.formatMessage({
@@ -161,6 +166,7 @@ const Device = () => {
       <BaseCrud
         columns={columns}
         service={service}
+        search={false}
         title={intl.formatMessage({
           id: 'pages.media.device',
           defaultMessage: '模拟测试',

+ 24 - 3
src/pages/media/SplitScreen/index.tsx

@@ -1,17 +1,38 @@
+// 视频分屏
 import { PageContainer } from '@ant-design/pro-layout';
 import { Card } from 'antd';
 import LeftTree from './tree';
-import './index.less';
 import { ScreenPlayer } from '@/components';
+import { ptzStop, ptzTool } from './service';
+import { useState } from 'react';
+import './index.less';
 
 const SplitScreen = () => {
+  const [deviceId, setDeviceId] = useState('');
+  const [channelId] = useState('');
+  const [url] = useState('');
+
   return (
     <PageContainer>
       <Card>
         <div className="split-screen">
-          <LeftTree />
+          <LeftTree
+            onSelect={(id) => {
+              setDeviceId(id);
+            }}
+          />
           <div className="right-content">
-            <ScreenPlayer />
+            <ScreenPlayer
+              id={deviceId}
+              url={url}
+              channelId={channelId}
+              onMouseUp={(id, cId) => {
+                ptzStop(id, cId);
+              }}
+              onMouseDown={(id, cId, type) => {
+                ptzTool(id, cId, type, 90);
+              }}
+            />
           </div>
         </div>
       </Card>

+ 20 - 0
src/pages/media/SplitScreen/service.ts

@@ -0,0 +1,20 @@
+import { request } from '@@/plugin-request/request';
+import SystemConst from '@/utils/const';
+
+const url = `/${SystemConst.API_BASE}/media`;
+
+// 设备树
+export const getMediaTree = (data?: any) =>
+  request(`${url}/device/_query/no-paging`, { method: 'POST', data });
+
+// 开始直播
+export const ptzStart = (deviceId: string, channelId: string) =>
+  request(`${url}/device/${deviceId}/${channelId}/_pzt/_start`, { method: 'POST' });
+
+// 云台控制-停止
+export const ptzStop = (deviceId: string, channelId: string) =>
+  request(`${url}/device/${deviceId}/${channelId}/_pzt/STOP`, { method: 'POST' });
+
+// 云台控制-缩放、转向等
+export const ptzTool = (deviceId: string, channelId: string, direct: string, speed: number = 90) =>
+  request(`${url}/device/${deviceId}/${channelId}/_pzt/${direct}/${speed}`, { method: 'POST' });

+ 29 - 2
src/pages/media/SplitScreen/tree.tsx

@@ -1,10 +1,37 @@
 import { Input, Tree } from 'antd';
+import { getMediaTree } from './service';
+import { useRequest } from 'umi';
+import { useEffect } from 'react';
+
+type LeftTreeTYpe = {
+  onSelect?: (deviceId: string) => void;
+};
+
+const LeftTree = (props: LeftTreeTYpe) => {
+  const { data, run: queryTree } = useRequest(getMediaTree, {
+    manual: true,
+  });
+
+  useEffect(() => {
+    queryTree({ paging: false });
+  }, []);
 
-const LeftTree = () => {
   return (
     <div className="left-content">
       <Input.Search />
-      <Tree />
+      <Tree
+        height={500}
+        fieldNames={{
+          title: 'name',
+          key: 'id',
+        }}
+        onSelect={(key) => {
+          if (props.onSelect) {
+            props.onSelect(key[0] as string);
+          }
+        }}
+        treeData={data}
+      />
     </div>
   );
 };

+ 0 - 0
src/pages/media/SplitScreen/type.d.ts


+ 1 - 1
src/pages/media/Stream/index.less

@@ -5,7 +5,7 @@
     justify-content: space-between;
     width: 100%;
     .title {
-      width: '50%';
+      width: 50%;
       overflow: hidden;
       font-weight: 800;
       white-space: nowrap;

+ 1 - 1
src/utils/menu/router.ts

@@ -48,7 +48,7 @@ export const MENUS_CODE = {
   'media/Stream/Detail': 'media/Stream/Detail',
   'notice/Type': 'notice/Type',
   'media/SplitScreen': 'media/SplitScreen',
-  'notice/Config': 'notice/Config',
+  'notice/Type/Config': 'notice/Config',
   'notice/Config/Detail': 'notice/Config/Detail',
   'notice/Template': 'notice/Template',
   'notice/Template/Detail': 'notice/Template/Detail',