Compare commits

...

27 Commits

Author SHA1 Message Date
CODE d50be8a368 增加串口配置2 1 year ago
巴林闲侠 a91a7b2a26 fix 视频播放累计延迟+参数修改不生效 1 year ago
巴林闲侠 de8e129035 离开主界面时候销毁播放器 1 year ago
巴林闲侠 8c9c425c9a 用解析不卡播放 2 years ago
巴林闲侠 9ee6434ce8 增加传感器参数 2 years ago
巴林闲侠 9fd2bf8fc6 flv播放延迟 2 years ago
巴林闲侠 ac1e9887ae 修改塔吊的告警配置 2 years ago
巴林闲侠 938adddfa9 设置页设置背景颜色 2 years ago
巴林闲侠 4780cd3dc6 flushStashedSamples 2 years ago
巴林闲侠 4615e48481 flv 播放 2 years ago
巴林闲侠 421f38203e 解析不卡方式播放 2 years ago
巴林闲侠 04aefef9ab 障碍物绘制 2 years ago
巴林闲侠 a9d6077b6f 障碍物坐标绘制 2 years ago
巴林闲侠 c4648a1d64 碰撞距离 2 years ago
巴林闲侠 943839ddca 视频和xy视图宽度 2 years ago
巴林闲侠 bb462e850e 视频和xy视图 2 years ago
巴林闲侠 b5a11a3c43 强制关闭进程接口 2 years ago
巴林闲侠 a302e9f58c 视频监控 2 years ago
巴林闲侠 ad846c162d 视频监控 2 years ago
巴林闲侠 152fd7058f 退出应用按钮 2 years ago
巴林闲侠 71ab59a68c 监控视频播放 2 years ago
殷伟文 34c125c5d9 更新 'console/Dockerfile' 2 years ago
巴林闲侠 ce1068fdbd del lock 2 years ago
巴林闲侠 769f1e3a41 del electron 2 years ago
巴林闲侠 edb0a76729 告警颜色 2 years ago
巴林闲侠 1a88eab824 // const parse = require('async-busboy'); 2 years ago
巴林闲侠 47cd2fa5ca 精简依赖包 2 years ago
  1. 1
      .gitignore
  2. 6
      console/Dockerfile
  3. 2
      console/client/assets/env.js
  4. 10
      console/client/assets/js/flv.min.js
  5. 8201
      console/client/assets/js/jessibuca/decoder.js
  6. BIN
      console/client/assets/js/jessibuca/decoder.wasm
  7. 13125
      console/client/assets/js/jessibuca/jessibuca.js
  8. 1
      console/client/assets/js/jessibuca/manifest.json
  9. 13
      console/client/index.ejs
  10. 3
      console/client/index.html
  11. 26
      console/client/src/sections/console/actions/index.js
  12. 71
      console/client/src/sections/console/components/videoModal.js
  13. 425
      console/client/src/sections/console/containers/index.js
  14. 115
      console/client/src/sections/console/containers/setUp.js
  15. 30
      console/client/src/utils/hooks.js
  16. 2
      console/client/src/utils/index.js
  17. 3
      console/client/src/utils/webapi.js
  18. 594
      console/log/development.txt
  19. 46
      console/main.js
  20. 12325
      console/package-lock.json
  21. 20
      console/package.json
  22. 159
      console/routes/attachment/index.js

1
.gitignore

@ -0,0 +1 @@
*development.txt

6
console/Dockerfile

@ -16,6 +16,12 @@ RUN rm -rf node_modules
RUN npm install --production --registry http://10.8.30.22:7000 RUN npm install --production --registry http://10.8.30.22:7000
#RUN npm cache clean -f && npm install --production --force --registry http://10.8.30.22:7000 #RUN npm cache clean -f && npm install --production --force --registry http://10.8.30.22:7000
FROM arm64v8/node:12-alpine
WORKDIR /var/app
COPY --from=0 /var/app /var/app
CMD ["-u", "http://localhost:8088"] CMD ["-u", "http://localhost:8088"]
ENTRYPOINT [ "node", "server.js" ] ENTRYPOINT [ "node", "server.js" ]

2
console/client/assets/env.js

@ -1 +1 @@
window.FS_API_ROOT = 'http://10.8.30.183:4100' window.FS_API_ROOT = 'http://127.0.0.1:4100'

10
console/client/assets/js/flv.min.js

File diff suppressed because one or more lines are too long

8201
console/client/assets/js/jessibuca/decoder.js

File diff suppressed because it is too large

BIN
console/client/assets/js/jessibuca/decoder.wasm

Binary file not shown.

13125
console/client/assets/js/jessibuca/jessibuca.js

File diff suppressed because one or more lines are too long

1
console/client/assets/js/jessibuca/manifest.json

@ -0,0 +1 @@
{}

13
console/client/index.ejs

@ -1,18 +1,19 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="shortcut icon" href="/assets/images/logo.png"> <link rel="shortcut icon" href="/assets/images/logo.png">
<link rel="stylesheet" type="text/css" href="/assets/font_sc/iconfont.css"> <link rel="stylesheet" type="text/css" href="/assets/font_sc/iconfont.css">
<script type="text/javascript" src="/assets/env.js"></script> <script type="text/javascript" src="/assets/env.js"></script>
</head> <script type="text/javascript" src="/assets/js/jessibuca/jessibuca.js"></script>
<style> </head>
<style>
</style> </style>
<body style="background: transparent"> <body style="background: transparent">
<div id='App'></div> <div id='App'></div>
</body> </body>
</html> </html>

3
console/client/index.html

@ -1,4 +1,4 @@
<!DOCTYPE html> <!-- <!DOCTYPE html> -->
<html> <html>
<head> <head>
@ -7,6 +7,7 @@
<link rel="shortcut icon" href="/assets/images/logo.png"> <link rel="shortcut icon" href="/assets/images/logo.png">
<link rel="stylesheet" type="text/css" href="/assets/font_sc/iconfont.css"> <link rel="stylesheet" type="text/css" href="/assets/font_sc/iconfont.css">
<script type="text/javascript" src="/assets/env.js"></script> <script type="text/javascript" src="/assets/env.js"></script>
<script type="text/javascript" src="/assets/js/jessibuca/jessibuca.js"></script>
</head> </head>
<style> <style>

26
console/client/src/sections/console/actions/index.js

@ -26,7 +26,33 @@ export function getCrane (params) {
}); });
} }
export function getVideo (params) {
return dispatch => basicAction({
type: 'get',
query: params,
dispatch: dispatch,
actionType: 'GET_VIDEO',
url: ApiTable.videoGet,
msg: { error: '获取视频信息失败' },
reducer: { name: 'video' }
});
}
export function logoutApp (params) {
return dispatch => basicAction({
type: 'post',
query: params,
dispatch: dispatch,
actionType: 'LOGOUT_APP',
url: ApiTable.logoutApp,
msg: { error: '退出应用失败' },
});
}
export default { export default {
editCrane, editCrane,
getCrane, getCrane,
getVideo,
logoutApp,
} }

71
console/client/src/sections/console/components/videoModal.js

@ -0,0 +1,71 @@
import React, { useEffect, useState, useRef } from 'react'
import { push } from 'react-router-redux';
import { connect } from 'react-redux';
import flvjs from 'flv.js'
import { getVideo } from '../actions'
import { Modal } from 'antd'
const VideoModal = ({ dispatch, onCancel }) => {
const [video, setVideo] = useState({})
const flvPlayer = useRef()
useEffect(() => {
dispatch(getVideo()).then(res => {
console.log(res);
if (res.success) {
setVideo(res.payload.data)
const container = document.getElementById('video-play');
const flv = flvjs.createPlayer({
type: 'flv',
url: `${res.payload.data.ws_flv}`,
isLive: true,
hasAudio: false,
hasVideo: true,
}, {
enableWorker: false,
enalleStashBuffer: true,
stashInitialSize: 128,
lazyLoadMaxDuration: 3 * 60,
seekType: 'range',
autoCleanupSourceBuffer: true,
cors: true,
});
flv.attachMediaElement(container);
flv.load();
flv.play();
flvPlayer.current = flv
}
})
}, [])
return (
<Modal
title="监控视频"
open={true}
onOk={() => { }}
onCancel={() => {
onCancel()
}}
width={'64%'}
style={{}}
footer={null}
>
<video
id={'video-play'}
autoPlay muted controls
style={{ height: '100%', width: '100%', }}
>
</video>
</Modal>
)
}
function mapStateToProps (state) {
const { crane } = state;
return {
craneData: crane.data || {}
}
}
export default connect(mapStateToProps)(VideoModal);

425
console/client/src/sections/console/containers/index.js

@ -2,14 +2,16 @@ import React, { useEffect, useState, useRef } from 'react'
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import request from 'superagent'; import request from 'superagent';
import { getCrane } from '../actions' import { getCrane, logoutApp, getVideo } from '../actions'
import { ApiTable } from '$utils' import { ApiTable } from '$utils'
import { Colors } from '@peace/utils' import { Colors } from '@peace/utils'
import { import {
SettingOutlined, VideoCameraOutlined SettingOutlined, VideoCameraOutlined, LogoutOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import VideoModal from '../components/videoModal'
import { Col, Row, Button, Modal, Input, Space } from 'antd'; import { Col, Row, Button, Modal, Input, Space } from 'antd';
import '../style.less' import '../style.less'
import flvjs from 'flv.js'
function calculateIntersection (cx, cy, d, angle) { function calculateIntersection (cx, cy, d, angle) {
// 将角度转换为弧度 // 将角度转换为弧度
@ -40,8 +42,12 @@ function calculateIntersection (cx, cy, d, angle) {
return [intersection_x, intersection_y]; return [intersection_x, intersection_y];
} }
let ws; let dataLiveWs;
let interval; let lidarLiveWs;
let dataLiveWsInterval;
let lidarLiveWsInterval;
let flvPlayerInterval;
let jessibucasInterval;
function Index (props) { function Index (props) {
const { dispatch, craneData } = props const { dispatch, craneData } = props
const xyCvs = useRef() const xyCvs = useRef()
@ -55,12 +61,32 @@ function Index (props) {
shadow: '#303030' shadow: '#303030'
}) })
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [videoVis, setVideoVis] = useState(false)
const [isOutModalOpen, setIsOutModalOpen] = useState(false)
const [video, setVideo] = useState({})
const flvPlayer = useRef(null)
const jessibucas = useRef(null)
const draw = (type, params = {}) => { const draw = (
type,
params = {
},
) => {
// params = {
// from: 'lidarLive',
// rotation: 78,
// }
if (type == 'xz') {
return
}
const canvasArea = document.getElementById('canvasArea') const canvasArea = document.getElementById('canvasArea')
const canvasHeight = canvasArea.clientHeight - 12 * 2 - 6 const canvasHeight = canvasArea.clientHeight - 12 * 2 - 6
const canvasWidth = canvasArea.clientWidth - 12 * 2 const canvasWidth = canvasArea.clientWidth / 14 * 10 - 12 * 2
const mainColor = "rgb(249,179,45)" const mainColor = "rgb(249,179,45)"
const dangerColor = "red"
if (type == 'xy') { if (type == 'xy') {
// xy 视图 // xy 视图
const xyCtx = xyCvs.current.getContext("2d"); const xyCtx = xyCvs.current.getContext("2d");
@ -69,9 +95,20 @@ function Index (props) {
const center = [canvasWidth / 2, canvasHeight / 2] const center = [canvasWidth / 2, canvasHeight / 2]
// 直径 // 直径
const diameter = Math.min(canvasWidth, canvasHeight) const diameter = Math.min(canvasWidth, canvasHeight)
// 半径
const radius = diameter / 2
console.log(radius);
// 参数半径和绘制半径的比值
const radiusRate = (params.radius || radius) / radius
console.log(radiusRate);
// 当前旋转角度
let curRotation =
params.from == 'lidarLive' ?
params?.rotation || 0 :
params?.rotation?.Value || 0;
// 画圆 // 画圆
xyCtx.beginPath(); xyCtx.beginPath();
xyCtx.arc(...center, diameter / 2, 0, 2 * Math.PI); xyCtx.arc(...center, radius, 0, 2 * Math.PI);
if (darkModde) { if (darkModde) {
xyCtx.strokeStyle = darkColor.subTextColor; xyCtx.strokeStyle = darkColor.subTextColor;
// xyCtx.fill(); // xyCtx.fill();
@ -84,22 +121,93 @@ function Index (props) {
xyCtx.fillStyle = mainColor; xyCtx.fillStyle = mainColor;
xyCtx.fill(); xyCtx.fill();
xyCtx.stroke(); xyCtx.stroke();
// 吊臂 // 吊臂 - 长~
let curRotation = params?.rotation?.Value || 42 let armLength = ((params.boom || radius) / radiusRate) * 2;
if (armLength <= (radius / 5)) {
armLength = radius / 5
}
xyCtx.moveTo(...center); xyCtx.moveTo(...center);
xyCtx.lineTo(...calculateIntersection(...center, diameter, curRotation)); xyCtx.lineTo(
// 配重臂 ...calculateIntersection(
...center,
armLength, // 臂长
curRotation
)
);
// 配重臂 - 尾巴
xyCtx.moveTo(...center); xyCtx.moveTo(...center);
xyCtx.lineTo(...calculateIntersection(...center, diameter / 8, curRotation + 180)); xyCtx.lineTo(...calculateIntersection(...center, diameter / 8, curRotation + 180));
xyCtx.strokeStyle = mainColor; xyCtx.strokeStyle = mainColor;
xyCtx.stroke(); xyCtx.stroke();
// 索 // 索 - 激光雷达 小点儿
xyCtx.beginPath(); xyCtx.beginPath();
xyCtx.arc(...calculateIntersection(...center, 168, curRotation), diameter / 48, 0, 2 * Math.PI); xyCtx.arc(
xyCtx.fillStyle = mainColor; ...calculateIntersection(
...center,
(params.lidar / radiusRate) * 2, // 绘制的离圆心的距离
curRotation
),
diameter / 128, // 点的大小
0,
2 * Math.PI
);
xyCtx.fillStyle = dangerColor;
xyCtx.fill();
xyCtx.stroke();
// 障碍物
// 测试数据
// params.blocks = [
// [
// {
// "X": 324,
// "Y": 231
// },
// {
// "X": 654,
// "Y": 234
// },
// {
// "X": 453,
// "Y": 231
// },
// {
// "X": 452,
// "Y": 34
// },
// {
// "X": 453,
// "Y": 34
// },
// {
// "X": 45,
// "Y": 67
// }
// ]
// ]
if (params.blocks && params.blocks.length) {
for (let block of params.blocks) {
if (block && block.length) {
for (let i = 0; i < block.length; i++) {
let point = block[i]
const x = point.X / radiusRate + center[0];
const y = point.Y / radiusRate + center[1];
if (i == 0) {
xyCtx.beginPath();
xyCtx.moveTo(x, y);
} else {
xyCtx.lineTo(x, y);
}
}
xyCtx.closePath();
xyCtx.lineWidth = 1;
xyCtx.strokeStyle = dangerColor;
xyCtx.fillStyle = dangerColor;
xyCtx.fill(); xyCtx.fill();
xyCtx.stroke(); xyCtx.stroke();
} }
}
}
}
if (type == 'xz') { if (type == 'xz') {
// xz 视图 // xz 视图
const xzCtx = xzCvs.current.getContext("2d"); const xzCtx = xzCvs.current.getContext("2d");
@ -433,31 +541,183 @@ function Index (props) {
dispatch(getCrane()) dispatch(getCrane())
// //
const root = window.FS_API_ROOT const root = window.FS_API_ROOT
ws = new WebSocket(`${root.replace('http', 'ws')}/${ApiTable.dataLive}`); //建立websocket连接
ws.onopen = function (e) { dataLiveWs = new WebSocket(`${root.replace('http', 'ws')}/${ApiTable.dataLive}`); //建立websocket连接
interval = setInterval(() => { dataLiveWs.onopen = function (e) {
dataLiveWsInterval = setInterval(() => {
// console.log("发送心跳保持长连接不超时断开"); // console.log("发送心跳保持长连接不超时断开");
this.send(JSON.stringify({ "act": "long_live" })); this.send(JSON.stringify({ "act": "long_live" }));
}, 20000);//20秒一次 }, 20000);//20秒一次
} }
ws.onerror = e => { dataLiveWs.onerror = e => {
console.log("websocket 发生错误:" + e) console.log("websocket dataLiveWs 发生错误:" + e)
} }
ws.onmessage = evt => { dataLiveWs.onmessage = evt => {
let msg = JSON.parse(evt.data); let msg = JSON.parse(evt.data);
if (msg) { if (msg) {
setCraneParams(msg) setCraneParams(msg)
draw('xy', msg) // draw('xy', msg)
draw('xz', msg) // draw('xz', msg)
}
}
lidarLiveWs = new WebSocket(`${root.replace('http', 'ws')}/${ApiTable.lidarLive}`); //建立websocket连接
lidarLiveWs.onopen = function (e) {
lidarLiveWsInterval = setInterval(() => {
// console.log("发送心跳保持长连接不超时断开");
this.send(JSON.stringify({ "act": "long_live" }));
}, 20000);//20秒一次
}
lidarLiveWs.onerror = e => {
console.log("websocket lidarLiveWs 发生错误:" + e)
}
lidarLiveWs.onmessage = evt => {
let msg = JSON.parse(evt.data);
if (msg) {
// console.log(msg);
draw('xy', {
...msg,
from: 'lidarLive',
})
}
}
//
dispatch(getVideo()).then(res => {
if (
res.success
) {
try {
setVideo(res.payload.data)
const container = document.getElementById('video-play');
console.log(`准备播放`, res.payload.data.ws_flv);
// 播放方式 1
const playJessibuca = () => {
const jessibuca = new window.Jessibuca({
container: container,
videoBuffer: 0.2, // 缓存时长
isResize: false,
text: "",
loadingText: "加载中",
debug: true,
showBandwidth: false, // 显示网速
showBandwidth: false,
operateBtns: {
fullscreen: false,
screenshot: false,
play: false,
audio: false,
fullscreen: true,
screenshot: true,
play: true,
audio: true,
},
forceNoOffscreen: false,
controlAutoHide: true,
isNotMute: false,
// useMSE:true,
// autoWasm:true
});
jessibucas.current = jessibuca
jessibuca.play(
// `http://flv.bdplay.nodemedia.cn/live/bbb.flv`
// `ws://localhost:8081/jessica/34020000001320000001/34020000001320000001.flv`
`${res.payload.data.ws_flv}`
);
}
playJessibuca()
jessibucasInterval = setInterval(() => {
jessibucas.current.destroy()
playJessibuca()
},
1000 * 60 * 30
// 1000 * 10
)
// 播放方式 2
// const flv = flvjs.createPlayer({
// type: 'flv',
// url: `${res.payload.data.ws_flv}`,
// isLive: true,
// hasAudio: false,
// hasVideo: true,
// }, {
// enableWorker: false,//分离线程
// enalleStashBuffer: false, //IO隐藏缓冲区
// stashInitialSize: 128,
// isLive: true,
// lazyLoad: false,
// // lazyLoadMaxDuration: 3 * 60,
// lazyLoadMaxDuration: 1,
// seekType: 'range',
// autoCleanupSourceBuffer: true,
// // cors: true,
// // stashInitialSize: 1024
// });
// flv.attachMediaElement(container);
// flv.load();
// try {
// // 初始化 _remuxer
// let controller = flv?._transmuxer?._controller
// controller._remuxer = {
// flushStashedSamples: function () {
// console.log("flushStashedSamples")
// }
// }
// } catch (error) {
// console.error(error);
// }
// flv.play();
// flvPlayer.current = flv
/** 尝试解决播放延迟问题 */
if (flvPlayerInterval) {
clearInterval(flvPlayerInterval)
}
// flvPlayerInterval = setInterval(() => {
// console.log(flv.buffered);
// if (flv.buffered.length) {
// let end = flv.buffered.end(0);//获取当前buffered值
// let diff = end - flv.currentTime;//获取buffered与currentTime的差值
// if (diff >= 3) {//如果差值大于等于0.5 手动跳帧 这里可根据自身需求来定
// console.log(222222222);
// flv.currentTime = flv.buffered.end(0);//手动跳帧
// }
// }
// }, 1000 * 10);
/** 尝试 END */
} catch (error) {
console.error(error);
} }
} }
})
return () => { return () => {
if (ws) { if (dataLiveWs) {
ws.close();//关闭连接 window.clearInterval(dataLiveWsInterval);
window.clearInterval(interval); dataLiveWs.close();//关闭连接
}
if (lidarLiveWs) {
window.clearInterval(lidarLiveWsInterval);
lidarLiveWs.close();//关闭连接
}
if (jessibucas.current) {
jessibucas.current.destroy()
}
if (jessibucasInterval.current) {
clearInterval(jessibucasInterval.current)
} }
} }
}, []) }, [])
@ -473,11 +733,16 @@ function Index (props) {
color: darkModde ? darkColor.textColor : 'auto', color: darkModde ? darkColor.textColor : 'auto',
background: darkModde ? darkColor.background : 'auto' background: darkModde ? darkColor.background : 'auto'
}}> }}>
<div style={{ padding: '0 8px 8px', textAlign: 'right' }}> <div style={{ padding: '0 8px 8px', }}>
<Space> <Space>
<Button type="primary" size={'large'} style={{}} icon={<VideoCameraOutlined />} onClick={() => { }}> <Button type="danger" size={'large'} style={{}} icon={<LogoutOutlined />} onClick={() => { setIsOutModalOpen(true) }}>
监控视频 退出
</Button> </Button>
</Space>
<Space style={{ float: 'right' }}>
{/* <Button type="primary" size={'large'} style={{}} icon={<VideoCameraOutlined />} onClick={() => { setVideoVis(true) }}>
监控视频
</Button> */}
<Button type="primary" size={'large'} style={{}} icon={<SettingOutlined />} onClick={() => setIsModalOpen(true)}> <Button type="primary" size={'large'} style={{}} icon={<SettingOutlined />} onClick={() => setIsModalOpen(true)}>
设置 设置
</Button> </Button>
@ -485,15 +750,37 @@ function Index (props) {
</div> </div>
<div style={{ height: 'calc(80% - 40px)', padding: 8 }}> <div style={{ height: 'calc(80% - 40px)', padding: 8 }}>
<Row style={{ height: '100%' }}> <Row style={{
<Col span={12} id="canvasArea" style={{ paddingRight: 8, maxHeight: '100%' }}> height: '100%',
}}>
<Col span={14} id="canvasArea" style={{ paddingRight: 8, maxHeight: '100%' }}>
<div className='card' style={cardStyle}> <div className='card' style={cardStyle}>
<canvas ref={xzCvs} id='xzCvs' height={120} width={120} style={{}}> <canvas ref={xzCvs} id='xzCvs' height={120} width={120} style={{ display: 'none' }}>
您的浏览器不支持canvas,请更换浏览器. 您的浏览器不支持canvas,请更换浏览器.
</canvas> </canvas>
{/* video 配合 flvjs 使用 */}
{/* <video
className='card'
id={'video-play'}
autoPlay
// muted
controls
style={{ height: '100%', width: '100%', }}
>
</video> */}
{/* 这个 div 配合 解析不卡使用 */}
<div
className='card'
id={'video-play'}
style={{ height: '100%', width: '100%', }}
>
</div>
</div> </div>
</Col> </Col>
<Col span={12} style={{ paddingLeft: 8, }}> <Col span={10} style={{ paddingLeft: 8, }}>
<div className='card' style={cardStyle}> <div className='card' style={cardStyle}>
<canvas ref={xyCvs} id='xyCvs' height={120} width={120} style={{}}> <canvas ref={xyCvs} id='xyCvs' height={120} width={120} style={{}}>
您的浏览器不支持canvas,请更换浏览器. 您的浏览器不支持canvas,请更换浏览器.
@ -501,34 +788,18 @@ function Index (props) {
</div> </div>
</Col> </Col>
</Row> </Row>
</div> </div>
<div style={{ height: '20%' }}> <div style={{ height: '20%' }}>
<Row style={{ height: '100%' }}> <Row style={{ height: '100%' }}>
{ {
[{ [{
k: '高度',
v: 'tower_height',
s: '-',
unit: 'm'
}, {
k: '幅度',
v: 'max_amp',
s: '-',
}, {
k: '回转角', k: '回转角',
v: 'rotation', v: 'rotation',
s: '-', s: '-',
unit: '°', unit: '°',
dataFrom: 'live', dataFrom: 'live',
}, {
k: '重量',
v: 'x',
s: '-',
}, {
k: '力矩',
v: 'max_torque',
s: '-',
unit: 'KN*m'
}, { }, {
k: '俯仰角', k: '俯仰角',
v: 'pitch', v: 'pitch',
@ -536,15 +807,35 @@ function Index (props) {
unit: '°', unit: '°',
dataFrom: 'live', dataFrom: 'live',
}, { }, {
k: '倾斜角', k: '碰撞距离',
v: 'inclination', v: 'lidar',
s: '-', s: '-',
unit: '°', unit: 'm',
dataFrom: 'live', dataFrom: 'live',
}, { }, {
k: '', // k: '高度',
v: '', // v: 'tower_height',
s: '', // s: '-',
// unit: 'm'
}, {
// k: '幅度',
// v: 'max_amp',
// s: '-',
}, {
// k: '重量',
// v: 'x',
// s: '-',
}, {
// k: '力矩',
// v: 'max_torque',
// s: '-',
// unit: 'KN*m'
}, {
// k: '倾斜角',
// v: 'inclination',
// s: '-',
// unit: '°',
// dataFrom: 'live',
},].map(s => { },].map(s => {
return ( return (
<Col span={3} style={{ <Col span={3} style={{
@ -552,7 +843,9 @@ function Index (props) {
background: background:
darkModde ? darkColor.background : 'auto' darkModde ? darkColor.background : 'auto'
}}> }}>
<div className="card" style={cardStyle}> <div className="card" style={Object.assign({}, cardStyle, {
boxShadow: `0 0 10px ${s.dataFrom === 'live' && craneParams[s.v]?.Warn ? Colors.pickColorWithAlarmLevel(craneParams[s.v]?.Warn) : darkModde ? darkColor.shadow : 'rgba(0, 0, 0, 0.2)'}`,
})}>
{ {
s.k ? s.k ?
<> <>
@ -563,7 +856,7 @@ function Index (props) {
{ {
s.dataFrom === 'live' ? s.dataFrom === 'live' ?
( (
craneParams[s.v]?.Value || '-' craneParams[s.v]?.Value || craneParams[s.v]?.Value == 0 ? craneParams[s.v]?.Value : '-'
) + ( ) + (
craneParams[s.v] && s.unit ? s.unit : '' craneParams[s.v] && s.unit ? s.unit : ''
) )
@ -576,7 +869,7 @@ function Index (props) {
} }
</p> </p>
<span className="status" style={{ <span className="status" style={{
backgroundColor: s.dataFrom === 'live' && craneParams[s.v]?.Warn ? Colors.getAlarmLevelColors(craneParams[s.v]?.Warn) : undefined backgroundColor: s.dataFrom === 'live' && craneParams[s.v]?.Warn ? Colors.pickColorWithAlarmLevel(craneParams[s.v]?.Warn) : undefined
}}> }}>
{ {
s.dataFrom === 'live' ? s.dataFrom === 'live' ?
@ -605,6 +898,20 @@ function Index (props) {
> >
<Input.Password size="large" placeholder="请输入密码" /> <Input.Password size="large" placeholder="请输入密码" />
</Modal> </Modal>
<Modal title="退出应用" open={isOutModalOpen}
onOk={() => {
dispatch(logoutApp());
}}
onCancel={() => {
setIsOutModalOpen(false)
}}
>
<span style={{ fontSize: 'large', fontWeight: 'bolder' }}>确定退出应用吗</span>
</Modal>
{
videoVis ?
<VideoModal onCancel={() => { setVideoVis(false) }} /> : ''
}
</div> </div>
) )
} }

115
console/client/src/sections/console/containers/setUp.js

@ -2,20 +2,22 @@ import React, { useEffect, useState, useRef } from 'react'
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import request from 'superagent'; import request from 'superagent';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { editCrane } from '../actions' import { editCrane, getCrane } from '../actions'
import { import {
BorderlessTableOutlined, BlockOutlined, RollbackOutlined, SaveOutlined BorderlessTableOutlined, BlockOutlined, RollbackOutlined, SaveOutlined, AimOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Col, Row, Button, Modal, Form, Input, InputNumber, message } from 'antd'; import { Col, Row, Button, Modal, Form, Input, InputNumber, message, Switch } from 'antd';
import '../style.less' import '../style.less'
function SetUp ({ dispatch }) { function SetUp ({ dispatch, craneData }) {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [renderMenu, setRenderMenu] = useState([]) const [renderMenu, setRenderMenu] = useState([])
const [renderForm, setRenderForm] = useState(false) const [renderForm, setRenderForm] = useState(false)
const [formItems, setFormItems] = useState([]) const [formItems, setFormItems] = useState([])
const [formIndex, setFormIndex] = useState(0) const [formIndex, setFormIndex] = useState(0)
const craneDataRef = useRef(craneData)
const [levelOneMenu] = useState([{ const [levelOneMenu] = useState([{
n: '参数标定', n: '参数标定',
ic: <BlockOutlined className='setup-icon' />, ic: <BlockOutlined className='setup-icon' />,
@ -24,7 +26,40 @@ function SetUp ({ dispatch }) {
} }
}, { }, {
n: '限位告警参数', n: '限位告警参数',
ic: <BorderlessTableOutlined className='setup-icon' /> ic: <BorderlessTableOutlined className='setup-icon' />,
click: () => {
setRenderForm(true)
setFormIndex(1)
setFormItems([
{
label: '设备编号',
name: 'device_no',
type: 'string',
disabled: true,
},
{
label: '1级碰撞距离',
name: 'dis_level_1',
type: 'number',
},
{
label: '3级碰撞距离',
name: 'dis_level_3',
type: 'number',
},
{
label: '是否静音',
name: 'mute',
type: 'boolean',
},
{
label: '2级碰撞距离',
name: 'dis_level_2',
type: 'number',
},
])
initData()
}
}, { }, {
n: '返回', n: '返回',
ic: <RollbackOutlined className='setup-icon' />, ic: <RollbackOutlined className='setup-icon' />,
@ -48,6 +83,7 @@ function SetUp ({ dispatch }) {
label: '设备编号', label: '设备编号',
name: 'device_no', name: 'device_no',
type: 'string', type: 'string',
disabled: true,
}, },
{ {
label: '经度', label: '经度',
@ -115,6 +151,38 @@ function SetUp ({ dispatch }) {
type: 'number', type: 'number',
}, },
]) ])
initData()
}
}, {
n: '传感器参数',
ic: <AimOutlined className='setup-icon' />,
click: () => {
setRenderForm(true)
setFormIndex(1)
setFormItems([
{
label: '设备编号',
name: 'device_no',
type: 'string',
disabled: true,
},
{
label: '测斜仪模块号',
name: 'hgc_module',
type: 'string',
},
{
label: '串口配置1',
name: 'serial_port',
type: 'string',
},
{
label: '串口配置2',
name: 'serial_port2',
type: 'string',
},
])
initData()
} }
}, { }, {
n: '返回', n: '返回',
@ -141,8 +209,21 @@ function SetUp ({ dispatch }) {
) )
} }
const initData = (craneData_) => {
setTimeout(() => {
form.setFieldsValue({
...(craneData_ || craneDataRef.current || craneData)
})
}, 300)
}
useEffect(() => {
craneDataRef.current = craneData
initData(craneData)
}, [craneData])
return ( return (
<div style={{ height: '100vh' }}> <div style={{ height: '100vh', background: '#000' }}>
{ {
!renderForm ? !renderForm ?
<div style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}> <div style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}>
@ -162,7 +243,7 @@ function SetUp ({ dispatch }) {
wrapperCol: { wrapperCol: {
span: 18, span: 18,
}, },
}} name="control-hooks" size='large'> }} name="control-hooks" size='large' style={{ display: 'flex', flexDirection: 'column', height: '95%', justifyContent: 'space-between', }}>
<Row style={{ padding: '8% 12% 0' }}> <Row style={{ padding: '8% 12% 0' }}>
{ {
(() => { (() => {
@ -180,11 +261,17 @@ function SetUp ({ dispatch }) {
// // required: true, // // required: true,
// // message: '请输入' + item.label // // message: '请输入' + item.label
// }]} // }]}
valuePropName={item.type == 'boolean' ? "checked" : undefined}
> >
{ {
item.type === 'number' ? item.type === 'number' ?
<InputNumber style={{ width: '100%' }} /> : <InputNumber style={{ width: '100%' }} disabled={item.disabled} />
<Input /> :
item.type == 'boolean' ?
<Switch checkedChildren="开启" unCheckedChildren="关闭" defaultChecked size={'large'} disabled={item.disabled} />
:
<Input disabled={item.disabled} />
} }
</Form.Item> </Form.Item>
@ -210,10 +297,11 @@ function SetUp ({ dispatch }) {
ic: <SaveOutlined className='setup-icon' />, ic: <SaveOutlined className='setup-icon' />,
click: () => { click: () => {
if (formIndex == 1) { if (formIndex == 1) {
const values = form.getFieldsValue() let values = form.getFieldsValue()
dispatch(editCrane(values)).then(res => { dispatch(editCrane({ ...craneData, ...values })).then(res => {
if (res.success) { if (res.success) {
message.success('修改配置信息成功') message.success('修改配置信息成功')
dispatch(getCrane())
} else { } else {
message.error('修改配置信息失败') message.error('修改配置信息失败')
} }
@ -238,15 +326,14 @@ function SetUp ({ dispatch }) {
<div> <div>
</div> </div>
</div> </div>
) )
} }
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth } = state; const { crane } = state;
return { return {
craneData: crane.data || {}
} }
} }

30
console/client/src/utils/hooks.js

@ -1,30 +0,0 @@
import React, { useEffect } from 'react';
import { useRequest } from 'ahooks';
import { Request } from '@peace/utils';
export const useFsRequest = ({ ...props }) => {
const {
method = 'get', header = null, body = {}, query = {}, root = null, url, ...rest
} = props;
return useRequest(() => {
if (method === 'post') {
return Request.post(url, body, query, root, header);
}
if (method === 'put') {
return Request.put(url, body, query, root, header);
}
if (method === 'delete') {
return Request.delete(url, query, root, header);
}
return Request.get(url, query, root, header);
}, {
loadingDelay: 500,
...rest,
});
};
export default {
useFsRequest,
};

2
console/client/src/utils/index.js

@ -2,11 +2,9 @@
import { AuthorizationCode } from './authCode'; import { AuthorizationCode } from './authCode';
import { ApiTable, RouteTable, } from './webapi' import { ApiTable, RouteTable, } from './webapi'
import Func from './func'; import Func from './func';
import { useFsRequest } from './hooks';
export { export {
AuthorizationCode, AuthorizationCode,
Func, Func,
ApiTable, RouteTable, ApiTable, RouteTable,
useFsRequest,
} }

3
console/client/src/utils/webapi.js

@ -10,6 +10,9 @@ export const ApiTable = {
dataLatest: 'v1/data/latest', dataLatest: 'v1/data/latest',
craneSetting: 'v1/settings', craneSetting: 'v1/settings',
dataLive: 'v1/data/live', dataLive: 'v1/data/live',
lidarLive: 'v1/lidar/live',
videoGet: 'v1/video/get',
logoutApp: 'v1/shutdown',
}; };
export const RouteTable = { export const RouteTable = {

594
console/log/development.txt

@ -77,3 +77,597 @@
2023-03-28 17:10:51.751 - info: [Router] Inject api: attachment/index 2023-03-28 17:10:51.751 - info: [Router] Inject api: attachment/index
2023-03-29 11:10:34.765 - debug: [FS-LOGGER] Init. 2023-03-29 11:10:34.765 - debug: [FS-LOGGER] Init.
2023-03-29 11:10:35.030 - info: [Router] Inject api: attachment/index 2023-03-29 11:10:35.030 - info: [Router] Inject api: attachment/index
2023-05-04 14:06:35.560 - debug: [FS-LOGGER] Init.
2023-05-04 14:06:35.613 - info: [Router] Inject api: attachment/index
2023-05-04 14:07:22.070 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/settings',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:07:22.078 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/video/get',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:07:58.835 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/settings',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:07:58.840 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/video/get',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:10:40.431 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/settings',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:10:40.437 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/video/get',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:56:24.316 - debug: [FS-LOGGER] Init.
2023-05-04 14:56:24.385 - info: [Router] Inject api: attachment/index
2023-05-04 14:56:59.130 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/settings',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 14:56:59.137 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/video/get',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 15:01:49.652 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/video/get',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}
2023-05-04 15:01:49.657 - error: [FS-ERRHD]
{
message: 'Error: connect ECONNREFUSED 10.8.30.183:4100',
name: 'RequestError',
cause: {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.8.30.183',
port: 4100
},
error: { '$ref': '$["cause"]' },
options: {
jar: false,
url: 'http://10.8.30.183:4100/v1/settings',
headers: {
host: '10.8.30.183:4100',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
expires: '-1',
'cache-control': 'no-cache,no-store,must-revalidate,max-age=-1,private',
'x-requested-with': 'XMLHttpRequest',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '*/*',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:5400/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'cookie-gray-released=old; cookie-gray-released.sig=yoy838I4CaX4fFTrAaY7VlBg7Ns'
},
encoding: null,
followRedirect: true,
method: 'GET',
body: '[object Object]',
simple: false,
resolveWithFullResponse: true,
callback: [Function: RP$callback],
transform: undefined,
transform2xxOnly: false
},
response: undefined,
stack: 'RequestError: Error: connect ECONNREFUSED 10.8.30.183:4100\n' +
' at new RequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\errors.js:14:15)\n' +
' at Request.plumbing.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:87:29)\n' +
' at Request.RP$callback [as _callback] (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request-promise-core\\lib\\plumbing.js:46:31)\n' +
' at self.callback (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:185:22)\n' +
' at Request.emit (events.js:314:20)\n' +
' at Request.onRequestError (C:\\_WorkCode\\CraneAntiCollision\\console\\node_modules\\request\\request.js:877:8)\n' +
' at ClientRequest.emit (events.js:314:20)\n' +
' at Socket.socketErrorListener (_http_client.js:427:9)\n' +
' at Socket.emit (events.js:314:20)\n' +
' at emitErrorNT (internal/streams/destroy.js:92:8)\n' +
' at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:84:21)'
}

46
console/main.js

@ -1,27 +1,27 @@
const { app, BrowserWindow, Menu } = require('electron') // const { app, BrowserWindow, Menu } = require('electron')
try { // try {
require('electron-reloader')(module, {}); // require('electron-reloader')(module, {});
} catch (_) { } // } catch (_) { }
const createWindow = () => { // const createWindow = () => {
const win = new BrowserWindow({ // const win = new BrowserWindow({
width: 1366, // width: 1366,
height: 768, // height: 768,
webPreferences: { // webPreferences: {
// preload, // // preload,
nodeIntegration: true, // nodeIntegration: true,
contextIsolation: false, // contextIsolation: false,
}, // },
}) // })
Menu.setApplicationMenu(null); // Menu.setApplicationMenu(null);
console.log(process.env, process.env.NODE_ENV); // console.log(process.env, process.env.NODE_ENV);
win.loadURL('http://localhost:5400') // win.loadURL('http://localhost:5400')
// win.loadFile('./client/index.html') // // win.loadFile('./client/index.html')
win.webContents.openDevTools() // win.webContents.openDevTools()
} // }
app.whenReady().then(() => { // app.whenReady().then(() => {
createWindow() // createWindow()
}) // })

12325
console/package-lock.json

File diff suppressed because it is too large

20
console/package.json

@ -8,7 +8,7 @@
"test": "mocha", "test": "mocha",
"start-elctr-forge": "electron-forge start", "start-elctr-forge": "electron-forge start",
"start": "cross-env NODE_ENV=development npm run start-params", "start": "cross-env NODE_ENV=development npm run start-params",
"start-params": "node server -p 5400 -u http://10.8.30.183:4100", "start-params": "node server -p 5400 -u http://127.0.0.1:4100",
"deploy": "export NODE_ENV=production && npm run build && node server", "deploy": "export NODE_ENV=production && npm run build && node server",
"build-dev": "set NODE_ENV=development&&webpack --config webpack.config.js", "build-dev": "set NODE_ENV=development&&webpack --config webpack.config.js",
"build": "set NODE_ENV=production&&webpack --config webpack.config.prod.js", "build": "set NODE_ENV=production&&webpack --config webpack.config.prod.js",
@ -28,18 +28,11 @@
"@babel/polyfill": "^7.12.1", "@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.14.7", "@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.14.5", "@babel/preset-react": "^7.14.5",
"@electron-forge/cli": "^6.0.5",
"@electron-forge/maker-deb": "^6.0.5",
"@electron-forge/maker-rpm": "^6.0.5",
"@electron-forge/maker-squirrel": "^6.0.5",
"@electron-forge/maker-zip": "^6.0.5",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"babel-plugin-import": "^1.13.3", "babel-plugin-import": "^1.13.3",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"connected-react-router": "^6.8.0", "connected-react-router": "^6.8.0",
"css-loader": "^3.5.0", "css-loader": "^3.5.0",
"electron": "^23.1.3",
"electron-reloader": "^1.2.3",
"express": "^4.17.1", "express": "^4.17.1",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"html-webpack-plugin": "^4.5.0", "html-webpack-plugin": "^4.5.0",
@ -73,22 +66,13 @@
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^4.6.2", "@ant-design/icons": "^4.6.2",
"@ant-design/pro-form": "^1.34.0",
"@ant-design/pro-table": "^2.48.0",
"@antv/g6": "^4.2.5",
"@fs/attachment": "^1.0.0",
"@peace/components": "0.0.35",
"@peace/utils": "0.0.37", "@peace/utils": "0.0.37",
"ahooks": "^3.7.4",
"ali-oss": "^6.17.1",
"antd": "^4.24.5", "antd": "^4.24.5",
"args": "^5.0.1", "args": "^5.0.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"echarts": "^5.4.1",
"echarts-for-react": "^3.0.2",
"electron-squirrel-startup": "^1.0.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"flv.js": "^1.6.2",
"fs-attachment": "^1.0.0", "fs-attachment": "^1.0.0",
"fs-web-server-scaffold": "^1.0.6", "fs-web-server-scaffold": "^1.0.6",
"koa-better-http-proxy": "^0.2.5", "koa-better-http-proxy": "^0.2.5",

159
console/routes/attachment/index.js

@ -1,10 +1,8 @@
'use strict'; 'use strict';
const request = require('superagent'); const request = require('superagent');
const parse = require('async-busboy'); // const parse = require('async-busboy');
const path = require('path') const path = require('path')
const fs = require('fs'); const fs = require('fs');
const OSS = require('ali-oss');
const uuid = require('uuid');
const UploadPath = { const UploadPath = {
project: ['.txt', '.dwg', '.doc', '.docx', '.xls', '.xlsx', ".csv", '.pdf', '.pptx', '.png', '.jpg', '.svg', '.rar', '.zip', '.jpeg', '.mp4'], project: ['.txt', '.dwg', '.doc', '.docx', '.xls', '.xlsx', ".csv", '.pdf', '.pptx', '.png', '.jpg', '.svg', '.rar', '.zip', '.jpeg', '.mp4'],
@ -78,33 +76,33 @@ module.exports = {
let upload = async function (ctx, next) { let upload = async function (ctx, next) {
try { try {
const { files } = await parse(ctx.req); // const { files } = await parse(ctx.req);
const file = files[0]; // const file = files[0];
const extname = path.extname(file.filename).toLowerCase(); // const extname = path.extname(file.filename).toLowerCase();
const fileType = ctx.query.type || "image"; // const fileType = ctx.query.type || "image";
const fileFolder = ctx.query.fileFolder || 'common'; // const fileFolder = ctx.query.fileFolder || 'common';
if (ext[fileType].indexOf(extname) < 0) { // if (ext[fileType].indexOf(extname) < 0) {
ctx.status = 400; // ctx.status = 400;
ctx.body = JSON.stringify({ name: 'UploadFailed', message: '文件格式无效' }); // ctx.body = JSON.stringify({ name: 'UploadFailed', message: '文件格式无效' });
return; // return;
} // }
const date = new Date().toLocaleDateString(); // const date = new Date().toLocaleDateString();
const time = new Date().getTime(); // const time = new Date().getTime();
let fileName = time + '_' + file.filename; // let fileName = time + '_' + file.filename;
let saveFile = path.join(__dirname, '../../', `/client/assets/files/${fileFolder}`, fileName); // let saveFile = path.join(__dirname, '../../', `/client/assets/files/${fileFolder}`, fileName);
const pathUrl = `./client/assets/files/${fileFolder}`; // const pathUrl = `./client/assets/files/${fileFolder}`;
const res1 = fs.existsSync(`./client/assets/files/${fileFolder}`); // const res1 = fs.existsSync(`./client/assets/files/${fileFolder}`);
!res1 && fs.mkdirSync(`./client/assets/files/${fileFolder}`); // !res1 && fs.mkdirSync(`./client/assets/files/${fileFolder}`);
const res = fs.existsSync(pathUrl); // const res = fs.existsSync(pathUrl);
!res && fs.mkdirSync(pathUrl); // !res && fs.mkdirSync(pathUrl);
let stream = fs.createWriteStream(saveFile); // let stream = fs.createWriteStream(saveFile);
fs.createReadStream(file.path).pipe(stream); // fs.createReadStream(file.path).pipe(stream);
stream.on('error', function (err) { // stream.on('error', function (err) {
app.fs.logger.log('error', '[Upload Heatmap]', err); // app.fs.logger.log('error', '[Upload Heatmap]', err);
}); // });
ctx.status = 200; // ctx.status = 200;
ctx.body = { filename: path.join(`/assets/files/${fileFolder}`, fileName), name: 'UploadSuccess', message: '上传成功' }; // ctx.body = { filename: path.join(`/assets/files/${fileFolder}`, fileName), name: 'UploadSuccess', message: '上传成功' };
} catch (err) { } catch (err) {
ctx.status = 500; ctx.status = 500;
ctx.fs.logger.error(err); ctx.fs.logger.error(err);
@ -138,23 +136,23 @@ module.exports = {
let upload_ = async function (ctx, next) { let upload_ = async function (ctx, next) {
let fkey = null; let fkey = null;
try { try {
const { p } = ctx.params; // const { p } = ctx.params;
const { files } = await parse(ctx.req); // const { files } = await parse(ctx.req);
const file = files[0]; // const file = files[0];
const extname = path.extname(file.filename).toLowerCase(); // const extname = path.extname(file.filename).toLowerCase();
if (!UploadPath[p]) { // if (!UploadPath[p]) {
ctx.status = 400; // ctx.status = 400;
ctx.body = JSON.stringify({ error: '附件存放的文件夹名称无效' }); // ctx.body = JSON.stringify({ error: '附件存放的文件夹名称无效' });
return; // return;
} else if (UploadPath[p].indexOf(extname) < 0) { // } else if (UploadPath[p].indexOf(extname) < 0) {
ctx.status = 400; // ctx.status = 400;
ctx.body = JSON.stringify({ error: '文件格式无效' }); // ctx.body = JSON.stringify({ error: '文件格式无效' });
return; // return;
} else { // } else {
const fileInfo = await ctx.app.fs.attachment.upload(file, { uploadPath: p }); // const fileInfo = await ctx.app.fs.attachment.upload(file, { uploadPath: p });
fkey = fileInfo.key; // fkey = fileInfo.key;
ctx.body = { uploaded: fkey }; // ctx.body = { uploaded: fkey };
} // }
} catch (err) { } catch (err) {
ctx.status = 500; ctx.status = 500;
ctx.fs.logger.error(err); ctx.fs.logger.error(err);
@ -162,78 +160,9 @@ module.exports = {
} }
} }
const uploadAliOSS = async (ctx,) => {
// 这个是上传到阿里
try {
const { aliOss } = opts
const { p = 'default' } = ctx.params;
const { files } = await parse(ctx.req);
const file = files[0];
const filename = file.filename || path.basename(file);
const client = new OSS({
// yourRegion填写Bucket所在地域.以华东1(杭州)为例,Region填写为oss-cn-hangzhou.
region: aliOss.region,
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高.强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户.
accessKeyId: aliOss.accessKey,
accessKeySecret: aliOss.secretKey,
// 填写Bucket名称,例如examplebucket.
bucket: aliOss.bucket,
});
let uploadPath = path.posix.join(p, uuid.v4(), filename);
let result = await client.putStream(
uploadPath,
file,
// { contentLength: size }
);
ctx.status = 200;
ctx.body = {
key: result.name,
uploaded: result.name,
url: result.url,
};
} catch (error) {
ctx.status = 400;
ctx.fs.logger.error(error);
ctx.body = { err: 'upload error.' };
}
}
const downloadFromAli = async (ctx) => {
try {
const { aliOss } = opts
const { path, filename } = ctx.query
const client = new OSS({
// yourRegion填写Bucket所在地域.以华东1(杭州)为例,Region填写为oss-cn-hangzhou.
region: aliOss.region,
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高.强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户.
accessKeyId: aliOss.accessKey,
accessKeySecret: aliOss.secretKey,
// 填写Bucket名称,例如examplebucket.
bucket: aliOss.bucket,
});
const filename_ = filename || path.split('/').pop()
const result = await client.get(path);
ctx.status = 200;
ctx.set('Content-Type', 'application/x-xls');
ctx.set('Content-disposition', 'attachment; filename=' + filename_);
ctx.body = result.content;
} catch (error) {
ctx.status = 400;
ctx.fs.logger.error(error);
ctx.body = { err: 'download error.' };
}
}
router.use(download_); router.use(download_);
router.post('/_upload/new', upload); router.post('/_upload/new', upload);
router.delete('/_upload/cleanup', remove); router.delete('/_upload/cleanup', remove);
router.post('/_upload/attachments/ali/:p', uploadAliOSS);
router.get('/_download/attachments/ali', downloadFromAli);
router.post('/_upload/attachments/:p', upload_); router.post('/_upload/attachments/:p', upload_);
} }
}; };

Loading…
Cancel
Save