Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wisdom-components
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
wisdom-components
Commits
a0b118cc
Commit
a0b118cc
authored
Jan 03, 2024
by
李纪文
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 增加vms视频回放
parent
d84fc0f8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
463 additions
and
1 deletion
+463
-1
VmsVideo.md
packages/base-components/VmsVideo/src/VmsVideo.md
+6
-0
index.js
packages/base-components/VmsVideo/src/apis/index.js
+25
-0
dmeo2.tsx
packages/base-components/VmsVideo/src/demos/dmeo2.tsx
+135
-0
index.jsx
packages/base-components/VmsVideo/src/index.jsx
+1
-1
get-size.js
...e-components/VmsVideo/src/recVideo/TimeSlider/get-size.js
+33
-0
index.js
...base-components/VmsVideo/src/recVideo/TimeSlider/index.js
+0
-0
responsiveCanvas.js
...ents/VmsVideo/src/recVideo/TimeSlider/responsiveCanvas.js
+69
-0
index.js
packages/base-components/VmsVideo/src/recVideo/index.js
+156
-0
index.less
packages/base-components/VmsVideo/src/recVideo/index.less
+38
-0
No files found.
packages/base-components/VmsVideo/src/VmsVideo.md
View file @
a0b118cc
...
...
@@ -15,8 +15,14 @@ group:
**需安装的依赖项: ezuikit-js axios (1.npm i ezuikit-js 2.npm i axios)**
### 视频
<code
src=
"./demos/dmeo1.tsx"
>
### 视频回放
<code
src=
"./demos/dmeo2.tsx"
>
## 参数说明
| JessibucaObj 常用参数(对萤石 EZOPEN 协议不生效) | 说明 | 类型 | 默认值 |
...
...
packages/base-components/VmsVideo/src/apis/index.js
0 → 100644
View file @
a0b118cc
import
{
request
}
from
'@wisdom-utils/utils'
;
const
REQUEST_METHOD_GET
=
'get'
;
const
REQUEST_METHOD_POST
=
'post'
;
// eslint-disable-next-line no-undef
const
baseURI
=
typeof
DUMI_TYPE
!==
'undefined'
&&
DUMI_TYPE
===
'dumi'
?
'/api'
:
''
;
const
CommonPath
=
window
?.
globalConfig
?.
hasGateWay
?
'/PandaCore/GateWay'
:
''
;
// 录像回放
export
function
videoPlayback
(
params
)
{
return
request
({
url
:
`
${
baseURI
}${
CommonPath
}
/pandavms/camera/playback`
,
method
:
REQUEST_METHOD_GET
,
params
,
});
}
// 根据时间轴时间选定 查看历史视频
export
function
newPlayback
(
params
)
{
return
request
({
url
:
`
${
baseURI
}${
CommonPath
}
/pandavms/camera/newpalyback`
,
method
:
REQUEST_METHOD_GET
,
params
,
});
}
packages/base-components/VmsVideo/src/demos/dmeo2.tsx
0 → 100644
View file @
a0b118cc
import
React
,
{
useRef
,
useEffect
,
useState
}
from
'react'
;
import
Video
from
'../recVideo'
;
const
Demo2
=
(
props
)
=>
{
const
jessibuca
=
useRef
(
null
);
let
JessibucaObj
=
{
operateBtns
:
{
// fullscreen: false,
screenshot
:
false
,
},
loadingText
:
'演示视频加载中'
,
decoder
:
'/JessibucaVideo/decoder.js'
,
};
// 若是在子应用中,则需加上子应用名称,且兼容基座
// 如下:
// let _url = '/civ_energy/JessibucaVideo/decoder.js'
// let JessibucaObj = {
// decoder: window.__POWERED_BY_QIANKUN__ ? '/civbase' + _url : _url
// }
// let VideoInfo = {
// key: '123638446', //'1CEB209F-8BC7-44B5-9F6B-3D8FCB855E76',
// dataRate: `/2`,
// fullUrl: 'ws://172.16.19.19:8080/jessica/1CEB209F-8BC7-44B5-9F6B-3D8FCB855E76',
// useFullUrl: true,
// cameraName: `摄像头s8`,
// appKey: '6c44c8e92d1c4d75a9818756025df550',
// appSecret: '78b7dc88f9f4bf19c2b1aabfdd995244',
// protocol: '萤石EZOPEN',
//};
let
VideoParam
=
{
id
:
'9745259F-76B5-4ECB-BDD7-8B1B2C5C84CD'
,
name
:
'3L00AE9PAJ00034'
,
protocol
:
'乐橙云HTTP-FLV'
,
username
:
'lc0f4b952c86c34c4b'
,
password
:
'dfdcae9267bf4964ae09998e16f016'
,
pandavmsHost
:
'ws://192.168.12.154:8080/'
,
address
:
'3L00AE9PAJ00034'
,
};
VideoParam
=
{
channel
:
'2'
,
// dataRate: 'Sub', // Main 主码流 Sub 子码流
name
:
'RTSP银河湾五期_通道_2'
,
id
:
'46D6E990-8049-4A61-B592-8503BDFAA07A'
,
username
:
'admin'
,
password
:
'zls_1234@abcd'
,
address
:
'172.16.19.2'
,
protocol
:
'RTSP'
,
pandavmsHost
:
'ws://192.168.8.30:7000/'
,
// pandavms后端主机地址 eg: ws://172.16.19.19:8080/
hoursRuler
:
48
,
beginTime
:
'2024-01-01 00:00:00'
,
// 回放开始时间
endTime
:
'2024-01-02 23:59:59'
,
// 回放结束时间
};
const
[
VideoInfo
,
setVideoInfo
]
=
useState
(
VideoParam
);
useEffect
(()
=>
{
// 事件 ,返回视频信息
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
on
(
'videoInfo'
,
function
(
data
)
{
console
.
log
(
'width:'
,
data
.
width
,
'height:'
,
data
.
width
);
});
// 事件 ,播放视频之后的回调
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
on
(
'play'
,
function
(
data
)
{
console
.
log
(
'play:'
,
jessibuca
);
});
// 事件 ,暂停视频之后的回调
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
on
(
'pause'
,
function
(
data
)
{
console
.
log
(
'pause:'
,
data
);
});
// ******
// 其他事件需查看在线文档
// ******
return
()
=>
{
console
.
log
(
'销毁。。。。。。。。。。。。。。。。。。。。。。。。。'
);
stopVideo
();
};
},
[]);
const
stopVideo
=
()
=>
{
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
pause
&&
jessibuca
.
current
.
pause
();
};
const
startVideo
=
()
=>
{
if
(
jessibuca
&&
jessibuca
.
current
)
{
jessibuca
.
current
.
play
();
// console.log(jessibuca.current.isPlaying());
}
};
const
testVideo
=
()
=>
{
// console.log(jessibuca.current.isPlaying());
setVideoInfo
({
channel
:
'2'
,
// dataRate: 'Sub', // Main 主码流 Sub 子码流
name
:
'RTSP银河湾五期_通道_2'
,
id
:
'46D6E990-8049-4A61-B592-8503BDFAA07A'
,
username
:
'admin'
,
password
:
'zls_1234@abcd'
,
address
:
'172.16.19.2'
,
protocol
:
'RTSP'
,
pandavmsHost
:
'ws://192.168.8.30:7000/'
,
// pandavms后端主机地址 eg: ws://172.16.19.19:8080/
hoursRuler
:
24
,
beginTime
:
'2024-01-01 00:00:00'
,
endTime
:
'2024-01-01 23:59:59'
,
});
};
const
destroyVideo
=
()
=>
{
if
(
VideoParam
.
protocol
!=
'萤石EZOPEN'
)
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
destroy
();
};
return
(
<
div
>
<
button
onClick=
{
stopVideo
}
>
暂停
</
button
>
<
button
onClick=
{
startVideo
}
>
开始
</
button
>
<
button
onClick=
{
testVideo
}
>
测试
</
button
>
<
button
onClick=
{
destroyVideo
}
>
销毁
</
button
>
<
div
style=
{
{
height
:
'700px'
}
}
>
<
Video
{
...
{
JessibucaObj
:
JessibucaObj
,
VideoInfo
:
VideoInfo
}}
ref=
{
jessibuca
}
/>
</
div
>
</
div
>
);
};
export
default
Demo2
;
packages/base-components/VmsVideo/src/index.jsx
View file @
a0b118cc
...
...
@@ -7,7 +7,7 @@
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// eslint-disable-next-line no-unused-vars
import
EZUIKit
,
{
log
}
from
'
./ezuikit-js/ezuikit
'
;
import
EZUIKit
,
{
log
}
from
'
ezuikit-js
'
;
import
axios
from
'axios'
;
import
React
,
{
...
...
packages/base-components/VmsVideo/src/recVideo/TimeSlider/get-size.js
0 → 100644
View file @
a0b118cc
const
parseNumber
=
(
prop
)
=>
parseFloat
(
prop
)
||
0
;
const
getSize
=
(
el
)
=>
{
if
(
el
===
window
||
el
===
document
.
body
)
{
return
[
window
.
innerWidth
,
window
.
innerHeight
];
}
let
temporary
=
false
;
if
(
!
el
.
parentNode
&&
document
.
body
)
{
temporary
=
true
;
document
.
body
.
appendChild
(
el
);
}
const
rect
=
el
.
getBoundingClientRect
();
const
styles
=
getComputedStyle
(
el
);
const
height
=
(
rect
.
height
|
0
)
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-top'
))
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-bottom'
));
const
width
=
(
rect
.
width
|
0
)
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-left'
))
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-right'
));
if
(
temporary
&&
document
.
body
)
{
document
.
body
.
removeChild
(
el
);
}
return
[
width
,
height
];
};
export
default
getSize
;
packages/base-components/VmsVideo/src/recVideo/TimeSlider/index.js
0 → 100644
View file @
a0b118cc
This diff is collapsed.
Click to expand it.
packages/base-components/VmsVideo/src/recVideo/TimeSlider/responsiveCanvas.js
0 → 100644
View file @
a0b118cc
import
React
,
{
Component
}
from
'react'
;
import
getSize
from
'./get-size'
;
export
default
class
RvResponsiveCanvas
extends
Component
{
static
defaultProps
=
{
scale
:
typeof
window
!==
'undefined'
?
window
.
devicePixelRatio
:
1
,
};
state
=
{
width
:
0
,
height
:
0
,
};
$canvas
;
componentDidMount
()
{
window
.
addEventListener
(
'resize'
,
this
.
handleResize
,
false
);
this
.
setSize
();
}
componentWillUnmount
()
{
window
.
removeEventListener
(
'resize'
,
this
.
handleResize
,
false
);
}
handleResize
=
()
=>
{
this
.
setSize
();
this
.
props
.
onResize
(
this
.
state
.
width
,
this
.
state
.
height
);
};
setSize
=
()
=>
{
const
parent
=
this
.
$canvas
.
parentElement
;
if
(
!
parent
)
{
return
;
}
const
[
width
,
height
]
=
getSize
(
parent
);
this
.
setState
({
width
,
height
});
};
setRef
=
(
el
)
=>
{
if
(
!
el
)
{
return
;
}
const
{
canvasRef
}
=
this
.
props
;
this
.
$canvas
=
el
;
if
(
typeof
canvasRef
===
'function'
)
{
canvasRef
(
el
);
}
};
render
()
{
const
{
scale
,
onResize
,
canvasRef
,
style
,
...
props
}
=
this
.
props
;
const
{
width
,
height
}
=
this
.
state
;
return
(
<
canvas
{...
props
}
ref
=
{
this
.
setRef
}
width
=
{
width
*
scale
}
height
=
{
height
*
scale
}
style
=
{{
...
style
,
width
,
height
,
minWidth
:
'952px'
}}
/
>
);
}
}
packages/base-components/VmsVideo/src/recVideo/index.js
0 → 100644
View file @
a0b118cc
import
{
Button
,
message
,
Modal
}
from
'antd'
;
import
{
useEffect
,
useState
,
useContext
,
useRef
,
useImperativeHandle
}
from
'react'
;
import
TestVideo
from
'../index'
;
import
classNames
from
'classnames'
;
import
{
DatePicker
,
TimePicker
,
Calendar
,
theme
,
ConfigProvider
}
from
'antd'
;
import
Empty
from
'@wisdom-components/empty'
;
import
{
videoPlayback
,
newPlayback
}
from
'../apis'
;
import
'./index.less'
;
import
moment
from
'moment'
;
import
TimeSlider
from
'./TimeSlider'
;
const
RecVideo
=
(
props
,
ref
)
=>
{
const
{
getPrefixCls
}
=
useContext
(
ConfigProvider
.
ConfigContext
);
const
prefixCls
=
getPrefixCls
(
'rec-video-view'
);
const
{
VideoInfo
,
JessibucaObj
}
=
props
;
const
jessibuca
=
useRef
(
null
);
const
[
hoursRuler
,
setHoursRuler
]
=
useState
(
VideoInfo
.
hoursRuler
||
24
);
const
[
showId
,
setShowId
]
=
useState
(
null
);
//视频ID
const
[
peridos
,
setPeridos
]
=
useState
([]);
//可播放视频时间段
const
[
playTimestamp
,
setPlayTimestamp
]
=
useState
(
null
);
//当前正在播放时间段
const
[
minTimestamp
,
setMinTimestamp
]
=
useState
(
null
);
//时间轴最小时间
const
[
maxTimestamp
,
setMaxTimestamp
]
=
useState
(
null
);
//时间轴最大时间
useEffect
(()
=>
{
changeReplayCfg
();
},
[
props
.
VideoInfo
]);
useImperativeHandle
(
ref
,
()
=>
{
// changeVal 就是暴露给父组件的方法, newVal是父组件传递的参数
return
jessibuca
.
current
;
// _video&& _video.current&&_video.current.jessibuca
});
useEffect
(()
=>
{
const
{
endTime
=
moment
().
format
(
'YYYY-MM-DD 23:59:59'
)
}
=
VideoInfo
;
const
edTimes
=
moment
(
endTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
if
(
playTimestamp
)
{
let
momentObj
=
moment
(
playTimestamp
);
let
formattedTime
=
momentObj
.
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
edDates
=
moment
(
edTimes
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
params
=
{
id
:
VideoInfo
.
id
,
startTime
:
formattedTime
,
endTime
:
edDates
,
'site-code'
:
window
?.
globalConfig
?.
userInfo
?.
LocalSite
||
''
,
};
rePaly
(
params
);
}
},
[
playTimestamp
]);
const
changeReplayCfg
=
()
=>
{
const
{
beginTime
=
moment
().
format
(
'YYYY-MM-DD 00:00:00'
),
endTime
=
moment
().
format
(
'YYYY-MM-DD 23:59:59'
),
}
=
VideoInfo
;
const
hoursPerRuler
=
calculateHours
(
beginTime
,
endTime
)
||
24
;
const
stTimes
=
moment
(
beginTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
edTimes
=
moment
(
endTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
param
=
{
id
:
VideoInfo
.
id
,
startTime
:
stTimes
,
endTime
:
edTimes
,
'site-code'
:
window
?.
globalConfig
?.
userInfo
?.
LocalSite
||
''
,
};
setHoursRuler
(
hoursPerRuler
);
setMinTimestamp
(
moment
(
stTimes
).
valueOf
());
setMaxTimestamp
(
moment
(
edTimes
).
valueOf
());
getVideoPlBack
(
param
);
};
const
getVideoPlBack
=
(
param
)
=>
{
videoPlayback
(
param
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
setPeridos
(
res
.
data
.
peridos
.
map
((
times
,
i
)
=>
{
let
beginTime
=
moment
(
times
.
StartTime
.
replaceAll
(
'T'
,
' '
).
replaceAll
(
'Z'
,
' '
));
let
endTime
=
moment
(
times
.
EndTime
.
replaceAll
(
'T'
,
' '
).
replaceAll
(
'Z'
,
' '
));
return
{
...
times
,
idx
:
i
,
beginTime
:
beginTime
.
valueOf
(),
endTime
:
endTime
.
valueOf
(),
style
:
{
background
:
'#637DEC'
},
};
}),
);
setShowId
(
res
.
data
.
url
);
}
else
{
message
.
warn
(
res
.
msg
);
setShowId
(
null
);
}
});
};
const
rePaly
=
(
params
)
=>
{
newPlayback
(
params
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
setShowId
(
res
.
data
);
}
else
{
message
.
warn
(
res
.
msg
);
}
});
};
const
calculateHours
=
(
time1
,
time2
)
=>
{
const
date1
=
new
Date
(
time1
);
const
date2
=
new
Date
(
time2
);
const
diff
=
Math
.
abs
(
date1
.
getTime
()
-
date2
.
getTime
());
return
Math
.
ceil
(
diff
/
(
1000
*
60
*
60
));
};
return
(
<
div
className
=
{
classNames
(
prefixCls
)}
>
{
showId
?
(
<>
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-video`
)}
>
{
showId
&&
(
<
TestVideo
VideoInfo
=
{{
...
VideoInfo
,
id
:
showId
}}
JessibucaObj
=
{{
...
JessibucaObj
}}
key
=
{
showId
}
ref
=
{
jessibuca
}
/
>
)}
<
/div
>
{
/* 时间轴 */
}
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-time`
)}
>
{
peridos
.
length
?
(
<
TimeSlider
minTimestamp
=
{
minTimestamp
}
key
=
{
JSON
.
stringify
(
peridos
)
+
(
hoursRuler
||
24
)}
maxTimestamp
=
{
maxTimestamp
}
hoursPerRuler
=
{
hoursRuler
||
24
}
playTimestamp
=
{
playTimestamp
?
playTimestamp
:
peridos
[
0
].
beginTime
}
playTimestampChange
=
{(
time
,
recordInfo
,
playOffset
)
=>
{
if
(
recordInfo
&&
playOffset
)
{
setPlayTimestamp
(
time
);
}
else
{
message
.
warn
(
'当前时间节点没有视频可以播放哦!'
);
}
}}
timecell
=
{
peridos
}
/
>
)
:
null
}
<
/div
>
<
/
>
)
:
(
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-empty`
)}
>
<
Empty
theme
=
{
'dark'
}
description
=
{
''
}
/
>
<
/div
>
)}
<
/div
>
);
};
export
default
React
.
forwardRef
(
RecVideo
);
packages/base-components/VmsVideo/src/recVideo/index.less
0 → 100644
View file @
a0b118cc
@root-entry-name: 'default';
@import '~antd/es/style/themes/index.less';
@rec-video-view-prefix-cls: ~'@{ant-prefix}-rec-video-view';
.@{rec-video-view-prefix-cls} {
display: flex;
align-items: center;
flex-direction: column;
height: 100%;
width: 100%;
&-video {
flex: 1;
width: 100%;
}
&-time {
flex: none;
width: 100%;
}
&-empty {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
:global {
.timeslider-canvas-wrap-his {
height: 72px;
width: 100%;
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment