巴林闲侠
2 years ago
22 changed files with 417 additions and 153 deletions
@ -0,0 +1,59 @@ |
|||
'use strict'; |
|||
const moment = require('moment') |
|||
const request = require('superagent') |
|||
|
|||
function videoList (opts) { |
|||
return async function (ctx) { |
|||
try { |
|||
const { models, } = ctx.fs.dc; |
|||
const { app, yingshiTokenRes } = ctx |
|||
|
|||
let yingshiToken = '' |
|||
if (yingshiTokenRes && yingshiTokenRes.token && yingshiTokenRes.expire && moment().isBefore(moment(yingshiTokenRes.expire))) { |
|||
yingshiToken = yingshiTokenRes.token |
|||
} else { |
|||
const tokenRes = await app.fs.yingshiRequest.post(`lapp/token/get`, { |
|||
query: { |
|||
appKey: opts.yingshiKey, |
|||
appSecret: opts.yingshiSecret |
|||
} |
|||
}) |
|||
if (tokenRes.code == 200 && tokenRes.data) { |
|||
const { accessToken, expireTime } = tokenRes.data |
|||
|
|||
ctx.yingshiTokenRes = { |
|||
token: accessToken, |
|||
expire: expireTime |
|||
} |
|||
yingshiToken = accessToken |
|||
} else { |
|||
throw '未能获取进行萤石鉴权' |
|||
} |
|||
} |
|||
|
|||
const deviceRes = await app.fs.yingshiRequest.post(`lapp/device/list`, { |
|||
query: { |
|||
accessToken: yingshiToken, |
|||
} |
|||
}) |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = (deviceRes.data || []).map(item => { |
|||
return { |
|||
...item, |
|||
token: yingshiToken, |
|||
} |
|||
}) |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
message: typeof error == 'string' ? error : undefined |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
videoList |
|||
}; |
@ -1,50 +0,0 @@ |
|||
'use strict'; |
|||
|
|||
const request = require('superagent'); |
|||
const buildUrl = (url,token) => { |
|||
let connector = url.indexOf('?') === -1 ? '?' : '&'; |
|||
return `${url}${connector}token=${token}`; |
|||
}; |
|||
|
|||
function factory(app, router, opts) { |
|||
return async function (ctx, next) { |
|||
|
|||
const token = ctx.fs.api.token; |
|||
|
|||
//console.log(username,password)
|
|||
const req = { |
|||
get: (url, query) => { |
|||
return request |
|||
.get(buildUrl(url,token)) |
|||
.query(query) |
|||
}, |
|||
post: (url, data, query) => { |
|||
return request |
|||
.post(buildUrl(url,token)) |
|||
.query(query) |
|||
//.set('Content-Type', 'application/json')
|
|||
.send(data); |
|||
}, |
|||
|
|||
put: (url, data) => { |
|||
return request |
|||
.put(buildUrl(url,token)) |
|||
//.set('Content-Type', 'application/json')
|
|||
.send(data); |
|||
}, |
|||
|
|||
delete: (url) => { |
|||
return request |
|||
.del(buildUrl(url,token)) |
|||
}, |
|||
}; |
|||
|
|||
app.business = app.business || {}; |
|||
app.business.request = req; |
|||
|
|||
await next(); |
|||
}; |
|||
} |
|||
|
|||
module.exports = factory; |
|||
|
@ -0,0 +1,67 @@ |
|||
'use strict'; |
|||
const request = require('superagent') |
|||
|
|||
class paasRequest { |
|||
constructor(root, { query = {} } = {}, option) { |
|||
this.root = root; |
|||
this.query = query |
|||
this.option = option |
|||
} |
|||
|
|||
#buildUrl = (url) => { |
|||
return `${this.root}/${url}`; |
|||
} |
|||
|
|||
#resultHandler = (resolve, reject) => { |
|||
return (err, res) => { |
|||
if (err) { |
|||
reject(err); |
|||
} else { |
|||
resolve(res[this.option.dataWord]); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
get = (url, { query = {}, header = {} } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.get(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
|
|||
post = (url, { data = {}, query = {}, header = {} } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.post(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
|
|||
put = (url, { data = {}, header = {}, query = {}, } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.put(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
|
|||
delete = (url, { header = {}, query = {} } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.delete(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
} |
|||
|
|||
function factory (app, opts) { |
|||
if (opts.pssaRequest) { |
|||
try { |
|||
for (let r of opts.pssaRequest) { |
|||
if (r.name && r.root) { |
|||
app.fs[r.name] = new paasRequest(r.root, { ...(r.params || {}) }, { dataWord: r.dataWord || 'body' }) |
|||
} else { |
|||
throw 'opts.pssaRequest 参数错误!' |
|||
} |
|||
} |
|||
} catch (error) { |
|||
console.error(error) |
|||
process.exit(-1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = factory; |
@ -0,0 +1,52 @@ |
|||
/** |
|||
* 萤石视频直播(基于萤石云iframe模式,使用方式简单) |
|||
* 官方参考:https://open.ys7.com/console/ezopenIframe.html
|
|||
*/ |
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
|
|||
const YSIframePlayer = props => { |
|||
|
|||
const { containerId, height, width, url, autoplay, audio, videoState, ysToken } = props; |
|||
const at = ysToken |
|||
if (!url || !at) return null; |
|||
const src = `https://open.ys7.com/ezopen/h5/iframe?audio=${audio ? '1' : '0'}&url=${url}&autoplay=${autoplay || 1}&accessToken=${at}` |
|||
// const src = `https://open.ys7.com/ezopen/h5/iframe?audio=1&url=${url}&autoplay=${autoplay || 1}&accessToken=${at}`
|
|||
return ( |
|||
<div |
|||
style={{ position: 'relative', height: '100%', width: '100%' }}> |
|||
<iframe |
|||
frameBorder="0" |
|||
id={containerId || 'myPlayer'} |
|||
src={src} |
|||
// https://open.ys7.com/doc/zh/book/index/live_proto.html 单个播放器的长宽比例限制最小为{width: 400px;height: 300px;}
|
|||
width={width || 400} |
|||
height={height || 300} |
|||
allowFullScreen |
|||
wmode="transparent" |
|||
> |
|||
</iframe> |
|||
{ |
|||
videoState && videoState.status == 0 ? |
|||
<div style={{ |
|||
height: width || 300, width: width || 400, position: 'absolute', top: 0, background: '#000', |
|||
display: 'flex', justifyContent: 'center', alignItems: 'center', color: '#fff' |
|||
}}> |
|||
设备中断,正在处理中... |
|||
</div> |
|||
: '' |
|||
} |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps (state) { |
|||
const { auth, } = state; |
|||
return { |
|||
user: auth.user, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(YSIframePlayer); |
@ -0,0 +1,30 @@ |
|||
import React, { useState, useEffect } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { getAssess, delAssess, editAssess } from '../actions/assess'; |
|||
import ProTable from '@ant-design/pro-table'; |
|||
import AssessModal from '../components/assessModal'; |
|||
import { Form, Space, DatePicker, Button, Select, Popconfirm } from 'antd' |
|||
import moment from 'moment'; |
|||
|
|||
function VideoCenter (props) { |
|||
const { dispatch, vcmpWebUrl, vcmpMirrorId } = props; |
|||
|
|||
useEffect(() => { |
|||
return () => { }; |
|||
}, []); |
|||
|
|||
return ( |
|||
<div> |
|||
<iframe src={`${vcmpWebUrl}/callService?mid=${vcmpMirrorId}`} style={{ height: 'calc(100vh - 142px)', width: '100%', display: 'block' }} frameBorder={0}></iframe> |
|||
</div> |
|||
); |
|||
} |
|||
function mapStateToProps (state) { |
|||
const { auth, global } = state |
|||
return { |
|||
user: auth.user, |
|||
vcmpWebUrl: global.vcmpWebUrl, |
|||
vcmpMirrorId: global.vcmpMirrorId, |
|||
} |
|||
} |
|||
export default connect(mapStateToProps)(VideoCenter); |
@ -1,19 +1,30 @@ |
|||
import React from 'react' |
|||
import React, { useEffect, useState } from 'react' |
|||
import Left from './left' |
|||
import Right from './right' |
|||
import CenterLeft from "./centerLeft" |
|||
import Centerright from "./centerRight" |
|||
import { connect } from 'react-redux' |
|||
import { getNearestAssessData, getVideoCenterList } from "../../../actions/example" |
|||
|
|||
const Leadership = (props) => { |
|||
const { dispatch } = props |
|||
|
|||
useEffect(() => { |
|||
dispatch(getVideoCenterList()) |
|||
}, []) |
|||
|
|||
return ( |
|||
<> |
|||
<Left dispatch={dispatch} /> |
|||
<CenterLeft dispatch={dispatch} /> |
|||
<Right dispatch={dispatch} /> |
|||
{/* <Centerright /> */} |
|||
|
|||
</> |
|||
) |
|||
} |
|||
export default Leadership |
|||
function mapStateToProps (state) { |
|||
return { |
|||
|
|||
} |
|||
} |
|||
export default connect(mapStateToProps)(Leadership) |
@ -1,95 +1,116 @@ |
|||
import React, { useEffect, useState } from 'react' |
|||
import Module from '../../../public/module' |
|||
import Lunbo from "../right/lunbo" |
|||
import { connect } from 'react-redux' |
|||
// import "./left.less"
|
|||
|
|||
const Leftcenter = () => { |
|||
const style = { height: "30%", marginTop: "5%" } |
|||
// const hualun = "auto"
|
|||
const [num, setNum] = useState(1); |
|||
const [tu, setTu] = useState(""); |
|||
const [name, setName] = useState(""); |
|||
const [list, setList] = useState([ |
|||
{ name: '沙潭至五星', img: "/assets/images/leadership/fake/1.jpg" }, |
|||
{ name: '滁槎至协城', img: "/assets/images/leadership/fake/2.jpg" }, |
|||
{ name: '瓜山至广福', img: "/assets/images/leadership/fake/3.jpg" }, |
|||
{ name: '罗舍至泗洪', img: "/assets/images/leadership/fake/4.jpg" }, |
|||
{ name: '渔业至万州', img: "/assets/images/leadership/fake/5.jpg" }, |
|||
// { name: '小蓝至东新', img: "/assets/images/leadership/shiyantu.png" },
|
|||
]) |
|||
useEffect(() => { |
|||
const timer = setInterval(() => { |
|||
if (num == list.length) { |
|||
setNum(1); |
|||
setTu(list[0].img); |
|||
} else { |
|||
setNum(num + 1); |
|||
setTu(list[num].img); |
|||
} |
|||
}, 2000); |
|||
return () => clearInterval(timer); |
|||
}, [num]); |
|||
const renderBody = () => { |
|||
return ( |
|||
<div style={{ width: "100%", height: "55%" }}>{ |
|||
list.map((item, index) => { |
|||
return ( |
|||
// <div style={{ width: "100%", height: "100%" }} >
|
|||
// {/* <div style={{ width: "100%", height: "100%", }}> */}
|
|||
<li style={{ height: "20px", position: "relative", width: "100%", marginTop: index == 0 ? "4px" : "5px", listStyle: "none", borderLeft: num - 1 == index ? "2px solid #1C60FE" : "2px solid #113892", backgroundColor: "linear-gradient(to right, rgba(0,70,200,0.3000) , rgba(0,124,230,0))" }} onMouseEnter={() => { |
|||
setTu(item.img); |
|||
setNum(index + 1); |
|||
setName(item.name) |
|||
// console.log(list);
|
|||
}}> |
|||
<p style={{ position: "absolute", color: num - 1 == index ? "#fff" : "rgba(216,240,255,0.8)", left: "10%" }}>{item.name}</p> |
|||
<img src='/assets/images/leadership/juxing.png' style={{ width: "100%", height: "100%", position: "absolute" }} /> |
|||
</li> |
|||
// {/* </div> */}
|
|||
// </div>
|
|||
) |
|||
const Leftcenter = ({ videoCenterList }) => { |
|||
console.log(videoCenterList); |
|||
const style = { height: "30%", marginTop: "5%" } |
|||
// const hualun = "auto"
|
|||
const [num, setNum] = useState(1); |
|||
const [tu, setTu] = useState(""); |
|||
const [name, setName] = useState(""); |
|||
const [list, setList] = useState([ |
|||
// { name: '沙潭至五星', img: "/assets/images/leadership/fake/1.jpg" },
|
|||
// { name: '滁槎至协城', img: "/assets/images/leadership/fake/2.jpg" },
|
|||
// { name: '瓜山至广福', img: "/assets/images/leadership/fake/3.jpg" },
|
|||
// { name: '罗舍至泗洪', img: "/assets/images/leadership/fake/4.jpg" },
|
|||
// { name: '渔业至万州', img: "/assets/images/leadership/fake/5.jpg" },
|
|||
|
|||
}) |
|||
} |
|||
</div > |
|||
) |
|||
} |
|||
return ( |
|||
<> |
|||
<div style={{ width: "100%", height: "40px"/* , backgroundColor: "#fff" */, position: "relative" }}> |
|||
{/* <p>{title || []}</p> */} |
|||
<img src='/assets/images/quanju/icon.png' style={{ width: "24px", position: "absolute", left: "20px", top: "20%" }} /> |
|||
<span style={{ position: "absolute", color: "#FFFFFF", fontSize: "24px", fontFamily: "YouSheBiaoTiHei", left: "50px" }}>主要路段拥堵情况</span> |
|||
<img src='/assets/images/leadership/zibiaoti.png' style={{ width: "93%", height: "35px", position: "absolute", top: "8px", left: "35px" }} /> |
|||
</div> |
|||
<div style={{ width: "100%", height: "100%", marginTop: "3%" }}> |
|||
<div style={{ width: "60%", height: "100%", float: "left", marginLeft: "1%" }}> |
|||
{ |
|||
list.map((item, index) => { |
|||
return index + 1 == num ? |
|||
<div style={{ width: "100%", height: "100%", position: "relative" }}> |
|||
// { name: '小蓝至东新', img: "/assets/images/leadership/shiyantu.png" },
|
|||
]) |
|||
|
|||
<img style={{ width: "100%",height:'100%', position: "absolute", bottom: "5%" }} src={item.img} /> |
|||
<p style={{ |
|||
width: "100%", height: "3vh", position: "absolute", bottom: "3%", |
|||
backgroundColor: "rgba(0,0,0,0.26)", lineHeight: "3vh", textAlign: "" |
|||
}}> |
|||
<img src='/assets/images/leadership/weizhis.png' style={{ width: "5%", height: "60%", marginLeft: "3%" }} /> |
|||
<span style={{ marginLeft: "3%", color: "#FFFFFF", fontSize: "12px", fontFamily: "PingFangSC-Regular, PingFang SC", fontWeight: 400 }}>{item.name}</span></p> |
|||
</div> : "" |
|||
useEffect(() => { |
|||
if (videoCenterList.length) { |
|||
setList(videoCenterList.slice(0, 5)) |
|||
} |
|||
}, [videoCenterList]) |
|||
|
|||
}) |
|||
} |
|||
useEffect(() => { |
|||
const timer = setInterval(() => { |
|||
if (num == list.length) { |
|||
setNum(1); |
|||
setTu(list[0].img); |
|||
} else { |
|||
setNum(num + 1); |
|||
setTu(list[num].img); |
|||
} |
|||
}, 2000 * 10); |
|||
return () => clearInterval(timer); |
|||
}, [num]); |
|||
|
|||
const renderBody = () => { |
|||
return ( |
|||
<div style={{ width: "100%", height: "55%" }}>{ |
|||
list.map((item, index) => { |
|||
return ( |
|||
// <div style={{ width: "100%", height: "100%" }} >
|
|||
// {/* <div style={{ width: "100%", height: "100%", }}> */}
|
|||
<li style={{ height: "20px", position: "relative", width: "100%", marginTop: index == 0 ? "4px" : "5px", listStyle: "none", borderLeft: num - 1 == index ? "2px solid #1C60FE" : "2px solid #113892", backgroundColor: "linear-gradient(to right, rgba(0,70,200,0.3000) , rgba(0,124,230,0))" }} onMouseEnter={() => { |
|||
setTu(item.img); |
|||
setNum(index + 1); |
|||
setName(item.deviceName) |
|||
// console.log(list);
|
|||
}}> |
|||
<p style={{ position: "absolute", color: num - 1 == index ? "#fff" : "rgba(216,240,255,0.8)", left: "10%" }}>{item.deviceName}</p> |
|||
<img src='/assets/images/leadership/juxing.png' style={{ width: "100%", height: "100%", position: "absolute" }} /> |
|||
</li> |
|||
// {/* </div> */}
|
|||
// </div>
|
|||
) |
|||
|
|||
}) |
|||
} |
|||
</div > |
|||
) |
|||
} |
|||
return ( |
|||
<> |
|||
<div style={{ width: "100%", height: "40px"/* , backgroundColor: "#fff" */, position: "relative" }}> |
|||
{/* <p>{title || []}</p> */} |
|||
<img src='/assets/images/quanju/icon.png' style={{ width: "24px", position: "absolute", left: "20px", top: "20%" }} /> |
|||
<span style={{ position: "absolute", color: "#FFFFFF", fontSize: "24px", fontFamily: "YouSheBiaoTiHei", left: "50px" }}>主要路段拥堵情况</span> |
|||
<img src='/assets/images/leadership/zibiaoti.png' style={{ width: "93%", height: "35px", position: "absolute", top: "8px", left: "35px" }} /> |
|||
</div> |
|||
<Lunbo |
|||
// canScroll={true}
|
|||
content={renderBody()} |
|||
containerStyle={{ position: "relative", height: "100%", width: "35%", float: "right", marginRight: "2%", marginTop: "1%" }} |
|||
divHeight={"100%"} |
|||
divId={"screen-slope-midde-top-jiangxi"} |
|||
/> |
|||
</div> |
|||
</> |
|||
) |
|||
<div style={{ width: "100%", height: "100%", marginTop: "3%" }}> |
|||
<div style={{ width: "60%", height: "100%", float: "left", marginLeft: "1%" }}> |
|||
{ |
|||
list.map((item, index) => { |
|||
return index + 1 == num ? |
|||
<div style={{ width: "100%", height: "100%", position: "relative" }}> |
|||
|
|||
<img style={{ width: "100%", height: '100%', position: "absolute", bottom: "5%" }} src={item.img} /> |
|||
<p style={{ |
|||
width: "100%", height: "3vh", position: "absolute", bottom: "3%", |
|||
backgroundColor: "rgba(0,0,0,0.26)", lineHeight: "3vh", textAlign: "" |
|||
}}> |
|||
<img src='/assets/images/leadership/weizhis.png' style={{ width: "5%", height: "60%", marginLeft: "3%" }} /> |
|||
<span style={{ marginLeft: "3%", color: "#FFFFFF", fontSize: "12px", fontFamily: "PingFangSC-Regular, PingFang SC", fontWeight: 400 }}> |
|||
{item.deviceName} |
|||
</span> |
|||
</p> |
|||
|
|||
</div> : "" |
|||
}) |
|||
} |
|||
</div> |
|||
<Lunbo |
|||
// canScroll={true}
|
|||
content={renderBody()} |
|||
containerStyle={{ position: "relative", height: "100%", width: "35%", float: "right", marginRight: "2%", marginTop: "1%" }} |
|||
divHeight={"100%"} |
|||
divId={"screen-slope-midde-top-jiangxi"} |
|||
/> |
|||
</div> |
|||
</> |
|||
) |
|||
} |
|||
function mapStateToProps (state) { |
|||
const { videoCenterList } = state |
|||
|
|||
return { |
|||
videoCenterList: videoCenterList.data || [] |
|||
} |
|||
} |
|||
export default Leftcenter |
|||
export default connect(mapStateToProps)(Leftcenter) |
Loading…
Reference in new issue