Browse Source

Merge branch 'dev_trial' of https://gitea.anxinyun.cn/free-sun/FS-IOT into dev_trial

release_1.1.1
巴林闲侠 2 years ago
parent
commit
562bc0746e
  1. 2
      code/VideoAccess-VCMP/web/client/src/components/index.js
  2. 121
      code/VideoAccess-VCMP/web/client/src/components/setup.jsx
  3. 700
      code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx
  4. 191
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/setup.jsx
  5. 32
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/camera.jsx
  6. 27
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/nvr.jsx
  7. 5
      code/VideoAccess-VCMP/web/client/src/sections/monitor/containers/videoPlayCross.jsx
  8. 299
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushModal.jsx
  9. 570
      code/VideoAccess-VCMP/web/client/src/sections/offline/containers/carrierpigeon.jsx
  10. 605
      code/VideoAccess-VCMP/web/client/src/sections/offline/containers/statuscode.jsx

2
code/VideoAccess-VCMP/web/client/src/components/index.js

@ -4,6 +4,7 @@ import Coming from './coming'
import ReminderBox from './reminderBox' import ReminderBox from './reminderBox'
import VideoPlay from './videoPlayer/videoPlay' import VideoPlay from './videoPlayer/videoPlay'
import VideoPlayModal from './videoPlayer/videoPlayModal' import VideoPlayModal from './videoPlayer/videoPlayModal'
import Setup from './setup'
export { export {
SimpleFileDownButton, SimpleFileDownButton,
@ -11,4 +12,5 @@ export {
ReminderBox, ReminderBox,
VideoPlay, VideoPlay,
VideoPlayModal, VideoPlayModal,
Setup
}; };

121
code/VideoAccess-VCMP/web/client/src/components/setup.jsx

@ -0,0 +1,121 @@
import React, { useState, useEffect } from "react";
import {
Modal,
CheckboxGroup,
Checkbox,
} from "@douyinfe/semi-ui";
function Setup(props) {
const {
close,
tableType,
tableList
} = props;
const [check, setCheck] = useState([]);
const checkboxcss = { width: "25%", height: 16, margin: "0 0 20px 0" };
useEffect(() => {
//
const checkItem = localStorage.getItem(tableType);
setCheck(checkItem?JSON.parse(checkItem) : [])
ischeck();
}, []);
function ischeck(value) {
if (check.length >= 8) {
if (check.includes(value)) {
return false;
} else {
return true;
}
}
}
return (
<Modal
title={
<div>
表格属性设置
<span
style={{
width: 50,
lineHeight: "19px",
display: "inline-block",
color: "white",
textAlign: "center",
marginLeft: 6,
background:
check.length == 8
? "rgba(40, 123, 255, 1)"
: "rgba(176, 176, 176, 1)",
}}
>
{check.length}/8
</span>
</div>
}
visible={true}
style={{ width: 600 }}
onOk={() => {
localStorage.setItem(tableType, JSON.stringify(check));
close();
}}
onCancel={() => {
close();
}}
>
<CheckboxGroup
style={{ width: "100%", fontSize: 14 }}
key="primary1"
direction="horizontal"
defaultValue={check}
aria-label="表格属性设置"
onChange={(check) => {
setCheck(check);
ischeck();
}}
>
{tableList.map((item,index)=>{
return(
<div
key={index}
style={{
width: 550,
border: "1px solid #EAEAEA",
padding: "0px 5px",
borderRadius: 4,
marginBottom: "20px",
}}
>
<div
style={{
borderBottom: "1px solid #EAEAEA",
marginLeft: "10px",
padding: "8px 0px",
}}
>
{item.title}
</div>
<div style={{ padding: "15px 12px", width: 530 }}>
{item.list.map((itm) => {
return (
<Checkbox
key={itm.value}
value={itm.value}
style={checkboxcss}
disabled={ischeck(itm.value)}
>
{itm.name}
</Checkbox>
);
})}
</div>
</div>
)})}
</CheckboxGroup>
</Modal>
);
}
export default Setup;

700
code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx

@ -15,371 +15,369 @@ const yingshiCloseSoundKey = 'closeSound'
const yingshiOpenSoundKey = 'openSound' const yingshiOpenSoundKey = 'openSound'
const VideoPlay = ({ const VideoPlay = ({
height, width, containerId = 'myPlayer', height, width, containerId = 'myPlayer',
// playUrl, // playUrl,
name, name,
videoObj, videoObj,
// videoObj = { // videoObj = {
// type: 'yingshi', // type: 'yingshi',
// audio: false, // audio: false,
// serialNo: 'G75922040', // // serialNo: 'G75922040', //
// channelNo: 1, // // channelNo: 1, //
// yingshiToken: 'at.3j6eyqbn0g5xvcut73v0rzdu1nh0gnxx-4ua03m82o9-12u1t9g-rtzndpyds', // // yingshiToken: 'at.3j6eyqbn0g5xvcut73v0rzdu1nh0gnxx-4ua03m82o9-12u1t9g-rtzndpyds', //
// playUrlSd: 'ezopen://open.ys7.com/G75922040/1.live', // // playUrlSd: 'ezopen://open.ys7.com/G75922040/1.live', //
// // playUrl: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003', // // playUrl: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003',
// playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live', // playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live',
// // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec', // // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec',
// }, // },
// videoObj = { // videoObj = {
// type: 'cascade', // type: 'cascade',
// audio: false, // audio: false,
// serialNo: '34020000001310000001', // // serialNo: '34020000001310000001', //
// topSerialNo: '34020000001110000077', // // topSerialNo: '34020000001110000077', //
// playUrlSd: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000001', // // playUrlSd: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000001', //
// // playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live', // // playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live',
// // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec', // // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec',
// }, // },
// //
iotVideoServer iotVideoServer
}) => { }) => {
console.log(videoObj); const [jessibuca, setjessibuca] = useState(null)
const [jessibuca, setjessibuca] = useState(null) const [isPlaying, setIsPlaying] = useState(false)
const [isPlaying, setIsPlaying] = useState(false) const [operationState, setoperationState] = useState()
const [operationState, setoperationState] = useState() const [voiceDisY, setVoiceDisY] = useState(0)
const [voiceDisY, setVoiceDisY] = useState(0) const [processDisX, setProcessDisX] = useState(0)
const [processDisX, setProcessDisX] = useState(0) const [isAdjustProcess, setIsAdjustProcess] = useState(false)
const [isAdjustProcess, setIsAdjustProcess] = useState(false) const [histroyTime, setHistroyTime] = useState([])
const [histroyTime, setHistroyTime] = useState([]) const [histroyBegain, setHistroyBegain] = useState()
const [histroyBegain, setHistroyBegain] = useState() const [roll, setRoll] = useState()//
const [roll, setRoll] = useState()// const [resolution, setResolution] = useState('sd') // sd hd
const [resolution, setResolution] = useState('sd') // sd hd
// ifream
// ifream const [yingshiPrepare, setYingshiPrepare] = useState('')
const [yingshiPrepare, setYingshiPrepare] = useState('')
const operationRef = useRef(null)
const operationRef = useRef(null) const processChangeTimeoutRef = useRef(null)
const processChangeTimeoutRef = useRef(null) // ifream
// ifream const yingshiPrepareRef = useRef(null)
const yingshiPrepareRef = useRef(null)
useEffect(() => {
useEffect(() => { setRoll(false)
setRoll(false)
}, [resolution]); }, [resolution]);
const changeSelectState = (key) => { const changeSelectState = (key) => {
if (videoObj.type == 'yingshi' && yingshiPrepareRef.current) { if (videoObj.type == 'yingshi' && yingshiPrepareRef.current) {
return
}
const nextOperationState = JSON.parse(JSON.stringify(operationRef.current))
if (key == 'histroy' && nextOperationState.histroy.select) {
//
setProcessDisX(0)
setHistroyTime([])
}
for (let k in nextOperationState) {
if (k == key) {
nextOperationState[k].select = !nextOperationState[k].select
} else if (k !== 'fullScreen') {
nextOperationState[k].select = false
}
}
operationRef.current = nextOperationState
if (operationRef.current.histroy.select && histroyTime.length == 0) {
setHistroyTime([moment().subtract(72, 'hours').format(timeFormat), moment().format(timeFormat)])
}
setoperationState(nextOperationState)
}
//
const operation = [{
key: 'control',
click: () => {
changeSelectState('control')
}
}, {
key: 'talk',
hide: !(videoObj.type == 'yingshi'),
click: () => {
changeSelectState('talk')
}
}, {
key: 'fullScreen',
click: () => {
if (yingshiPrepareRef.current) {
return return
} }
changeSelectState('fullScreen') const nextOperationState = JSON.parse(JSON.stringify(operationRef.current))
let player = document.getElementById('vcmp_videoplay') if (key == 'histroy' && nextOperationState.histroy.select) {
if (screenfull.isEnabled) { //
screenfull.toggle(player); setProcessDisX(0)
} setHistroyTime([])
} }
}, {
key: 'histroy', for (let k in nextOperationState) {
hide: !Boolean(videoObj.replayUrl), if (k == key) {
click: () => { nextOperationState[k].select = !nextOperationState[k].select
changeSelectState('histroy') } else if (k !== 'fullScreen') {
yingshiPrepareRef.current = 'play' nextOperationState[k].select = false
setYingshiPrepare('play')
}
},]
useEffect(() => {
if (videoObj.type == 'yingshi') {
yingshiPrepareRef.current = 'play'
setYingshiPrepare('play')
} else {
createJessibuca()
}
let nextOperationState = {}
for (let p of operation) {
nextOperationState[p.key] = {
select: false
}
}
setoperationState(nextOperationState)
operationRef.current = nextOperationState
//
screenfull.on('change', () => {
if (screenfull.isFullscreen && operationRef.current && !operationRef.current['fullScreen'].select) {
changeSelectState('fullScreen')
}
if (!screenfull.isFullscreen && operationRef.current && operationRef.current['fullScreen'].select) {
changeSelectState('fullScreen')
}
});
// ifream
const listenYingshiMessage = async (e) => {
const { data, origin } = e
console.log(e);
if (origin !== 'https://open.ys7.com') return
if (data.type == "handleSuccess") {
setRoll(true)
if (yingshiPrepareRef.current == 'play') {
setIsPlaying(true)
} }
} else if (data.type == yingshiOpenSoundKey && data.code == 0) { }
if (yingshiPrepareRef.current == yingshiOpenSoundKey) { operationRef.current = nextOperationState
setVoiceDisY(30)
if (operationRef.current.histroy.select && histroyTime.length == 0) {
setHistroyTime([moment().subtract(72, 'hours').format(timeFormat), moment().format(timeFormat)])
}
setoperationState(nextOperationState)
}
//
const operation = [{
key: 'control',
click: () => {
changeSelectState('control')
}
}, {
key: 'talk',
hide: !(videoObj.type == 'yingshi'),
click: () => {
changeSelectState('talk')
}
}, {
key: 'fullScreen',
click: () => {
if (yingshiPrepareRef.current) {
return
} }
} if (data.type == yingshiCloseSoundKey && data.code == 0) { changeSelectState('fullScreen')
if (yingshiPrepareRef.current == yingshiCloseSoundKey) { let player = document.getElementById('vcmp_videoplay')
setVoiceDisY(0) if (screenfull.isEnabled) {
screenfull.toggle(player);
} }
} }
yingshiPrepareRef.current = null }, {
setYingshiPrepare(null) key: 'histroy',
} hide: !Boolean(videoObj.replayUrl),
if (videoObj.type == 'yingshi') { click: () => {
window.addEventListener('message', listenYingshiMessage); changeSelectState('histroy')
}
return () => {
window.removeEventListener('message', listenYingshiMessage);
}
}, [])
useEffect(() => {
if (histroyTime.length) {
setHistroyBegain(histroyTime[0])
document.getElementById('process_point').style.left = 0 + 'px'; //
if (videoObj.type == 'yingshi') {
yingshiPrepareRef.current = 'play' yingshiPrepareRef.current = 'play'
setYingshiPrepare('play') setYingshiPrepare('play')
} }
} else { },]
setHistroyBegain(null)
} useEffect(() => {
}, [histroyTime]) if (videoObj.type == 'yingshi') {
useEffect(() => { yingshiPrepareRef.current = 'play'
if (operationState && operationState.histroy.select) { setYingshiPrepare('play')
if (isAdjustProcess) { } else {
// createJessibuca()
if (processChangeTimeoutRef.current) { }
clearTimeout(processChangeTimeoutRef.current) let nextOperationState = {}
for (let p of operation) {
nextOperationState[p.key] = {
select: false
}
}
setoperationState(nextOperationState)
operationRef.current = nextOperationState
//
screenfull.on('change', () => {
if (screenfull.isFullscreen && operationRef.current && !operationRef.current['fullScreen'].select) {
changeSelectState('fullScreen')
}
if (!screenfull.isFullscreen && operationRef.current && operationRef.current['fullScreen'].select) {
changeSelectState('fullScreen')
} }
processChangeTimeoutRef.current = setTimeout(() => { });
setHistroyBegain(
moment(histroyTime[0]) // ifream
.add( const listenYingshiMessage = async (e) => {
Math.abs(moment(histroyTime[0]).diff(moment(histroyTime[1]), 'seconds')) * (processDisX / document.getElementById('process_point').parentElement.offsetWidth), const { data, origin } = e
'second' console.log(e);
) if (origin !== 'https://open.ys7.com') return
.format(timeFormat) if (data.type == "handleSuccess") {
) setRoll(true)
if (videoObj.type == 'yingshi') { if (yingshiPrepareRef.current == 'play') {
yingshiPrepareRef.current = 'play' setIsPlaying(true)
setYingshiPrepare('play') }
} } else if (data.type == yingshiOpenSoundKey && data.code == 0) {
}, 300) if (yingshiPrepareRef.current == yingshiOpenSoundKey) {
} else { setVoiceDisY(30)
// }
document.getElementById('process_point').style.left = processDisX - 4.5 + 'px' } if (data.type == yingshiCloseSoundKey && data.code == 0) {
} if (yingshiPrepareRef.current == yingshiCloseSoundKey) {
} setVoiceDisY(0)
}, [processDisX]) }
}
const createJessibuca = async () => { yingshiPrepareRef.current = null
if (videoObj.type != 'yingshi') { setYingshiPrepare(null)
try { }
// const inviteRes = await IotVideoServerRequest.get(VideoServeApi.invite, { if (videoObj.type == 'yingshi') {
// id: '36011200002002021114', window.addEventListener('message', listenYingshiMessage);
// channel: '36011200581314002900' }
// }).then(res => { return () => {
// console.log(res); window.removeEventListener('message', listenYingshiMessage);
// }, err => { }
// console.log(err); }, [])
// })
useEffect(() => {
const inviteRes_ = await request.get(`${iotVideoServer}/api/gb28181/invite?id=${videoObj.topSerialNo}&channel=${videoObj.serialNo}`) if (histroyTime.length) {
} catch (error) { setHistroyBegain(histroyTime[0])
console.log(error.response); document.getElementById('process_point').style.left = 0 + 'px'; //
} if (videoObj.type == 'yingshi') {
yingshiPrepareRef.current = 'play'
setYingshiPrepare('play')
let $container = document.getElementById(containerId); }
const jessibuca = new window.Jessibuca({ } else {
container: $container, setHistroyBegain(null)
videoBuffer: 0.2, // }
isResize: false, }, [histroyTime])
text: "", useEffect(() => {
loadingText: "加载中", if (operationState && operationState.histroy.select) {
debug: true, if (isAdjustProcess) {
showBandwidth: false, // //
operateBtns: { if (processChangeTimeoutRef.current) {
fullscreen: false, clearTimeout(processChangeTimeoutRef.current)
screenshot: false, }
play: false, processChangeTimeoutRef.current = setTimeout(() => {
audio: false, setHistroyBegain(
}, moment(histroyTime[0])
forceNoOffscreen: false, .add(
isNotMute: false, Math.abs(moment(histroyTime[0]).diff(moment(histroyTime[1]), 'seconds')) * (processDisX / document.getElementById('process_point').parentElement.offsetWidth),
}); 'second'
setjessibuca(jessibuca) )
play({ jessibuca }) .format(timeFormat)
} )
} if (videoObj.type == 'yingshi') {
yingshiPrepareRef.current = 'play'
const yingshiOperation = (operation) => { setYingshiPrepare('play')
document.getElementById(containerId).contentWindow.postMessage(operation, yingshiUrl) }
// setIsPlaying(operation == 'play') }, 300)
} } else {
//
const play = (params) => { document.getElementById('process_point').style.left = processDisX - 4.5 + 'px'
if (videoObj.type == 'yingshi') { }
yingshiOperation('play') }
} else if ((params.jessibuca || jessibuca) && videoObj.playUrlSd) { }, [processDisX])
const jes = params.jessibuca || jessibuca
jes.play(videoObj.playUrlSd); const createJessibuca = async () => {
setIsPlaying(true) if (videoObj.type != 'yingshi') {
} try {
} // const inviteRes = await IotVideoServerRequest.get(VideoServeApi.invite, {
// id: '36011200002002021114',
const pause = () => { // channel: '36011200581314002900'
if (videoObj.type == 'yingshi') { // }).then(res => {
// yingshiOperation('stop') // console.log(res);
} else if (jessibuca) { // }, err => {
jessibuca.pause(); // console.log(err);
setIsPlaying(false) // })
}
} const inviteRes_ = await request.get(`${iotVideoServer}/api/gb28181/invite?id=${videoObj.topSerialNo}&channel=${videoObj.serialNo}`)
} catch (error) {
const closeSound = () => { console.log(error.response);
if (videoObj.type == 'yingshi') { }
yingshiPrepareRef.current = yingshiCloseSoundKey
setYingshiPrepare(yingshiCloseSoundKey)
yingshiOperation(yingshiCloseSoundKey) let $container = document.getElementById(containerId);
} const jessibuca = new window.Jessibuca({
} container: $container,
videoBuffer: 0.2, //
const openSound = () => { isResize: false,
if (videoObj.type == 'yingshi') { text: "",
yingshiPrepareRef.current = yingshiOpenSoundKey loadingText: "加载中",
setYingshiPrepare(yingshiOpenSoundKey) debug: true,
yingshiOperation(yingshiOpenSoundKey) showBandwidth: false, //
} operateBtns: {
} fullscreen: false,
screenshot: false,
play: false,
return ( audio: false,
<> },
<div className="vcmp_videoplay" style={{ height: height || '100%', width: width || '100%', overflow: 'hidden' }}> forceNoOffscreen: false,
<div id="vcmp_videoplay" style={{ position: 'relative', display: 'flex', height: '100%', width: '100%' }}> isNotMute: false,
{/* 顶部信息 */} });
<VideoHeader setjessibuca(jessibuca)
operationState={operationState} changeSelectState={changeSelectState} play({ jessibuca })
histroyTime={histroyTime} }
setoperationState={setoperationState} name={name} }
roll={roll}
showTime={ const yingshiOperation = (operation) => {
videoObj.type == 'yingshi' && yingshiPrepare == 'play' ? document.getElementById(containerId).contentWindow.postMessage(operation, yingshiUrl)
null : (histroyBegain || moment()) // setIsPlaying(operation == 'play')
} }
setProcessDisX={setProcessDisX}
content={videoObj.content} const play = (params) => {
/> if (videoObj.type == 'yingshi') {
{/* 视频内容 */} yingshiOperation('play')
{ } else if ((params.jessibuca || jessibuca) && videoObj.playUrlSd) {
videoObj.type == 'yingshi' ? const jes = params.jessibuca || jessibuca
<iframe jes.play(videoObj.playUrlSd);
frameBorder="0" setIsPlaying(true)
id={containerId} }
src={ }
`${yingshiUrl}?audio=${videoObj.audio && operationState && !operationState.histroy.select ? '1' : '0'}&url=${operationState && operationState.histroy.select && histroyBegain ? `${videoObj.replayUrl}?begin=${moment(histroyBegain).format("YYYYMMDDHHmmss")}&end=${moment(histroyTime[1]).format("YYYYMMDDHHmmss")}` : resolution == 'sd' ? videoObj.playUrlSd : videoObj.playUrlHd}&autoplay=${'1'}&accessToken=${videoObj.yingshiToken}`
const pause = () => {
if (videoObj.type == 'yingshi') {
// yingshiOperation('stop')
} else if (jessibuca) {
jessibuca.pause();
setIsPlaying(false)
}
}
const closeSound = () => {
if (videoObj.type == 'yingshi') {
yingshiPrepareRef.current = yingshiCloseSoundKey
setYingshiPrepare(yingshiCloseSoundKey)
yingshiOperation(yingshiCloseSoundKey)
}
}
const openSound = () => {
if (videoObj.type == 'yingshi') {
yingshiPrepareRef.current = yingshiOpenSoundKey
setYingshiPrepare(yingshiOpenSoundKey)
yingshiOperation(yingshiOpenSoundKey)
}
}
return (
<>
<div className="vcmp_videoplay" style={{ height: height ? height : '100%', width: width || '100%', overflow: 'hidden' }}>
<div id="vcmp_videoplay" style={{ position: 'relative', display: 'flex', height: '100%', width: '100%' }}>
{/* 顶部信息 */}
<VideoHeader
operationState={operationState} changeSelectState={changeSelectState}
histroyTime={histroyTime}
setoperationState={setoperationState} name={name}
roll={roll}
showTime={
videoObj.type == 'yingshi' && yingshiPrepare == 'play' ?
null : (histroyBegain || moment())
} }
// https://open.ys7.com/doc/zh/book/index/live_proto.html setProcessDisX={setProcessDisX}
// {width: 400px;height: 300px;} content={videoObj.content}
width={'100%'} />
height={'100%'} {/* 视频内容 */}
allowFullScreen {
wmode="transparent" videoObj.type == 'yingshi' ?
style={{ pointerEvents: 'none' }} <iframe
/> : frameBorder="0"
<div id={containerId}
id={containerId} src={
style={{ `${yingshiUrl}?audio=${videoObj.audio && operationState && !operationState.histroy.select ? '1' : '0'}&url=${operationState && operationState.histroy.select && histroyBegain ? `${videoObj.replayUrl}?begin=${moment(histroyBegain).format("YYYYMMDDHHmmss")}&end=${moment(histroyTime[1]).format("YYYYMMDDHHmmss")}` : resolution == 'sd' ? videoObj.playUrlSd : videoObj.playUrlHd}&autoplay=${'1'}&accessToken=${videoObj.yingshiToken}`
height: '100%', width: '100%' }
}}> // https://open.ys7.com/doc/zh/book/index/live_proto.html
// {width: 400px;height: 300px;}
</div> width={'100%'}
} height={'100%'}
allowFullScreen
{/* 下方操作栏 */} wmode="transparent"
<VideoOperation style={{ pointerEvents: 'none' }}
operationState={operationState} operation={operation} /> :
voiceDisY={voiceDisY} setVoiceDisY={setVoiceDisY} <div
processDisX={processDisX} setProcessDisX={setProcessDisX} id={containerId}
isAdjustProcess={isAdjustProcess} setIsAdjustProcess={setIsAdjustProcess} style={{
resolution={resolution} setResolution={setResolution} height: '100%', width: '100%'
histroyTime={histroyTime} setHistroyTime={setHistroyTime} }}>
histroyBegain={histroyBegain}
play={play} pause={pause} closeSound={closeSound} openSound={openSound} </div>
isPlaying={isPlaying} }
videoObj={videoObj}
setYingshiPrepare={setYingshiPrepare} {/* 下方操作栏 */}
yingshiPrepareRef={yingshiPrepareRef} <VideoOperation
/> operationState={operationState} operation={operation}
</div> voiceDisY={voiceDisY} setVoiceDisY={setVoiceDisY}
processDisX={processDisX} setProcessDisX={setProcessDisX}
isAdjustProcess={isAdjustProcess} setIsAdjustProcess={setIsAdjustProcess}
resolution={resolution} setResolution={setResolution}
histroyTime={histroyTime} setHistroyTime={setHistroyTime}
histroyBegain={histroyBegain}
play={play} pause={pause} closeSound={closeSound} openSound={openSound}
isPlaying={isPlaying}
videoObj={videoObj}
setYingshiPrepare={setYingshiPrepare}
yingshiPrepareRef={yingshiPrepareRef}
/>
</div>
</div> </div>
</> </>
) )
} }
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth, global } = state; const { auth, global } = state;
console.log('global',global); return {
return { user: auth.user,
user: auth.user, iotVideoServer: global.iotVideoServer,
iotVideoServer: global.iotVideoServer, };
};
} }
export default connect(mapStateToProps)(VideoPlay); export default connect(mapStateToProps)(VideoPlay);

191
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/setup.jsx

@ -1,191 +0,0 @@
import React, { useState, useEffect } from "react";
import {
Modal,
CheckboxGroup,
Checkbox,
} from "@douyinfe/semi-ui";
function Setup(props) {
const {
visible,
close,
SETUPS,
CAMERAS,
cameraSetup,
} = props;
const [check, setCheck] = useState([]);
const checkboxcss = { width: "25%", height: 16, margin: "0 0 20px 0" };
useEffect(() => {
//
const nvrItem = localStorage.getItem(SETUPS);
const cameraItem = localStorage.getItem(CAMERAS);
if (cameraSetup) {
setCheck(cameraItem ? JSON.parse(cameraItem) : []);
} else {
setCheck(nvrItem ? JSON.parse(nvrItem) : []);
}
ischeck();
}, []);
const equipmentNVR = [
{ name: "设备厂家", value: "manufactor" },
{ name: "添加账号", value: "accountNumber" },
{ name: "通道数", value: "passageway" },
{ name: "端口", value: "port" },
{ name: "设备状态", value: "state" },
{ name: "创建时间", value: "time" },
];
const projectNVR = [
{ name: "项目名称", value: "name" },
{ name: "pcode", value: "pcode" },
{ name: "结构物", value: "structure" },
];
const equipmentCamera = [
{ name: "设备厂家", value: "manufactor" },
{ name: "接入类型", value: "type" },
{ name: "设备状态", value: "state" },
{ name: "云台支持", value: "support" },
{ name: "内存卡信息", value: "memoryCard" },
{ name: "设备创建时间", value: "time" },
{ name: "设备添加账号", value: "account" },
];
const projectCamera = [
{ name: "项目名称", value: "name" },
{ name: "pcode", value: "pcode" },
{ name: "结构物", value: "structure" },
{ name: "测点", value: "measuringPoint" },
{ name: "监测因素", value: "factor" },
];
function ischeck(value) {
if (check.length >= 8) {
if (check.includes(value)) {
return false;
} else {
return true;
}
}
}
return (
<Modal
title={
<div>
表格属性设置
<span
style={{
width: 50,
lineHeight: "19px",
display: "inline-block",
color: "white",
textAlign: "center",
marginLeft: 6,
background:
check.length == 8
? "rgba(40, 123, 255, 1)"
: "rgba(176, 176, 176, 1)",
}}
>
{check.length}/8
</span>
</div>
}
visible={visible}
style={{ width: 600 }}
onOk={() => {
cameraSetup
? localStorage.setItem(CAMERAS, JSON.stringify(check))
: localStorage.setItem(SETUPS, JSON.stringify(check));
close();
}}
onCancel={() => {
close();
}}
>
<CheckboxGroup
style={{ width: "100%", fontSize: 14 }}
key="primary1"
direction="horizontal"
defaultValue={check}
aria-label="表格属性设置"
onChange={(check) => {
setCheck(check);
ischeck();
}}
>
<div
style={{
width: 550,
border: "1px solid #EAEAEA",
padding: "0px 5px",
borderRadius: 4,
marginBottom: "20px",
}}
>
<div
style={{
borderBottom: "1px solid #EAEAEA",
marginLeft: "10px",
padding: "8px 0px",
}}
>
设备信息
</div>
<div style={{ padding: "15px 12px", width: 530 }}>
{(cameraSetup ? equipmentCamera : equipmentNVR).map((item) => {
return (
<Checkbox
key={item.value}
value={item.value}
style={checkboxcss}
disabled={ischeck(item.value)}
>
{item.name}
</Checkbox>
);
})}
</div>
</div>
<div
style={{
width: 550,
border: "1px solid #EAEAEA",
padding: "0px 5px",
borderRadius: 4,
}}
>
<div
style={{
borderBottom: "1px solid #EAEAEA",
marginLeft: "10px",
padding: "8px 0px",
}}
>
项目信息
</div>
<div style={{ padding: "15px 12px", width: 530 }}>
{(cameraSetup ? projectCamera : projectNVR).map((item) => {
return (
<Checkbox
key={item.value}
value={item.value}
style={checkboxcss}
disabled={ischeck(item.value)}
>
{item.name}
</Checkbox>
);
})}
</div>
</div>
</CheckboxGroup>
</Modal>
);
}
export default Setup;

32
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/camera.jsx

@ -17,7 +17,7 @@ import { SimpleFileDownButton, VideoPlayModal } from "$components";
import "../style.less"; import "../style.less";
import CameraModal from "../components/cameraModal"; import CameraModal from "../components/cameraModal";
import RemarksModal from "../components/remarksModal"; import RemarksModal from "../components/remarksModal";
import Setup from "../components/setup"; import {Setup} from "$components";
import SideSheets from "../components/sideSheet"; import SideSheets from "../components/sideSheet";
import { skeletonScreen } from "../components/skeletonScreen"; import { skeletonScreen } from "../components/skeletonScreen";
import { accessType } from "./nvr"; import { accessType } from "./nvr";
@ -51,7 +51,30 @@ const CameraHeader = (props) => {
const page = useRef(query.page); const page = useRef(query.page);
const deviceClickb = useRef(true) const deviceClickb = useRef(true)
const CAMERAS = "cameras"; const CAMERAS = "cameras";
const tableList = [//
{
title:'设备信息',
list:[
{ name: "设备厂家", value: "manufactor" },
{ name: "接入类型", value: "type" },
{ name: "设备状态", value: "state" },
{ name: "云台支持", value: "support" },
{ name: "内存卡信息", value: "memoryCard" },
{ name: "设备创建时间", value: "time" },
{ name: "设备添加账号", value: "account" },
]
},
{
title:'项目信息',
list:[
{ name: "项目名称", value: "name" },
{ name: "pcode", value: "pcode" },
{ name: "结构物", value: "structure" },
{ name: "测点", value: "measuringPoint" },
{ name: "监测因素", value: "factor" },
]
},
];
useEffect(() => { useEffect(() => {
// //
let isAxyData = props.location.search let isAxyData = props.location.search
@ -771,9 +794,8 @@ const CameraHeader = (props) => {
{setup ? ( {setup ? (
<Setup <Setup
visible={true} tableType={CAMERAS}
CAMERAS={CAMERAS} tableList={tableList}
cameraSetup={cameraSetup}
close={() => { close={() => {
setSetup(false); setSetup(false);
attribute(venderList); attribute(venderList);

27
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/nvr.jsx

@ -5,7 +5,7 @@ import { Button, Form, Table, Pagination, Skeleton, Popconfirm, Popover, Tag, }
import "../style.less"; import "../style.less";
import { ApiTable } from "$utils"; import { ApiTable } from "$utils";
import NvrModal from "../components/nvrModal"; import NvrModal from "../components/nvrModal";
import Setup from "../components/setup"; import {Setup} from "$components";
import SideSheets from "../components/sideSheet"; import SideSheets from "../components/sideSheet";
import { skeletonScreen } from "../components/skeletonScreen"; import { skeletonScreen } from "../components/skeletonScreen";
import { ReminderBox } from "../../../components/index"; import { ReminderBox } from "../../../components/index";
@ -36,6 +36,27 @@ const NvrHeader = (props) => {
const SETUPS = "setups"; const SETUPS = "setups";
const USER = "user" + props.user.id const USER = "user" + props.user.id
const nvrRef = useRef(); // const nvrRef = useRef(); //
const tableList = [//
{
title:'设备信息',
list:[
{ name: "设备厂家", value: "manufactor" },
{ name: "添加账号", value: "accountNumber" },
{ name: "通道数", value: "passageway" },
{ name: "端口", value: "port" },
{ name: "设备状态", value: "state" },
{ name: "创建时间", value: "time" },
]
},
{
title:'项目信息',
list:[
{ name: "项目名称", value: "name" },
{ name: "pcode", value: "pcode" },
{ name: "结构物", value: "structure" },
]
},
];
useEffect(() => { useEffect(() => {
dispatch(actions.equipmentWarehouse.getVender()).then((res) => { dispatch(actions.equipmentWarehouse.getVender()).then((res) => {
@ -575,8 +596,8 @@ const NvrHeader = (props) => {
{setup ? ( {setup ? (
<Setup <Setup
visible={true} tableType={SETUPS}
SETUPS={SETUPS} tableList={tableList}
close={() => { close={() => {
setSetup(false); setSetup(false);
attribute(venderList); attribute(venderList);

5
code/VideoAccess-VCMP/web/client/src/sections/monitor/containers/videoPlayCross.jsx

@ -8,17 +8,19 @@ const VideoPlayCross = (props) => {
const [videoParams, setVideoParams] = useState(null) const [videoParams, setVideoParams] = useState(null)
useEffect(() => { useEffect(() => {
console.log(props);
if (props.location.search) { if (props.location.search) {
const params = qs.parse(props.location.search.slice(1)) const params = qs.parse(props.location.search.slice(1))
if (params.videoObj) { if (params.videoObj) {
console.log(params.videoObj); console.log(params.videoObj);
// params.videoObj = (new Function("return " + params.videoObj))() // params.videoObj = (new Function("return " + params.videoObj))()
params.videoObj = JSON.parse(params.videoObj) params.videoObj = JSON.parse(params.videoObj)
params.height = JSON.parse(params.height)
setVideoParams(params) setVideoParams(params)
return return
} }
} }
console.log(videoParams);
function messageListen (e) { function messageListen (e) {
// //
const { data } = e const { data } = e
@ -34,6 +36,7 @@ const VideoPlayCross = (props) => {
return () => { return () => {
window.removeEventListener('message', messageListen); window.removeEventListener('message', messageListen);
} }
}, []) }, [])
return ( return (
<> <>

299
code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushModal.jsx

@ -0,0 +1,299 @@
import React, { useState, useRef, useEffect, useImperativeHandle } from "react";
import { connect } from "react-redux";
import { Modal, Form, Row, Col, Spin } from "@douyinfe/semi-ui";
import { IconTickCircle } from "@douyinfe/semi-icons";
import moment from "moment";
function pushModal (props) {
const { modalName, pushRef } = props;
const { dispatch, actions, vender, close } = props;
const pushData = props.pushData || {}; //
const form = useRef();
const [visible, setVisible] = useState(false); //
const [isloading, setloading] = useState(false); //loading
const [loadingTip, setloadingTip] = useState("获取中...请稍后..."); //loading tip
const [step, setstep] = useState("none"); //
const [okText, setokText] = useState("测试校验"); //oktext
const [cancelText, setcancelText] = useState("取消"); //text
const [formObj, setformObj] = useState(); //
function showDialog () {
//
setVisible(true);
}
function positionForm (val) {
let zz = /^(-?\d+)(\.\d+)?$/;
if (!val) {
return "请输入或拾取高德经纬度坐标";
} else if (val.split(",").length != 2) {
return "请输入格式为116.354169,39.835452的经纬度坐标";
} else if (!zz.test(val.split(",")[0])) {
return "只能填写数字";
} else if (!zz.test(val.split(",")[1])) {
return "只能填写数字";
} else {
return "";
}
}
function handleOk () {
//
if (step == "none") {
form.current
.validate()
.then((values) => {
//
console.log(values)
let valuesObj = JSON.parse(JSON.stringify(values));
valuesObj.longitude = values.position.split(",")[0];
valuesObj.latitude = values.position.split(",")[1];
delete valuesObj.position;
if (pushData.id) {
valuesObj.id = pushData.id;
}
var front = new moment(); //
setloading(true);
dispatch(
actions.equipmentWarehouse.getCheck({
serialNo: valuesObj.serialNo,
})
).then((res) => {
var after = new moment(); //
var duration = moment.duration(after.diff(front))._data.milliseconds;
if (res.success) {
setTimeout(
() => {
setloadingTip("已完成");
setTimeout(() => {
setstep("block");
setloading(false);
setokText("确认");
setcancelText("上一步");
setloadingTip("获取中...请稍后...");
}, 1000);
},
duration > 2000 ? 0 : 2000 - duration
);
} else {
setTimeout(
() => {
setloadingTip("校验失败");
setTimeout(() => {
setstep("none");
setloading(false);
setokText("测试校验");
setcancelText("取消");
setloadingTip("获取中...请稍后...");
}, 1000);
},
duration > 2000 ? 0 : 2000 - duration
);
}
});
setformObj(valuesObj);
})
.catch((errors) => {
//
console.log("errors", errors);
});
} else {
dispatch(actions.equipmentWarehouse.addchangepush(formObj)).then((res) => {
setVisible(false);
close();
});
}
}
function handleAfterClose () {
//
setstep("none");
setokText("测试校验");
setcancelText("取消");
}
function handleCancel () {
//
if (step == "none") {
setVisible(false);
} else {
setstep("none");
setokText("测试校验");
setcancelText("取消");
}
}
function handleLocation () {
//
window.open("https://lbs.amap.com/tools/picker", "_blank");
}
useImperativeHandle(pushRef, () => ({
//
//aa
pushNumber: () => formObj.serialNo
}));
return (
<>
<div onClick={showDialog}>{modalName == "add" ? "创建推送" : "修改"}</div>
<Modal
title={modalName == "add" ? "创建推送" : "修改"}
okText={okText}
cancelText={cancelText} //
visible={visible}
onOk={handleOk}
width={782}
height={720}
afterClose={handleAfterClose}
onCancel={handleCancel}
>
<Spin tip={loadingTip} spinning={isloading}>
<div
style={{
paddingLeft: 16,
display: step == "none" ? "block" : "none",
}}
>
<Form
allowEmpty
labelPosition="left"
labelAlign="left"
labelWidth="90px"
onValueChange={(values) => console.log(values)}
getFormApi={(formApi) => (form.current = formApi)}
>
<Row>
<Col span={12}>
<Form.Input
maxLength="39"
field="serialNo"
label="设备编号:"
initValue={pushData.serialNo || ""}
placeholder="请输入设备编号"
style={{ width: 149 }}
rules={[{ required: true, message: "请输入设备编号" }]}
/>
</Col>
<Col span={12}>
<Form.InputNumber
formatter={(value) => `${value}`.replace(/\D/g, "")}
hideButtons={true}
maxLength="15"
field="regionCode"
label="行政区区码:"
initValue={pushData.regionCode || ""}
placeholder="请输入行政区区码"
style={{ width: 149 }}
/>
</Col>
<Col span={24}>
<Form.Input
maxLength="36"
field="name"
label="设备名称:"
initValue={pushData.name || ""}
placeholder="请输入设备名称"
style={{ width: 421 }}
rules={[
{
required: true,
message: "请输入设备名称、常用项目或位置定义",
},
]}
/>
</Col>
<Col span={24}>
<Form.Select
label="设备厂家:"
field="venderId"
initValue={pushData.venderId || null}
placeholder="请选择设备厂家"
style={{ width: 421 }}
rules={[{ required: true, message: "请选择设备厂家" }]}
>
{vender.map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.name}
</Form.Select.Option>
))}
</Form.Select>
</Col>
<Col span={24} style={{ display: "flex" }}>
<Form.Input
maxLength="39"
field="position"
label="安装位置:"
initValue={
pushData.longitude && pushData.latitude
? pushData.longitude + "," + pushData.latitude
: ""
}
placeholder="请输入或拾取高德经纬度坐标"
style={{ width: 386 }}
validate={positionForm}
rules={[
{
required: true,
message: "请输入或拾取高德经纬度坐标",
},
]}
/>
<div
style={{
width: 32,
height: 32,
background: "#1859C1",
marginLeft: 4,
display: "flex",
justifyContent: "center",
alignItems: "center",
cursor: "pointer",
marginTop: 12,
borderRadius: 3 + "px",
}}
onClick={handleLocation}
>
<img
src="../../../assets/images/background/location.png"
width={16}
height={20}
/>
</div>
</Col>
</Row>
</Form>
</div>
<div style={{ height: 224, display: step }}>
<div
style={{
paddingTop: 50,
display: "flex",
justifyContent: "center",
}}
>
<IconTickCircle style={{ color: "#04B234", fontSize: 60 }} />
</div>
<div
style={{
marginTop: 20,
display: "flex",
justifyContent: "center",
}}
>
是否确认创建推送
</div>
</div>
</Spin>
</Modal>
</>
);
}
function mapStateToProps (state) {
const { auth, global, members, vender } = state;
return {
loading: members.isRequesting,
user: auth.user,
actions: global.actions,
members: members.data,
vender: vender.data || [], //
};
}
export default connect(mapStateToProps)(pushModal);

570
code/VideoAccess-VCMP/web/client/src/sections/offline/containers/carrierpigeon.jsx

@ -1,20 +1,566 @@
import React, { useEffect } from 'react'; import React, { useState, useEffect, useRef } from "react";
import { connect } from 'react-redux'; import { connect } from "react-redux";
import { Coming } from '$components' import moment from "moment";
import '../style.less' import { Button, Form, Table, Pagination, Skeleton, Popconfirm, Popover, Tag, } from "@douyinfe/semi-ui";
import "../style.less";
import { ApiTable } from "$utils";
import { Setup } from "$components";
import PushModal from "../components/pushModal";
// import SideSheets from "../components/sideSheet";
// import { skeletonScreen } from "../components/skeletonScreen";
// import { ReminderBox } from "../../../components/index";
export const accessType = [
{ name: "萤石云", key: "yingshi" },
{ name: "NVR", key: "nvr" },
{ name: "IPC", key: "ipc" },
{ name: "级联", key: "cascade" },
];
const Carrierpigeon = (props) => { const Carrierpigeon = (props) => {
const { history, dispatch, actions, user, loading, equipmentWarehouseNvr } = props;
const { equipmentWarehouse } = actions;
const [setup, setSetup] = useState(false);
const [sideSheet, setSideSheet] = useState(false);
const [setupp, setSetupp] = useState([]);
const [venderList, setvenderList] = useState([]); //
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [search, setearch] = useState({}); //
const [rowId, setRowId] = useState(); //id
const [reminder, setReminder] = useState(false); //
const api = useRef();
const searchData = useRef(search)
const limits = useRef(); //
const page = useRef(query.page);
const PIGEON = "pigeon";
const USER = "user" + props.user.id
const nvrRef = useRef(); //
const tableList = [//
{
title: '推送信息',
list: [
{ name: "策略类型", value: "PolicyType" },
{ name: "推送机制", value: "PushMechanism" },
{ name: "监听设备数量", value: "DevicesNumber" },
{ name: "累计推送次数", value: "PushNumber" },
]
},
];
useEffect(() => {
dispatch(actions.equipmentWarehouse.getVender()).then((res) => {
setvenderList(res.payload.data);
attribute(res.payload.data);
});
//
localStorage.getItem(PIGEON) == null
? localStorage.setItem(
PIGEON,
JSON.stringify(["PolicyType", "PushMechanism", "DevicesNumber", "PushNumber"])
)
: "";
}, []);
return ( useEffect(() => {
<Coming /> equipmentGetNvr();
) }, [query, search]);
}
const equipmentGetNvr = () => {
searchData.current = { ...query, ...search }
dispatch(equipmentWarehouse.getNvr(searchData.current)).then((res) => {
limits.current = res.payload.data.data.length
});
}
function equipmentStatus (data) {
switch (data) {
case "email":
return "邮件通知"
case "note":
return "短信通知"
default:
return "未知"
}F
}
function colorStatus (data) {
switch (data) {
case "ON":
return "#04B234"
case "ONLINE":
return "#04B234"
case "OFF":
return "rgba(0, 0, 0, 0.45)"
default:
return "#1859C1"
}
}
const columns = [
{
title: "序号",
render: (_, record, index) => {
return index + 1;
},
},
{
title: "策略名称",
dataIndex: "name",
render: (_, r, index) => {
console.log("r:" + r.name);
return r.name
},
},
{
title: "操作",
width: "20%",
dataIndex: "",
render: (_, row) => {
return (
<div style={{ display: "flex" }}>
<Button theme="borderless">
<PushModal
modalName="revise"
/>
</Button>
<Button
theme="borderless"
onClick={() => {
setSideSheet(true);
setRowId(row.id);
}}
>
禁用
</Button>
<Popconfirm
title="是否确定删除?"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
dispatch(equipmentWarehouse.delNvr(row.id)).then(() => {
if (page.current > 0 && limits.current < 2) {
setQuery({ limit: 10, page: page.current - 1 })
} else {
setQuery({ limit: 10, page: page.current })
}
});
}}
>
<Button theme="borderless">删除</Button>
</Popconfirm>
<Button theme="borderless">
复制
</Button>
<Button theme="borderless">
日志
</Button>
</div>
);
},
},
];
//
function attribute (data) {
const arr = localStorage.getItem(PIGEON)
? JSON.parse(localStorage.getItem(PIGEON))
: [];
const column = [
{
title: "推送机制",
dataIndex: "venderId",
key: "PushMechanism",
render: (_, r, index) => {
let manufactorName = data.find((item) => item.id == r.venderId);
return manufactorName ? manufactorName.name : "";
},
},
{
title: "监听设备数量",
dataIndex: "DevicesNum",
key: "DevicesNumber",
render: (_, r, index) => {
return r.name
},
},
{
title: "累计推送次数",
dataIndex: "PushNum",
key: "PushNumber",
render: (_, r, index) => {
return (r.name + '次')
},
},
{
title: "策略类型",
dataIndex: "size",
key: "PolicyType",
render: (_, r, index) => {
let status = r.gbNvr;
return (
<div>
<span
style={{
width: 8,
height: 8,
display: "inline-block",
borderRadius: "50%",
backgroundColor: status ? colorStatus(status.online) : "",
margin: "0 8px 0 0",
}}
/>
{status ? "邮件通知" : equipmentStatus(status.email)}
</div>
);
},
},
];
for (let i = 0; i < arr.length; i++) {
let colum = column.filter((item) => {
return item.key === arr[i];
});
columns.splice(i + 2, 0, colum[0]);
}
setSetupp(columns);
}
//station
// function station (r, name, projects) {
// let data = []
// if (projects == "projects") {
// r.station.map((v) => {
// if (v.structure.projects.length > 0) {
// v.structure.projects.map((item) => data.push(item[name]))
// }
// })
// } else {
// r.station.map((v, index) => data.push(v.structure[name]))
// }
// let dataSet = [...(new Set(data))]
// return dataSet.length > 0 ? <Popover
// key="updateTime"
// position="top"
// content={
// dataSet.length > 1 ? <article style={{ padding: 12 }}>{dataSet.map((v, index) => <div key={index}>{v}</div>)}</article> : ""
// }
// >
// <Tag>{dataSet.length > 1 ? `${dataSet[0]}...` : dataSet.length > 0 ? dataSet[0] : ""}</Tag>
// </Popover> : ""
// }
//
const screen = {
width: 193,
marginRight: 20,
marginBottom: 16,
color: "rgba(0, 0, 0, 0.65)",
};
return (
<>
<div>
<video
id="nvrBanner"
autoPlay
loop
muted
style={{ width: "100%", objectFit: "cover", height: 171 }}
src="/assets/video/nvr_banner.mp4"
type="video/mp4"
/>
<div style={{ position: "absolute", top: 12 }}>
<div
style={{
fontSize: 22,
paddingTop: 15,
marginLeft: 21,
}}
>
信鸽服务
</div>
<div
style={{
fontSize: 14,
paddingTop: 18,
marginLeft: 20,
}}
>
对设备状态变更进行监听通过短信或邮件通知指定人员
</div>
<div
style={{
fontSize: 14,
marginTop: 28,
marginLeft: 21,
width: 89,
height: 32,
lineHeight: "32px",
textAlign: "center",
backgroundColor: "#D9EAFF",
color: "#1859C1",
cursor: "pointer",
}}
>
<PushModal
modalName="add"
/>
{/* <NvrModal
modalName="add"
venderList={venderList}
nvrRef={nvrRef}
close={() => {
const remind = localStorage.getItem(USER);
console.log(remind)
if (!remind) {
setReminder(true)
}
equipmentGetNvr();
}}
/> */}
</div>
</div>
</div>
<div
style={{
width: "100%",
background: "#FFFFFF",
borderRadius: 3,
padding: "8px 20px",
marginTop: 20,
}}
>
<div
style={{
height: 22,
fontSize: 16,
fontFamily: "PingFangSC-Medium, PingFang SC",
fontWeight: "bold",
color: " rgba(0, 0, 0, 0.85)",
lineHeight: "22px",
marginBottom: 16,
}}
>
筛选条件
</div>
<div style={{ display: "flex" }}>
<Form
onSubmit={(values) => console.log(values)}
// onValueChange={values=>console.log(values)}
getFormApi={(formApi) => (api.current = formApi)}
layout="horizontal"
style={{ position: "relative", width: "100%", flex: 1 }}
>
<Form.Input
label="策略名称:"
field="keyword"
maxLength="36"
placeholder="请输入策略名称"
labelPosition="left"
style={screen}
/>
<Form.Select
label="策略类型:"
labelPosition="left"
field="PolicyType"
style={screen}
placeholder="全部"
showClear
>
<Form.Select.Option value="ALL">全部</Form.Select.Option>
<Form.Select.Option value="OFF">短信通知</Form.Select.Option>
<Form.Select.Option value="UNKONW">邮件通知</Form.Select.Option>
</Form.Select>
</Form>
<div
style={{
width: 150,
display: "flex",
justifyContent: "flex-end",
alignItems: "flex-end",
}}
>
<Button
theme="solid"
type="primary"
style={{
width: 65,
height: 30,
borderRadius: 3,
marginBottom: 20,
marginRight: 20,
}}
onClick={() => {
api.current.validate().then((v) => {
setearch(v);
setQuery({ limit: 10, page: 0 })
});
}}
>
搜索
</Button>
<Button
theme="light"
type="primary"
style={{
width: 65,
height: 30,
backGround: "#FFFFFF",
borderRadius: 3,
border: "1px solid #D9D9D9",
marginBottom: 20,
}}
onClick={() => {
api.current.reset();
setearch({});
setQuery({ limit: 10, page: 0 })
}}
>
重置
</Button>
</div>
</div>
</div>
<div style={{ background: "#FFFFFF", marginTop: 5 }}>
<div
style={{
width: "100%",
display: "flex",
justifyContent: "space-between",
padding: "13px 20px",
}}
>
<div
style={{
width: 64,
height: 22,
fontSize: 16,
fontfAmily: "PingFangSC-Medium, PingFang SC",
fontWeight: "bold",
color: "rgba(0, 0, 0, 0.85)",
lineHeight: "22px",
}}
>
策略详情
</div>
<div>
<Button
style={{
width: 32,
height: 32,
background: "#D9D9D9",
borderadius: 3,
marginRight: 20,
}}
type="primary"
key="primary"
onClick={() => {
setSetup(true);
}}
>
<img
src="/assets/images/background/setup.png"
alt="设置"
style={{ width: 18, height: 18 }}
/>
</Button>
</div>
</div>
<Skeleton
loading={loading}
// placeholder={skeletonScreen()}
active={true}
>
<Table
columns={setupp.filter((s) => s)}
dataSource={equipmentWarehouseNvr.data}
bordered={false}
empty="暂无数据"
style={{
padding: "0px 20px",
}}
pagination={false}
/>
</Skeleton>
<div
style={{
display: "flex",
justifyContent: "flex-end",
padding: "20px 20px",
}}
>
<span style={{ lineHeight: "30px" }}>
{equipmentWarehouseNvr.total}条策略
</span>
<Pagination
total={equipmentWarehouseNvr.total}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1
}}
/>
</div>
{setup ? (
<Setup
tableType={PIGEON}
tableList={tableList}
close={() => {
setSetup(false);
attribute(venderList);
}}
/>
) : (
""
)}
{/* {sideSheet ? (
<SideSheets
visible={true}
rowId={rowId}
accessType={accessType}
venderList={venderList}
close={() => {
setSideSheet(false);
}}
/>
) : (
[]
)} */}
{/* <ReminderBox
title="是否继续添加NVR摄像头?"
wait="再等等"
toadd="去添加"
visible={reminder}
USER={USER}
onOk={() => {
history.push({ pathname: '/equipmentWarehouse/camera', query: { addNvr: true, serialNo: nvrRef.current.nvrNumber() } });
localStorage.setItem('vcmp_selected_sider', JSON.stringify("camera"))
setReminder(false)
}}
close={() => {
setReminder(false)
}}
/> */}
</div>
</>
);
};
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth } = state; const { auth, global, members, equipmentWarehouseNvr } = state;
return { return {
user: auth.user, loading: equipmentWarehouseNvr.isRequesting && !equipmentWarehouseNvr.data,
}; user: auth.user,
actions: global.actions,
members: members.data,
equipmentWarehouseNvr: equipmentWarehouseNvr.data || {},
};
} }
export default connect(mapStateToProps)(Carrierpigeon); export default connect(mapStateToProps)(Carrierpigeon);

605
code/VideoAccess-VCMP/web/client/src/sections/offline/containers/statuscode.jsx

@ -1,20 +1,601 @@
import React, { useEffect } from 'react'; import React, { useState, useEffect, useRef } from "react";
import { connect } from 'react-redux'; import { connect } from "react-redux";
import { Coming } from '$components' import moment from "moment";
import '../style.less' import { Button, Form, Table, Pagination, Skeleton, Popconfirm, Popover, Tag, } from "@douyinfe/semi-ui";
import "../style.less";
import {Setup} from "$components";
// import SideSheets from "../components/sideSheet";
// import { skeletonScreen } from "../components/skeletonScreen";
// import { ReminderBox } from "../../../components/index";
export const accessType = [
{ name: "萤石云", key: "yingshi" },
{ name: "NVR", key: "nvr" },
{ name: "IPC", key: "ipc" },
{ name: "级联", key: "cascade" },
];
const Statuscode = (props) => { const Statuscode = (props) => {
const { history, dispatch, actions, user, loading, equipmentWarehouseNvr } = props;
const { equipmentWarehouse } = actions;
const [setup, setSetup] = useState(false);
const [sideSheet, setSideSheet] = useState(false);
const [setupp, setSetupp] = useState([]);
const [venderList, setvenderList] = useState([]); //
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [search, setearch] = useState({}); //
const [rowId, setRowId] = useState(); //id
const [reminder, setReminder] = useState(false); //
const api = useRef();
const searchData = useRef(search)
const limits = useRef(); //
const page = useRef(query.page);
const CODE = "code";
const USER = "user" + props.user.id
const nvrRef = useRef(); //
const tableList = [//
{
title:'状态码信息',
list:[
{ name: "常规解决方案", value: "manufactor" },
{ name: "状态频率", value: "accountNumber" },
]
},
];
useEffect(() => {
dispatch(actions.equipmentWarehouse.getVender()).then((res) => {
setvenderList(res.payload.data);
attribute(res.payload.data);
});
//
localStorage.getItem(CODE) == null
? localStorage.setItem(
CODE,
JSON.stringify(["manufactor", "accountNumber"])
)
: "";
}, []);
return ( useEffect(() => {
<Coming /> equipmentGetNvr();
) }, [query, search]);
}
const equipmentGetNvr = () => {
searchData.current = { ...query, ...search }
dispatch(equipmentWarehouse.getNvr(searchData.current)).then((res) => {
limits.current = res.payload.data.data.length
});
}
function equipmentStatus (data) {
switch (data) {
case "ON":
return "在线"
case "ONLINE":
return "在线"
case "OFF":
return "离线"
default:
return "未知"
}F
}
function colorStatus (data) {
switch (data) {
case "ON":
return "#04B234"
case "ONLINE":
return "#04B234"
case "OFF":
return "rgba(0, 0, 0, 0.45)"
default:
return "#1859C1"
}
}
const columns = [
{
title: "序号",
render: (_, record, index) => {
return index + 1;
},
},
{
title: "设备名称",
dataIndex: "name",
render: (_, r, index) => {
console.log(r);
return r.name
},
},
{
title: "SIP地址",
dataIndex: "owner",
render: (_, r, index) => {
return r?.gbNvr?.sipip
},
},
{
title: "操作",
width: "20%",
dataIndex: "",
render: (_, row) => {
return (
<div style={{ display: "flex" }}>
<Button theme="borderless">
启用
</Button>
<Button
theme="borderless"
onClick={() => {
setSideSheet(true);
setRowId(row.id);
}}
>
释义
</Button>
<Popconfirm
title="删除NVR会删除端口下的所有摄像头,是否确定删除?"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
dispatch(equipmentWarehouse.delNvr(row.id)).then(() => {
if (page.current > 0 && limits.current < 2) {
setQuery({ limit: 10, page: page.current - 1 })
} else {
setQuery({ limit: 10, page: page.current })
}
});
}}
>
<Button theme="borderless">方案</Button>
</Popconfirm>
</div>
);
},
},
];
//
function attribute (data) {
const arr = localStorage.getItem(CODE)
? JSON.parse(localStorage.getItem(CODE))
: [];
const column = [
{
title: "设备厂家",
dataIndex: "venderId",
key: "manufactor",
render: (_, r, index) => {
let manufactorName = data.find((item) => item.id == r.venderId);
return manufactorName ? manufactorName.name : "";
},
},
{
title: "添加账号",
dataIndex: "createUserId",
key: "accountNumber",
render: (_, r, index) => {
return r?.createUser?.name
},
},
{
title: "通道数",
dataIndex: "channelCount",
key: "passageway",
},
{
title: "端口",
dataIndex: "port",
key: "port",
},
{
title: "设备状态",
dataIndex: "size",
key: "state",
render: (_, r, index) => {
let status = r.gbNvr;
return (
<div>
<span
style={{
width: 8,
height: 8,
display: "inline-block",
borderRadius: "50%",
backgroundColor: status ? colorStatus(status.online) : "",
margin: "0 8px 0 0",
}}
/>
{status ? equipmentStatus(status.online) : ""}
</div>
);
},
},
{
title: "创建时间",
dataIndex: "createTime",
key: "time",
render: (_, r, index) => {
return moment(r.createTime).format("YYYY-MM-DD HH:MM:SS");
},
},
{
title: "项目名称",
dataIndex: "",
key: "name",
render: (_, r, index) => {
return r.station.length == 0
? ""
: station(r, "name", "projects")
},
},
{
title: "pcode",
dataIndex: "",
key: "pcode",
render: (_, r, index) => {
return r.station.length == 0
? ""
: station(r, "url", "projects")
},
},
{
title: "结构物",
dataIndex: "",
key: "structure",
render: (_, r, index) => {
return r.station.length == 0
? ""
: station(r, "name")
},
},
];
for (let i = 0; i < arr.length; i++) {
let colum = column.filter((item) => {
return item.key === arr[i];
});
columns.splice(i + 2, 0, colum[0]);
}
setSetupp(columns);
}
//station
function station (r, name, projects) {
let data = []
if (projects == "projects") {
r.station.map((v) => {
if (v.structure.projects.length > 0) {
v.structure.projects.map((item) => data.push(item[name]))
}
})
} else {
r.station.map((v, index) => data.push(v.structure[name]))
}
let dataSet = [...(new Set(data))]
return dataSet.length > 0 ? <Popover
key="updateTime"
position="top"
content={
dataSet.length > 1 ? <article style={{ padding: 12 }}>{dataSet.map((v, index) => <div key={index}>{v}</div>)}</article> : ""
}
>
<Tag>{dataSet.length > 1 ? `${dataSet[0]}...` : dataSet.length > 0 ? dataSet[0] : ""}</Tag>
</Popover> : ""
}
//
const screen = {
width: 193,
marginRight: 20,
marginBottom: 16,
color: "rgba(0, 0, 0, 0.65)",
};
return (
<>
<div>
<video
id="nvrBanner"
autoPlay
loop
muted
style={{ width: "100%", objectFit: "cover", height: 171 }}
src="/assets/video/nvr_banner.mp4"
type="video/mp4"
/>
<div style={{ position: "absolute", top: 12 }}>
<div
style={{
fontSize: 22,
paddingTop: 15,
marginLeft: 21,
}}
>
状态码管理
</div>
<div
style={{
fontSize: 14,
paddingTop: 18,
marginLeft: 20,
}}
>
系统支持状态码显示内容的释义修改当设备异常时会为您显示自定义释义内容
</div>
</div>
</div>
<div
style={{
width: "100%",
background: "#FFFFFF",
borderRadius: 3,
padding: "8px 20px",
marginTop: 20,
}}
>
<div
style={{
height: 22,
fontSize: 16,
fontFamily: "PingFangSC-Medium, PingFang SC",
fontWeight: "bold",
color: " rgba(0, 0, 0, 0.85)",
lineHeight: "22px",
marginBottom: 16,
}}
>
筛选条件
</div>
<div style={{ display: "flex" }}>
<Form
onSubmit={(values) => console.log(values)}
// onValueChange={values=>console.log(values)}
getFormApi={(formApi) => (api.current = formApi)}
layout="horizontal"
style={{ position: "relative", width: "100%", flex: 1 }}
>
<Form.Input
label="释义搜索: "
field="keyword"
maxLength="36"
placeholder="请输入错误描述、释义或自定义释义"
labelPosition="left"
style={screen}
/>
<Form.Select
label="启用状态:"
labelPosition="left"
style={screen}
field="venderId"
placeholder="全部"
showClear
>
<Form.Select.Option value="ALL">全部</Form.Select.Option>
<Form.Select.Option value="OFF">启用</Form.Select.Option>
<Form.Select.Option value="UNKONW">禁用</Form.Select.Option>
</Form.Select>
<Form.Select
label="状态查询:"
labelPosition="left"
field="state"
style={screen}
placeholder="全部"
showClear
>
<Form.Select.Option value="ALL">全部</Form.Select.Option>
<Form.Select.Option value="OFF">已设置</Form.Select.Option>
<Form.Select.Option value="UNKONW">未设置</Form.Select.Option>
</Form.Select>
</Form>
<div
style={{
width: 150,
display: "flex",
justifyContent: "flex-end",
alignItems: "flex-end",
}}
>
<Button
theme="solid"
type="primary"
style={{
width: 65,
height: 30,
borderRadius: 3,
marginBottom: 20,
marginRight: 20,
}}
onClick={() => {
api.current.validate().then((v) => {
setearch(v);
setQuery({ limit: 10, page: 0 })
});
}}
>
搜素
</Button>
<Button
theme="light"
type="primary"
style={{
width: 65,
height: 30,
backGround: "#FFFFFF",
borderRadius: 3,
border: "1px solid #D9D9D9",
marginBottom: 20,
}}
onClick={() => {
api.current.reset();
setearch({});
setQuery({ limit: 10, page: 0 })
}}
>
重置
</Button>
</div>
</div>
</div>
<div style={{ background: "#FFFFFF", marginTop: 5 }}>
<div
style={{
width: "100%",
display: "flex",
justifyContent: "space-between",
padding: "13px 20px",
}}
>
<div
style={{
width: 84,
height: 22,
fontSize: 16,
fontfAmily: "PingFangSC-Medium, PingFang SC",
fontWeight: "bold",
color: "rgba(0, 0, 0, 0.85)",
lineHeight: "22px",
}}
>
状态码详情
</div>
<div>
<Button
style={{
width: 32,
height: 32,
background: "#D9D9D9",
borderadius: 3,
marginRight: 20,
}}
type="primary"
key="primary"
onClick={() => {
setSetup(true);
}}
>
<img
src="/assets/images/background/setup.png"
alt="设置"
style={{ width: 18, height: 18 }}
/>
</Button>
<Button
theme="solid"
type="primary"
style={{
width: 65,
height: 32,
borderRadius: 3,
}}
onClick={() => {
// api.current.validate().then((v) => {
// setearch(v);
// setQuery({ limit: 10, page: 0 })
// });
}}
>
批量设置
</Button>
</div>
</div>
<Skeleton
loading={loading}
// placeholder={skeletonScreen()}
active={true}
>
<Table
columns={setupp.filter((s) => s)}
dataSource={equipmentWarehouseNvr.data}
bordered={false}
empty="暂无数据"
style={{
padding: "0px 20px",
}}
pagination={false}
/>
</Skeleton>
<div
style={{
display: "flex",
justifyContent: "flex-end",
padding: "20px 20px",
}}
>
<span style={{ lineHeight: "30px" }}>
{equipmentWarehouseNvr.total}个设备
</span>
<Pagination
total={equipmentWarehouseNvr.total}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1
}}
/>
</div>
{setup ? (
<Setup
tableType={CODE}
tableList={tableList}
close={() => {
setSetup(false);
attribute(venderList);
}}
/>
) : (
""
)}
{/* {sideSheet ? (
<SideSheets
visible={true}
rowId={rowId}
accessType={accessType}
venderList={venderList}
close={() => {
setSideSheet(false);
}}
/>
) : (
[]
)} */}
{/* <ReminderBox
title="是否继续添加NVR摄像头?"
wait="再等等"
toadd="去添加"
visible={reminder}
USER={USER}
onOk={() => {
history.push({ pathname: '/equipmentWarehouse/camera', query: { addNvr: true, serialNo: nvrRef.current.nvrNumber() } });
localStorage.setItem('vcmp_selected_sider', JSON.stringify("camera"))
setReminder(false)
}}
close={() => {
setReminder(false)
}}
/> */}
</div>
</>
);
};
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth } = state; const { auth, global, members, equipmentWarehouseNvr } = state;
return { return {
user: auth.user, loading: equipmentWarehouseNvr.isRequesting && !equipmentWarehouseNvr.data,
}; user: auth.user,
actions: global.actions,
members: members.data,
equipmentWarehouseNvr: equipmentWarehouseNvr.data || {},
};
} }
export default connect(mapStateToProps)(Statuscode); export default connect(mapStateToProps)(Statuscode);

Loading…
Cancel
Save