Browse Source

添加级联摄像头

release_0.0.2
wenlele 2 years ago
parent
commit
4b87887396
  1. 3
      code/VideoAccess-VCMP/api/.vscode/launch.json
  2. 42
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js
  3. 4
      code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js
  4. 2
      code/VideoAccess-VCMP/api/app/lib/index.js
  5. 3
      code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js
  6. 22
      code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js
  7. 8
      code/VideoAccess-VCMP/api/app/lib/service/redis.js
  8. 14
      code/VideoAccess-VCMP/api/config.js
  9. 1
      code/VideoAccess-VCMP/api/package.json
  10. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-control-select.png
  11. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-control-unselect.png
  12. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-fullScreen-select.png
  13. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-fullScreen-unselect.png
  14. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-histroy-select.png
  15. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-histroy-unselect.png
  16. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-talk-select.png
  17. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-talk-unselect.png
  18. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/videoPlayBg.png
  19. 1
      code/VideoAccess-VCMP/web/client/assets/js/jessibuca/decoder.js
  20. BIN
      code/VideoAccess-VCMP/web/client/assets/js/jessibuca/decoder.wasm
  21. 1
      code/VideoAccess-VCMP/web/client/assets/js/jessibuca/jessibuca.js
  22. BIN
      code/VideoAccess-VCMP/web/client/assets/video/cross_loading.mp4
  23. BIN
      code/VideoAccess-VCMP/web/client/assets/video/login_bg.mp4
  24. 1
      code/VideoAccess-VCMP/web/client/index.ejs
  25. 1
      code/VideoAccess-VCMP/web/client/index.html
  26. 4
      code/VideoAccess-VCMP/web/client/src/components/index.js
  27. 48
      code/VideoAccess-VCMP/web/client/src/components/textScroll.jsx
  28. 19
      code/VideoAccess-VCMP/web/client/src/components/textScroll.less
  29. 143
      code/VideoAccess-VCMP/web/client/src/components/videoPlay.jsx
  30. 0
      code/VideoAccess-VCMP/web/client/src/components/videoPlay.less
  31. 32
      code/VideoAccess-VCMP/web/client/src/components/videoPlayModal.jsx
  32. 5
      code/VideoAccess-VCMP/web/client/src/components/videoPlayModal.less
  33. 11
      code/VideoAccess-VCMP/web/client/src/layout/containers/layout/index.jsx
  34. 5
      code/VideoAccess-VCMP/web/client/src/layout/index.jsx
  35. 18
      code/VideoAccess-VCMP/web/client/src/sections/auth/containers/login.jsx
  36. 2
      code/VideoAccess-VCMP/web/package.json

3
code/VideoAccess-VCMP/api/.vscode/launch.json

@ -22,7 +22,8 @@
"--iotAuthApi http://127.0.0.1:4200",
"--iotVideoServerUrl http://221.230.55.27:8081",
"--godUrl https://restapi.amap.com/v3",
"--godKey 21c2d970e1646bb9a795900dd00093ce"
"--godKey 21c2d970e1646bb9a795900dd00093ce",
"--mqttVideoServer mqtt://127.0.0.1"
]
},
{

42
code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js

@ -96,6 +96,7 @@ async function createYingshi (ctx) {
async function getNvrSteam (ctx) {
let errMsg = '获取 NVR 视频流失败'
try {
const { models } = ctx.fs.dc
const { streamId } = ctx.query
const { utils: { getGbCameraLevel3ByStreamId } } = ctx.app.fs
@ -109,8 +110,24 @@ async function getNvrSteam (ctx) {
throw errMsg
}
const addedRes = await models.Camera.findAll({
attributes: ['id', 'name', 'serialNo'],
where: {
nvrId: nvrRes.id
}
})
const cameraRes = await getGbCameraLevel3ByStreamId({ streamId })
for (let c of cameraRes) {
let preAdd = addedRes.find(ad => ad.dataValues.serialNo == c.streamid)
if (preAdd) {
c.dataValues.camera = preAdd.dataValues
} else {
c.dataValues.camera = null
}
}
ctx.status = 200;
ctx.body = cameraRes
} catch (error) {
@ -198,6 +215,7 @@ async function createNvrCamera (ctx) {
name: c.name,
sip: corCamera.sipip,
cloudControl: c.cloudControl,
nvrId: nvrRes.id,
createTime: moment().format(),
createUserId: userId,
forbidden: false,
@ -216,6 +234,9 @@ async function createNvrCamera (ctx) {
if (updateData.length) {
for (let u of updateData) {
await models.Camera.update(u, {
where: {
id: u.id
},
transaction
})
}
@ -324,6 +345,26 @@ async function createIpcCamera (ctx) {
}
}
async function getCascadeSipList (ctx) {
try {
const { models } = ctx.fs.dc
const sipListRes = await models.GbCamera.findAll({
attributes: ['id', 'streamid'],
where: {
level: 0,
ipctype: '级联',
}
})
ctx.status = 200;
ctx.body = sipListRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function verifyCascadeCamera (ctx) {
let errMsg = '校验级联摄像头信息失败'
try {
@ -401,6 +442,7 @@ module.exports = {
createNvrCamera,
verifyIpcCamera,
createIpcCamera,
getCascadeSipList,
verifyCascadeCamera,
createCascadeCamera,
};

4
code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js

@ -16,7 +16,7 @@ async function edit (ctx, next) {
where: {
streamid: serialNo,
level: 0,
ipctype: 'nvr'
// ipctype: 'nvr'
}
})
@ -77,7 +77,7 @@ async function verify (ctx, next) {
where: {
streamid: serialNo,
level: 0,
ipctype: 'nvr'
// ipctype: 'nvr'
}
})

2
code/VideoAccess-VCMP/api/app/lib/index.js

@ -4,6 +4,7 @@ const utils = require('./utils')
const routes = require('./routes');
const redisConnect = require('./service/redis')
const socketConect = require('./service/socket')
const mqttVideoServer = require('./service/mqttVideoServer')
const paasRequest = require('./service/paasRequest');
const authenticator = require('./middlewares/authenticator');
// const apiLog = require('./middlewares/api-log');
@ -19,6 +20,7 @@ module.exports.entry = function (app, router, opts) {
// 顺序固定 ↓
redisConnect(app, opts)
socketConect(app, opts)
mqttVideoServer(app, opts)
// 实例其他平台请求方法
paasRequest(app, opts)

3
code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js

@ -27,6 +27,9 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['POST/camera/create/ipc'] = { content: '创建IPC摄像头', visible: false };
router.post('/camera/create/ipc', cameraCreate.createIpcCamera);
app.fs.api.logAttr['GET/camera/sip_list/cascade'] = { content: '获取级联摄像头sip列表', visible: false };
router.get('/camera/sip_list/cascade', cameraCreate.getCascadeSipList);
app.fs.api.logAttr['POST/camera/verify/cascade'] = { content: '验证级联摄像头信息', visible: false };
router.post('/camera/verify/cascade', cameraCreate.verifyCascadeCamera);

22
code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js

@ -0,0 +1,22 @@
'use strict';
const mqtt = require('mqtt');
module.exports = async function factory (app, opts) {
// const client = mqtt.connect(opts.mqtt.mqttVideoServer);
// client.on('connect', function () {
// console.info(`mqtt connect success ${opts.mqtt.mqttVideoServer}`);
// })
// client.on('error', function (e) {
// console.error(`mqtt connect failed ${opts.mqtt.mqttVideoServer}`);
// app.fs.logger.error('info', '[FS-AUTH-MQTT]', `mqtt connect failed ${opts.mqtt.mqttVideoServer}`);
// })
// client.subscribe('test', { qos: 2 });//订阅主题为test的消息
// client.on('message', function (top, message) {
// console.log(message.toString());
// });
// app.mqttVideoServer = client
}

8
code/VideoAccess-VCMP/api/app/lib/service/redis.js

@ -6,13 +6,13 @@ module.exports = async function factory (app, opts) {
let client = new redis(opts.redis.port, opts.redis.host);
client.on("error", function (err) {
app.fs.logger.error('info', '[FS-AUTH-REDIS]', 'redis connect error.');
console.error("Error :", err);
process.exit(-1);
app.fs.logger.error('info', '[FS-AUTH-REDIS]', `redis connect error. ${opts.redis.host + ':' + opts.redis.port}` );
// console.error("Error :", err);
// process.exit(-1);
});
client.on('connect', function () {
console.log(`redis connect success ${opts.redis.host + ':' + opts.redis.port}`);
console.info(`redis connect success ${opts.redis.host + ':' + opts.redis.port}`);
})
// 自定义方法

14
code/VideoAccess-VCMP/api/config.js

@ -19,6 +19,7 @@ args.option('iotAuthApi', 'IOT 鉴权 api');
args.option('iotVideoServerUrl', '视频后端服务地址');
args.option('godUrl', '高德地图API请求地址');
args.option('godKey', '高德地图API key');
args.option('mqttVideoServer', '视频后台 mqtt 服务 URL');
const flags = args.parse(process.argv);
@ -29,6 +30,8 @@ const IOTA_REDIS_SERVER_HOST = process.env.IOTA_REDIS_SERVER_HOST || flags.redis
const IOTA_REDIS_SERVER_PORT = process.env.IOTA_REDIS_SERVER_PORT || flags.redisPort || "6379";//redis 端口
const IOTA_REDIS_SERVER_PWD = process.env.IOTA_REDIS_SERVER_PWD || flags.redisPswd || "";//redis 密码
const MQTT_VIDEO_SERVER = process.env.MQTT_VIDEO_SERVER || flags.mqttVideoServer;
const IOT_AUTH_API = process.env.IOT_AUTH_API || flags.iotAuthApi;
const IOT_VIDEO_SERVER_URL = process.env.IOT_VIDEO_SERVER_URL || flags.iotVideoServerUrl
const AXY_API_URL = process.env.AXY_API_URL || flags.axyApiUrl;
@ -36,7 +39,7 @@ const GOD_URL = process.env.GOD_URL || flags.godUrl || 'https://restapi.amap.com
const GOD_KEY = process.env.GOD_KEY || flags.godKey;
const YINGSHI_URL = process.env.YINGSHI_URL || flags.yingshiUrl || 'https://open.ys7.com/api';
if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY) {
if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY || !MQTT_VIDEO_SERVER) {
console.log('缺少启动参数,异常退出');
args.showHelp();
process.exit(-1);
@ -65,7 +68,11 @@ const product = {
port: IOTA_REDIS_SERVER_PORT,
pwd: IOTA_REDIS_SERVER_PWD
},
pssaRequest: [{// name 会作为一个 request 出现在 ctx.app.fs
mqtt: {
mqttVideoServer: MQTT_VIDEO_SERVER,
},
pssaRequest: [
{// name 会作为一个 request 出现在 ctx.app.fs
name: 'authRequest',
root: IOT_AUTH_API
}, {
@ -91,7 +98,8 @@ const product = {
name: 'videoServerRequest',
root: IOT_VIDEO_SERVER_URL + '/api',
dataWord: 'text'
},]
},
]
}
}
],

1
code/VideoAccess-VCMP/api/package.json

@ -23,6 +23,7 @@
"koa-convert": "^1.2.0",
"koa-proxy": "^0.9.0",
"moment": "^2.24.0",
"mqtt": "^4.3.7",
"path": "^0.12.7",
"path-to-regexp": "^3.0.0",
"pg": "^7.9.0",

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-control-select.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-control-unselect.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-fullScreen-select.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-fullScreen-unselect.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-histroy-select.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-histroy-unselect.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-talk-select.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-talk-unselect.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/videoPlayBg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

1
code/VideoAccess-VCMP/web/client/assets/js/jessibuca/decoder.js

File diff suppressed because one or more lines are too long

BIN
code/VideoAccess-VCMP/web/client/assets/js/jessibuca/decoder.wasm

Binary file not shown.

1
code/VideoAccess-VCMP/web/client/assets/js/jessibuca/jessibuca.js

File diff suppressed because one or more lines are too long

BIN
code/VideoAccess-VCMP/web/client/assets/video/cross_loading.mp4

Binary file not shown.

BIN
code/VideoAccess-VCMP/web/client/assets/video/login_bg.mp4

Binary file not shown.

1
code/VideoAccess-VCMP/web/client/index.ejs

@ -5,6 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
<link rel="shortcut icon" href="/assets/images/favicon.ico">
<script src="/assets/js/jessibuca/jessibuca.js"></script>
</head>
<body>

1
code/VideoAccess-VCMP/web/client/index.html

@ -5,6 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
<link rel="shortcut icon" href="/assets/images/favicon.ico">
<script src="/assets/js/jessibuca/jessibuca.js"></script>
</head>
<body>

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

@ -2,9 +2,11 @@
import SimpleFileDownButton from './simpleFileDownButton'
import Coming from './coming'
import ReminderBox from './reminderBox'
import VideoPlayModal from './videoPlayModal'
export {
SimpleFileDownButton,
Coming,
ReminderBox
ReminderBox,
VideoPlayModal,
};

48
code/VideoAccess-VCMP/web/client/src/components/textScroll.jsx

@ -0,0 +1,48 @@
import React, { useRef, useEffect, useState } from 'react'
import moment from 'moment'
import './textScroll.less'
function TextScroll (props) {
const { content, duration } = props
const [showContent, setShowContent] = useState('1231231')
useEffect(() => {
let repeatTime = moment()
let refreshTime = moment()
const scroll = () => {
let contentParent = document.getElementById('marquee_box')
document.getElementById('contentPMakeUp').style.width = contentParent.clientWidth + 'px'
//
if (moment().diff(refreshTime) > 1000 / 60) {
const contentP = document.getElementById('contentP')
//
if (moment().diff(repeatTime) > 1000 * 1.5) {
contentP.style.visibility = 'visible'
}
if (moment().diff(repeatTime) > 1000 * 3) {
contentParent.scrollLeft = contentParent.scrollLeft + 1
}
if (contentParent.scrollLeft >= contentP.clientWidth + 24) {
contentParent.scrollLeft = 0
repeatTime = moment()
setShowContent('asdasd' + Math.random())
contentP.style.visibility = 'hidden'
}
refreshTime = moment()
}
window.requestAnimationFrame(scroll)
}
window.requestAnimationFrame(scroll)
}, [])
return (
<div className="marquee_box" id='marquee_box' style={{ overflow: 'hidden' }} >
<p style={{ position: 'relative', left: 24 }}>
<p id='contentP' style={{ display: 'inline-block', visibility: 'hidden' }}>{showContent}</p>
<p id='contentPMakeUp' style={{ width: 0, display: 'inline-block' }}></p>
</p>
</div>
)
}
export default React.memo(TextScroll)

19
code/VideoAccess-VCMP/web/client/src/components/textScroll.less

@ -0,0 +1,19 @@
.marquee_box {
width: 100%;
height: 100%;
word-break: keep-all;
white-space: nowrap;
// display: flex;
// align-items: center;
}
.marquee_box p {
// display: inline-block;
padding: 0;
margin: 0;
}
.marquee_box:hover p {
animation-play-state: paused;
cursor: default;
}

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

@ -0,0 +1,143 @@
import React, { useState, useEffect, useRef } from "react";
import { connect } from "react-redux";
import moment from 'moment'
import { Button, Modal, Col, Row, Space } from "@douyinfe/semi-ui";
import TextScroll from './textScroll'
import './videoPlay.less';
const VideoPlay = ({ height, width }) => {
const [jessibuca, setjessibuca] = useState(null)
const [playUrl, setPlayUrl] = useState('http://flv.bdplay.nodemedia.cn/live/bbb.flv')
const [isPlaying, setIsPlaying] = useState(false)
const [operationState, setoperationState] = useState()
const operation = [{
key: 'control',
click: () => { console.log(121212); }
}, {
key: 'talk',
click: () => { console.log(121212); }
}, {
key: 'fullScreen',
click: () => { console.log(121212); }
}, {
key: 'histroy',
click: () => { console.log(121212); }
},]
useEffect(() => {
create()
let nextOperationState = {}
for (let p of operation) {
nextOperationState[p.key] = {
select: false
}
}
setoperationState(nextOperationState)
}, [])
const create = () => {
let $container = document.getElementById('container');
const jessibuca = new window.Jessibuca({
container: $container,
videoBuffer: 0.2, //
isResize: false,
text: "",
loadingText: "加载中",
debug: true,
showBandwidth: true, //
operateBtns: {
fullscreen: true,
screenshot: true,
play: true,
audio: true,
},
forceNoOffscreen: false,
isNotMute: false,
});
setjessibuca(jessibuca)
}
useEffect(() => {
play()
}, [jessibuca])
const play = () => {
if (jessibuca && playUrl) {
jessibuca.play(playUrl);
setIsPlaying(true)
}
}
const pause = () => {
if (jessibuca) {
jessibuca.pause();
setIsPlaying(false)
}
}
const butStyle = {
border: '1px solid #fff', display: 'inline-block', color: '#fff', padding: '0 10px',
display: 'flex', alignItems: 'center', height: '64%', marginLeft: 12
}
return (
<>
<div style={{ height: height || '100%', width: width || '100%' }}>
<div style={{ position: 'relative', }}>
<div style={{
height: 42, lineHeight: '42px', background: '#00000026',
position: 'absolute', width: '100%', zIndex: 99,
color: '#fff'
}}>
<Row >
<Col span={9} style={{
backgroundImage: 'url(/assets/images/background/videoPlayBg.png)',
backgroundSize: '100% 100%',
backgroundRepeat: 'no-repeat',
textAlign: 'center'
}}>123</Col>
<Col span={15} style={{}}>
<div style={{ paddingRight: 12 }}>
<TextScroll content={['asdadasdasdasdasdasd','123123']} duration={6} />
</div>
</Col>
</Row>
</div>
<div id="container" style={{ height: height || '100%', width: width || '100%' }}></div>
<div style={{
height: 42, lineHeight: '42px', background: 'linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%)', padding: '0 12px',
display: 'flex', justifyContent: 'space-between',
position: 'absolute', bottom: 0, width: '100%', zIndex: 99
}}>
<div style={{ display: 'flex', alignItems: 'center' }}>
{
operationState ?
operation.map(p => {
return <img
src={`/assets/images/background/video-icon-${p.key}-${operationState[p.key].select ? 'select' : 'unselect'}.png`}
height={26}
style={{ marginRight: 24 }}
/>
}) : ''
}
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={butStyle}>标清</div>
<div style={butStyle}>高清</div>
</div>
</div>
</div>
</div>
</>
)
}
function mapStateToProps (state) {
const { auth } = state;
return {
user: auth.user,
};
}
export default connect(mapStateToProps)(VideoPlay);

0
code/VideoAccess-VCMP/web/client/src/components/videoPlay.less

32
code/VideoAccess-VCMP/web/client/src/components/videoPlayModal.jsx

@ -0,0 +1,32 @@
import React, { useState, useEffect, useRef } from "react";
import { connect } from "react-redux";
import moment from 'moment'
import { Button, Modal, } from "@douyinfe/semi-ui";
import VideoPlay from './videoPlay'
import './videoPlayModal.less';
const VideoPlayModal = ({ visible }) => {
return (
<Modal
visible={visible}
header={null}
footer={null}
size={'large'}
style={{}}
bodyStyle={{}}
className="videoModal"
>
<VideoPlay height={460} />
</Modal>
)
}
function mapStateToProps (state) {
const { auth } = state;
return {
user: auth.user,
};
}
export default connect(mapStateToProps)(VideoPlayModal);

5
code/VideoAccess-VCMP/web/client/src/components/videoPlayModal.less

@ -0,0 +1,5 @@
.videoModal {
.semi-modal-content {
padding: 0;
}
}

11
code/VideoAccess-VCMP/web/client/src/layout/containers/layout/index.jsx

@ -71,6 +71,7 @@ const LayoutContainer = props => {
if (dom) {
if (!scrollbar) {
scrollbar = new PerfectScrollbar('#page-content', { suppressScrollX: true });
scrollbar.update();
} else {
scrollbar.update();
dom.scrollTop = 0;
@ -85,8 +86,16 @@ const LayoutContainer = props => {
<div style={{
position: 'absolute', height: '100%', width: '100%',
display: 'flex', alignItems: 'center', placeContent: 'center',
backgroundColor: "#000"
}}>
载入中...
<video
autoPlay loop muted
style={{
// width: "100%", objectFit: "cover", objectPosition: 'left top', height: 'calc(100vh - 4px)'
}}
src="/assets/video/cross_loading.mp4"
type="video/mp4"
/>
</div>
:
<>

5
code/VideoAccess-VCMP/web/client/src/layout/index.jsx

@ -150,6 +150,7 @@ const Root = props => {
/>
)))
// IOT system cross
window.addEventListener('message', async function (e) { // message
const { data } = e
if (data && data.action) {
@ -162,7 +163,7 @@ const Root = props => {
setAuthCrossLoading(false)
});
setAuthCrossLoading(false)
// setAuthCrossLoading(false)
}, [])
return (
@ -191,7 +192,7 @@ const Root = props => {
</ConfigProvider>
: ''
}
<iframe id="iotAuth" src={"http://10.8.30.82:5200/cross"} style={{ position: 'absolute', top: 0, height: 1, visibility: 'hidden' }} frameBorder={0} >
<iframe id="iotAuth" src={"http://10.8.30.7:5200/cross"} style={{ position: 'absolute', top: 0, height: 1, visibility: 'hidden' }} frameBorder={0} >
<p>你的浏览器不支持 iframe</p>
</iframe>
</>

18
code/VideoAccess-VCMP/web/client/src/sections/auth/containers/login.jsx

@ -30,12 +30,20 @@ const Login = props => {
return (
<div style={{
height: '100vh',
backgroundImage: "url('/assets/images/background/loginBackground.png')",
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
position: 'relative',
// height: '100vh',
// backgroundImage: "url('/assets/images/background/loginBackground.png')",
// backgroundSize: 'cover',
// backgroundRepeat: 'no-repeat',
// position: 'relative',
}}>
<video
autoPlay loop muted
style={{
width: "100%", objectFit: "cover", objectPosition: 'left top', height: 'calc(100vh - 4px)'
}}
src="/assets/video/login_bg.mp4"
type="video/mp4"
/>
<div style={{
width: 446,
height: 348,

2
code/VideoAccess-VCMP/web/package.json

@ -7,7 +7,7 @@
"test": "mocha",
"start-vite": "cross-env NODE_ENV=developmentVite npm run start-params",
"start": "cross-env NODE_ENV=development npm run start-params",
"start-params": "node server -p 5000 -u http://10.8.30.82:4000 --apiAuthUrl http://10.8.30.82:4200",
"start-params": "node server -p 5000 -u http://10.8.30.7:4000 --apiAuthUrl http://10.8.30.7:4200",
"deploy": "export NODE_ENV=production&& npm run build && node server",
"build-dev": "cross-env NODE_ENV=development&&webpack --config webpack.config.js",
"build": "export NODE_ENV=production&&webpack --config webpack.config.prod.js"

Loading…
Cancel
Save