Browse Source

fix: 路外视频监控

tags/PMS_V1.0.0_Alpha5
chenglb 1 year ago
parent
commit
81920cd065
  1. 2
      src/components/TableModule/index.jsx
  2. 156
      src/pages/OutRoadMgm/OutDeviceMgm/OutMonitorMgm/HistoryTable.jsx
  3. 13
      src/pages/OutRoadMgm/OutDeviceMgm/OutMonitorMgm/index.scss
  4. 217
      src/pages/OutRoadMgm/OutDeviceMgm/OutMonitorMgm/loadable.jsx
  5. 166
      src/pages/OutRoadMgm/OutDeviceMgm/OutNvrMgm/loadable.jsx
  6. 23
      src/services/search.js

2
src/components/TableModule/index.jsx

@ -322,7 +322,7 @@ const TableModule = forwardRef((props, ref) => {
setAreaSelectedList([])
searchForm.resetFields();
setFormData({ ...searchForm.getFieldsValue(), plateValue: '' })
search({ ...searchForm.getFieldsValue() })
// search({ ...searchForm.getFieldsValue() })
setTimeGroup({
timeType: '1',
timeRanges: {

156
src/pages/OutRoadMgm/OutDeviceMgm/OutMonitorMgm/HistoryTable.jsx

@ -0,0 +1,156 @@
import React, { useEffect, useState, useRef } from "react"
import { Button, message , Input, Modal ,Table ,DatePicker } from "antd"
import { IconPda ,VideoPlay } from '@/components'
import { useNavigate } from "react-router-dom"
import './index.scss'
import ajax from "@/services"
import { useDispatch,useSelector } from "react-redux"
import { setFirstPageMap } from "@/store/common.js"
import axios from 'axios'
import { dictionary } from "@/config/common";
import moment from "moment";
export default function HistoryTable(props) {
const {id} = props
const [tableData, setTableData] = useState([ ])
const [total, setTotal] = useState(0)
const [pageData, setPageData] = useState({
pn: 1,
page_size: dictionary?.pageSizeOptions[0] ? dictionary.pageSizeOptions[0] : 15
})
const [visible, setVisible]= useState(false)
const [timeRange, setTimeRange] = useState([moment(new Date(new Date().getTime() - 365*86400*1000)), moment()])
const videoRef = useRef()
const [videoUrl, setVideoUrl] = useState('')
const intervalPlayRef = useRef()
const columns = [
{
title: '序号',
width: 150,
dataIndex: 'name',
key: 'name',
align: "center",
render: (va, record,index) => <span>{index + 1}</span>,
},
{
title: '开始时间',
dataIndex: 'start_time',
key: 'start_time',
align: "center"
},
{
title: '结束时间',
dataIndex: 'end_time',
key: 'end_time',
align: "center"
},
{
title: '操作',
key: 'operation',
width: 150,
align: "center",
render: (va, record) => <a onClick={()=>{getOneVideoPlay(record.start_time, record.end_time)}}>查看回放</a>,
},
];
const getHistoryVideoList = ()=>{
let start_time = timeRange[0].format('YYYY-MM-DD HH:mm:ss'),
end_time = timeRange[1].format('YYYY-MM-DD HH:mm:ss');
ajax.getHistoryVideoList({...pageData, start_time, end_time}).then(
res=>{
if(res.status == 20000){
setTableData(res.data)
setTotal(res.total ? res.total: 1000)
}else{
setTableData([])
setTotal(0)
}
}
).catch(err=>{
setTableData([])
setTotal(0)
})
}
const getOneVideoPlay =(time1, time2)=>{
ajax.getOneVideoPlay({id: id, start_time: time1, end_time: time2, type: 2}).then(
res=>{
if(res.status == 20000){
setVisible(true)
setVideoUrl(res.data.url)
}
}
).catch(err=>{
})
}
// const stopIntervalToClose = ()=>{
// if(intervalPlayRef.current){
// clearInterval(intervalPlayRef.current)
// intervalPlayRef.current = null
// }
// }
useEffect(()=>{
getHistoryVideoList()
},[pageData])
useEffect(()=>{
getHistoryVideoList()
},[])
return (
<div className="table-block">
<div className="search-part" style={{display: "flex",justifyContent:"space-between",marginBottom: '10px'}}>
<div className="time-item" style={{width: '400px',display: 'flex', alignItems:"center"}}>
<span style={{display: "block", width: '90px'}}>回放时间</span>
<DatePicker.RangePicker value={timeRange} onChange={(e)=>{setTimeRange(e)}} showTime allowClear={false} />
</div>
<Button type="primary" onClick={getHistoryVideoList}>查询</Button>
</div>
<div className="table-part">
<Table
columns={columns}
dataSource={tableData}
rowKey={(row)=>row.start_time}
scroll={{
y: 450,
}}
pagination={{
total: total,
pageSizeOptions: dictionary?.pageSizeOptions,
current: pageData.pn,
pageSize: pageData.page_size,
onChange:(targetPn, targetSize)=>{
if(pageData.page_size != targetSize){
setPageData({
pn:1, page_size: targetSize
})
}else{
setPageData({
pn:targetPn, page_size: targetSize
})
}
}
}}
/>
</div>
<Modal
open={visible}
width={1200}
title=""
onCancel={()=>{setVisible(false);}}
footer={null}
>
<div>
{
videoUrl ? <VideoPlay videoType="mp4" ref={videoRef} videoUrl={videoUrl} ></VideoPlay> : null
}
</div>
</Modal>
</div>
)
}

13
src/pages/OutRoadMgm/OutDeviceMgm/OutMonitorMgm/index.scss

@ -281,4 +281,17 @@ $color-primary : var(--color-primary);
}
}
}
.out-monitor-switch-line{
border-bottom: 1px solid #999da8;
margin-bottom: 10px;
height: 34px;
line-height: 34px;
span{
cursor: pointer;
font-weight: bold;
&.active{
color: #3b97ff;
}
}
}

217
src/pages/OutRoadMgm/OutDeviceMgm/OutMonitorMgm/loadable.jsx

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from "react";
import { ResultFlowResult } from "@/components";
import { ResultFlowResult , VideoPlay } from "@/components";
import {
Select,
Input,
@ -20,6 +20,7 @@ import { getToken } from "@/config/cookie";
import moment from "moment";
import "./index.scss";
import ajax from "@/services";
import HistoryTable from "./HistoryTable";
function OutMonitorMgm(props) {
const [form] = Form.useForm();
// session
@ -32,6 +33,7 @@ function OutMonitorMgm(props) {
device_code: "", //
operator_id: "", //
road_id: "", //
nvr_type: 0
};
//
const [pageInfo, setPageInfo] = useState({
@ -58,26 +60,37 @@ function OutMonitorMgm(props) {
const [roadData, setRoadData] = useState([]);
const [nvrData, setNvrData] = useState([]);
const [nvrGbData, setNvrGbData] = useState([]);
const [berthData, setBerthData] = useState([]);
const [berthSelectData, setBerthSelectData] = useState([]);
const [selectedKeys, setSelectedKeys] = useState([]);
const defRowData = {
device_name: "",
nvr_id: "",
device_code: "",
berth_ids: "",
nvr_type: ""
};
//
const [rowData, setRowData] = useState(defRowData);
//
const [visible1, setVisible1] = useState(false);
//
const [videoModalVisible, setVideoModalVisible] = useState(false)
const [playType ,setPlayType] = useState('1')
const intervalPlayRef = useRef()
//
const [fileList, setFileList] = useState([]);
const [sessionTabList, setSessionTabList] = useSessionStorageState('outMonitorMgm', {
value: {
}
})
const [oneVideoRealtimeUrlInfo, setOneVideoRealtimeUrlInfo] = useState({})
const videoRef = useRef()
const intervalRef = useRef()
const rowDataRef = useRef()
rowDataRef.current = rowData
useEffect(() => {
if (sessionTabList && Object.values(sessionTabList).length > 0) {
setFormData({
@ -188,9 +201,43 @@ function OutMonitorMgm(props) {
};
const handlePlay = (item) => {
message.error(`播放数据暂未对接`);
// message.error(``);
ajax.getOneVideoPlay({id: item.id, type: 1}).then(
res=>{
if(res.status == 20000 && res.data.url){
setVideoModalVisible(true)
setOneVideoRealtimeUrlInfo({id: item.id, url: res.data.url})
startIntervalToPlay()
}else{
message.error(`播放数据暂未对接`);
}
}
).catch(err=>{
})
};
const startIntervalToPlay = ()=>{
if(!intervalPlayRef.current){
intervalPlayRef.current = setInterval(() => {
ajax.getOutRoadVideoPlaying({id: rowDataRef.current.id, type:1}).then((res)=>{
if(res.status == 20000){
// console.log('')
}
})
}, 5000);
}
}
const stopIntervalToClose = ()=>{
if(intervalPlayRef.current){
clearInterval(intervalPlayRef.current)
intervalPlayRef.current = null
}
}
const handleDel = (item) => {
Modal.confirm({
title: "确认删除?",
@ -202,7 +249,8 @@ function OutMonitorMgm(props) {
});
};
const getNvrList = () => {
ajax.getAllOutNvrList().then(
//
ajax.getAllOutNvrList({nvr_type: 1}).then(
(res) => {
if (res.status == 20000) {
setNvrData(res?.data || []);
@ -215,6 +263,21 @@ function OutMonitorMgm(props) {
message.error("服务器异常");
}
);
//
ajax.getAllOutNvrList({nvr_type: 2}).then(
(res) => {
if (res.status == 20000) {
res.data.push({value: 111222233, label: 'nvr090909'}) // todo
setNvrGbData(res?.data || []);
} else {
message.error(res.message);
}
},
(err) => {
console.log(err);
message.error("服务器异常");
}
);
};
const getChannelByNvr = (nvr) => {
ajax
@ -228,7 +291,7 @@ function OutMonitorMgm(props) {
.then(
(res) => {
if (res?.status == 20000) {
const newData = res?.data || [];
const newData = res?.data?.left || [];
if (newData?.length) {
setBerthData(
newData.map((item) => ({ key: item.value, title: item.label }))
@ -321,6 +384,15 @@ function OutMonitorMgm(props) {
align: "center",
},
{
title: "NVR类型",
dataIndex: "nvr_type",
align: "center",
render: (val) => {
return <>{val == 2 ? '国标' : '非国标'}</>;
},
width: 100,
},
{
title: "设备编号",
dataIndex: "device_code",
align: "center",
@ -399,10 +471,10 @@ function OutMonitorMgm(props) {
//
const onFinish = (values) => {
// console.log(values);
if (!rowData?.berth_ids) {
message.error("请选择泊位");
return;
}
// if (!rowData?.berth_ids) {
// message.error("");
// return;
// }
ajax[values?.id ? "monitorOutEdit" : "monitorOutAdd"]({
...values,
berth_ids: rowData?.berth_ids,
@ -580,6 +652,19 @@ function OutMonitorMgm(props) {
onChange={(v) => setFormData({ ...formData, road_id: v })}
/>
</div>
<div className="yisa-search">
<label>NVR类型</label>
<Select
className="form-con"
placeholder="请选择"
allowClear={false}
options={[{label: '全部',value: 0},{label: '非国标',value: 1},{label: '国标',value: 2}]}
value={formData?.nvr_type || 0}
onChange={(v) => {
setFormData({ ...formData, nvr_type: v });
}}
/>
</div>
<div className="form-btn">
<Button
className="reset"
@ -667,35 +752,85 @@ function OutMonitorMgm(props) {
<Input />
</Form.Item>
<Form.Item
label={"所属NVR"}
name={"nvr_id"}
rules={[{ required: true, message: "所属NVR不能为空" }]}
>
<Select placeholder="请选择" allowClear options={nvrData} />
</Form.Item>
</div>
<div className="row-line">
<Form.Item
label={"设备号"}
name={"device_code"}
rules={[{ required: true, message: "设备号不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
</div>
<div className="row-line berth-container">
<Form.Item label={<span className="required">通道号</span>}>
<Transfer
dataSource={berthData}
titles={["未选择", "已选择"]}
targetKeys={berthSelectData}
selectedKeys={selectedKeys}
onChange={onTransferChange}
onSelectChange={onTransferSelectChange}
render={(item) => item.title}
<div className="row-line">
<Form.Item
label={"NVR类型"}
name={"nvr_type"}
rules={[{ required: true, message: "NVR类型不能为空" }]}
>
<Select
placeholder="请选择"
options={[{label: '非国标NVR', value: 1} , {label: '国标NVR', value: 2}]}
/>
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.nvr_type !== currentValues.nvr_type
}
>
{({ getFieldValue }) => {
return getFieldValue("nvr_type") == 1 ? (
<Form.Item
label={"所属NVR"}
name={"nvr_id"}
rules={[{ required: true, message: "所属NVR不能为空" }]}
>
<Select placeholder="请选择" allowClear options={nvrData} />
</Form.Item>
) : (
<Form.Item
label={"所属NVR"}
name={"nvr_id"}
rules={[{ required: true, message: "所属NVR不能为空" }]}
>
<Select placeholder="请选择" allowClear options={nvrGbData}
onChange={(e)=>{
if(form.getFieldValue("nvr_type") == 1){
getChannelByNvr(e)
}
}
} />
</Form.Item>
);
}}
</Form.Item>
</div>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.nvr_type !== currentValues.nvr_type || prevValues.nvr_id !== currentValues.nvr_id
}
>
{({ getFieldValue }) => {
return getFieldValue("nvr_type") == 1 ? (
<div className="row-line berth-container">
<Form.Item label={<span className="required">通道号</span>}>
<Transfer
dataSource={berthData}
titles={["未选择", "已选择"]}
targetKeys={berthSelectData}
selectedKeys={selectedKeys}
onChange={onTransferChange}
onSelectChange={onTransferSelectChange}
render={(item) => item.title}
/>
</Form.Item>
</div>
) : null;
}}
</Form.Item>
<Form.Item className="submitBtn">
<Button type="primary" className="submit" htmlType="submit">
确定
@ -749,6 +884,32 @@ function OutMonitorMgm(props) {
</div>
</div>
</Modal>
<Modal
open={videoModalVisible}
width={1200}
onCancel={()=>{setVideoModalVisible(false); setPlayType('1'); stopIntervalToClose()}}
footer={null}
title={rowData.device_name}
>
<div className="out-monitor-switch-line">
<span onClick={()=>{setPlayType('1')}}>实时</span>&emsp;<span onClick={()=>{setPlayType('2')}}>回放</span>
</div>
{
playType == '1' ?
<div>
{
rowData.id == oneVideoRealtimeUrlInfo.id ?
<VideoPlay videoType="flv" ref={videoRef} videoUrl={oneVideoRealtimeUrlInfo.url} ></VideoPlay>
: null
}
</div>
:
<div >
<HistoryTable id={rowData.id} />
</div>
}
</Modal>
</div>
</>
);

166
src/pages/OutRoadMgm/OutDeviceMgm/OutNvrMgm/loadable.jsx

@ -31,6 +31,7 @@ function OutNvrMgm(props) {
name: "", //
operator_id: "", //
road_id: "", //
nvr_type: 0
};
//
const [pageInfo, setPageInfo] = useState({
@ -275,26 +276,51 @@ function OutNvrMgm(props) {
title: "设备名称",
dataIndex: "name",
align: "center",
width: 150,
ellipsis: true
},
{
title: "区域",
dataIndex: "area_name",
align: "center",
width: 150,
ellipsis: true
},
{
title: "所属车场",
dataIndex: "road_name",
align: "center",
width: 150,
ellipsis: true
},
{
title: "NVR类型",
dataIndex: "nvr_type",
align: "center",
render: (val) => {
return <>{val == 2 ? '国标' : '非国标'}</>;
},
width: 100,
},
{
title: "国际编号",
dataIndex: "standard_code",
align: "center",
width: 150,
ellipsis: true
},
{
title: "IP地址",
dataIndex: "ip_address",
align: "center",
width: 150,
ellipsis: true
},
{
title: "端口号",
dataIndex: "port",
align: "center",
width: 80,
},
{
title: "视频端口号",
@ -306,22 +332,27 @@ function OutNvrMgm(props) {
title: "用户名",
dataIndex: "user_name",
align: "center",
width: 100,
},
{
title: "密码",
dataIndex: "password",
align: "center",
width: 150,
ellipsis: true
},
{
title: "更新时间",
dataIndex: "update_time",
align: "center",
width: 110,
width: 150,
ellipsis: true
},
{
title: "操作",
align: "center",
width: 140,
fixed: 'right',
render: (val, row, index) => {
return (
<Dropdown
@ -584,6 +615,19 @@ function OutNvrMgm(props) {
onChange={(v) => setFormData({ ...formData, road_id: v.target.value })}
/>
</div>
<div className="yisa-search">
<label>NVR类型</label>
<Select
className="form-con"
placeholder="请选择"
allowClear={false}
options={[{label: '全部',value: 0},{label: '非国标',value: 1},{label: '国标',value: 2}]}
value={formData?.nvr_type || 0}
onChange={(v) => {
setFormData({ ...formData, nvr_type: v });
}}
/>
</div>
<div className="form-btn">
<Button
className="reset"
@ -706,13 +750,6 @@ function OutNvrMgm(props) {
<Input disabled />
</Form.Item>
<Form.Item
label={"IP地址"}
name={"ip_address"}
rules={[{ required: true, message: "ip地址不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
{/* <Form.Item
label={"NVR类型"}
name={"nvr_type"}
rules={[{ required: true, message: "NVR类型不能为空" }]}
@ -721,42 +758,89 @@ function OutNvrMgm(props) {
placeholder="请选择"
options={[{label: '非国标NVR', value: '1'} , {label: '国标NVR', value: '2'}]}
/>
</Form.Item> */}
</div>
<div className="row-line">
<Form.Item
label={"端口号"}
name={"port"}
rules={[{ required: true, message: "端口号不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
<Form.Item
label={"视频端口号"}
name={"video_port"}
rules={[{ required: true, message: "视频端口号不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
</div>
<div className="row-line">
<Form.Item
label={"用户名"}
name={"user_name"}
rules={[{ required: true, message: "用户名不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.nvr_type !== currentValues.nvr_type
}
>
{({ getFieldValue }) => {
return getFieldValue("nvr_type") == 2 ? (
<div className="row-line">
<Form.Item
label={"国标编号"}
name={"standard_code"}
rules={[{ required: true, message: "国标编号不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
</div>
) : null;
}}
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.nvr_type !== currentValues.nvr_type
}
>
{({ getFieldValue }) => {
return getFieldValue("nvr_type") == 1 ? (
<>
<div className="row-line">
<Form.Item
label={"IP地址"}
name={"ip_address"}
rules={[{ required: true, message: "ip地址不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
<Form.Item
label={"端口号"}
name={"port"}
rules={[{ required: true, message: "端口号不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
<Form.Item
label={"密码"}
name={"password"}
rules={[{ required: true, message: "密码不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
</div>
</div>
<div className="row-line">
<Form.Item
label={"视频端口号"}
name={"video_port"}
rules={[{ required: true, message: "视频端口号不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
<Form.Item
label={"用户名"}
name={"user_name"}
rules={[{ required: true, message: "用户名不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
</div>
<div className="row-line">
<Form.Item
label={"密码"}
name={"password"}
rules={[{ required: true, message: "密码不能为空" }]}
>
<Input autoComplete="off" />
</Form.Item>
</div>
</>
) : null;
}}
</Form.Item>
<Form.Item className="submitBtn">
<Button type="primary" className="submit" htmlType="submit">
确定

23
src/services/search.js

@ -851,6 +851,25 @@ const getChannelByNvr = (params) => {
data: params,
});
};
// 路外 根据起止时间查指定国标设备的历史视频列表
const getHistoryVideoList = (params) => {
return ajax({
url: "/api/orp/nvr/get_history_list",
type: "post",
data: params,
});
};
// 路外 查看监控视频
const getOneVideoPlay = (params) => {
return ajax({
url: "/api/orp/nvr/get_video_play",
type: "post",
data: params,
});
};
const getAllBrandNameList = (params) => {
return ajax({
url: "/api/bpm/device/get_all_brand",
@ -1367,5 +1386,7 @@ export default {
getOutMonitorList,
monitorOutAdd,
monitorOutEdit,
getChannelByNvr
getChannelByNvr,
getHistoryVideoList,
getOneVideoPlay
}
Loading…
Cancel
Save