Compare commits

...

274 Commits

Author SHA1 Message Date
wenlele 1453d187c4 播放修改 2 years ago
巴林闲侠 ce3e1c932d 萤石设备播放地址更新查询用时 2 years ago
巴林闲侠 df40d3d9df redis.Cluster 2 years ago
巴林闲侠 4e192fe454 redis pswd 2 years ago
巴林闲侠 a9ced94fc7 播放器 params.videoObj 2 years ago
巴林闲侠 a31d4c04d3 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 f0760bd0e5 https->http 2 years ago
deartibers d588ac9661 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
deartibers 56e277b099 备注视频样式修改 2 years ago
巴林闲侠 13524a5cf1 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 04663f3cbf /camera 暂时不鉴权 2 years ago
deartibers 405c723228 备注按id排序 2 years ago
巴林闲侠 1ae93b7676 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 ffc064fcb0 备注排序x 2 years ago
deartibers bb385d7536 默认信息 2 years ago
巴林闲侠 55928225d5 camera_remark 2 years ago
巴林闲侠 d372ce14fc Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 c079740238 视频备注 100% 2 years ago
wenlele e6c365494d Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 766935ed75 表格添加备注功能 2 years ago
deartibers c15990cd60 备注修改 2 years ago
deartibers 761c829c0e 备注滚动 2 years ago
巴林闲侠 a9ce108e9d CameraRemark 排序 2 years ago
wenlele 29244b7288 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele cb6d752abc 测试 2 years ago
deartibers c38fb8cbf9 备注功能 2 years ago
巴林闲侠 f05ade2b91 获取流 同时获取备注 2 years ago
巴林闲侠 bfdf962443 定时任务 2 years ago
巴林闲侠 f0a380d64d 1.1.0 2 years ago
deartibers 36052b634c Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
deartibers d067752179 文件包和备注 2 years ago
wenlele 06fc355304 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 0c08d9e55d 置灰修改完成 2 years ago
巴林闲侠 c8a00261a0 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 9131be6873 定时任务即刻启用 2 years ago
wenlele 17de5056e4 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 37b84265a1 播放完成 2 years ago
巴林闲侠 ed1423141f Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 ccaa56c1ea yingshi talk 2 years ago
deartibers c9bd721035 nvr全选显示时间 2 years ago
巴林闲侠 9d2420130b Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 e3a6dc6e85 jessibuca.destroy() 2 years ago
wenlele 8cb1cfcf8b NVR添加名称格式修改 2 years ago
巴林闲侠 8e74408c87 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 efdde52111 GB视频播放 2 years ago
deartibers c6b6345116 nav图标 2 years ago
巴林闲侠 f72a28c30b mqtt 视频状态推送 2 years ago
巴林闲侠 707f8437fe 定时更新时间 2 years ago
巴林闲侠 f6a7c66c68 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 b6a763e3c8 安心云摄像头查询信息增加 2 years ago
wenlele feb1824eed 播放完成 2 years ago
deartibers 623fae136e 解决合并冲突 2 years ago
deartibers 73ee59529f 主题 2 years ago
巴林闲侠 30ccd213a7 视频播放cross 2 years ago
巴林闲侠 13a97ea076 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 b0d21b367c 萤石播放器 99.9% 2 years ago
wenlele 885c69d4d6 查询信息修改完毕 2 years ago
deartibers 97d8d0337e Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
deartibers 769ff49451 主题设置 2 years ago
巴林闲侠 09f72f5c9d 萤石播放器 89.9% 2 years ago
巴林闲侠 faf23bb4f6 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 6c646018a6 萤石播放器 88.8% 2 years ago
deartibers bccf70dec1 上下线推送 2 years ago
wenlele 96e04ea0db 测试置灰完成 2 years ago
wenlele ab2e4dc81a nvr摄像头视频流bug解决 2 years ago
巴林闲侠 09af37576b Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 32ded7ec5a 萤石状态更新逻辑 2 years ago
wenlele 3d1242fa31 级联视频流功能完成 2 years ago
巴林闲侠 1bbcd0c6a5 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 517929e1ce 播放地址拼接 2 years ago
wenlele a6c4ac075f Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele d255cb4ef6 级联视频流 80% 2 years ago
巴林闲侠 39fa23c823 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 263c79d246 萤石状态获取 2 years ago
巴林闲侠 ee1dee9f84 萤石状态获取 2 years ago
wenlele 7ed76c4208 搜索修改 2 years ago
wenlele 8d29279fd9 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele bb9974c8b2 查询复制地址完成 2 years ago
巴林闲侠 4a3946d4cc 萤石状态推送 2 years ago
巴林闲侠 756231efa7 fix websocket 信息推送 2 years ago
巴林闲侠 eb9789e6c0 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 1b16c8a05b makeDir 2 years ago
wenlele 35ab0b2fa6 完善导出 2 years ago
巴林闲侠 e9e4b42060 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 b3caa8a43a 级联添加接口 2 years ago
wenlele 26aa1c6ae8 头部敬语和摄像头页面设备状态查询添加 2 years ago
巴林闲侠 a7d98ddcfc dockerfile 2 years ago
巴林闲侠 8deb57ba1f Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 fa513c5e8e 萤石状态广播测试 2 years ago
wenlele 5a0da83039 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele f69525056b socket 2 years ago
巴林闲侠 57e99c139a Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 7279365a62 iourl = root 2 years ago
wenlele e8d0d7c2d7 登录页添加背景文字 2 years ago
巴林闲侠 1f3dc736fb Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 cfc281eddc yingshi state 2 years ago
wenlele d171c80b5a 添加新的模块 2 years ago
巴林闲侠 28756bee04 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 eb5bbc2758 萤石状态查询 2 years ago
wenlele 03fc11ead2 NVR添加成功后弹框跳转和不再提醒功能(根据用户判断是否提醒) 100% 2 years ago
巴林闲侠 de5d8f4283 videoOperationHistroyTime 2 years ago
巴林闲侠 06f310034e Merge branches 'dev_trial' and 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 7826cbc581 videoOperationTime 2 years ago
wenlele af10506c47 从安心云四个摄像头的添加跳转到视频平台对应的摄像头添加 2 years ago
巴林闲侠 b288d2156e 参数提示 2 years ago
巴林闲侠 b712b36be8 debug 2 years ago
巴林闲侠 7db8194212 参数提示 2 years ago
巴林闲侠 a421a1671e docker 2 years ago
巴林闲侠 5ad052f205 docker 2 years ago
巴林闲侠 6553443e41 引用错误 2 years ago
巴林闲侠 ee23345513 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 89749c7dc2 定时任务 2 years ago
wenlele d1dbeeccae 删掉一个不用的按钮 2 years ago
wenlele 26a9ff2b1f 冲突解决 2 years ago
wenlele 45761dd89b 解决冲突 2 years ago
wenlele 9958510f5c 从安心云四个摄像头的添加跳转到视频平台对应的摄像头添加 50% 2 years ago
巴林闲侠 4d6398b7e5 dockerfile 2 years ago
巴林闲侠 25902d6f22 jenkinsfile 2 years ago
巴林闲侠 e1dd11c50e sql脚本 2 years ago
巴林闲侠 aff86a6820 jenkinsfile 2 years ago
巴林闲侠 54d4227b59 登录背景mp4 2 years ago
巴林闲侠 65f427a12d sql脚本 2 years ago
巴林闲侠 1cd95e5ad3 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 0debdb7c1d docker 文件 ,部分播放器样式 2 years ago
wenlele 3430ecb5e2 萤石,级联,ipc添加修改时通过接口测试的功能完成 2 years ago
wenlele 2d9f850a9f NVR跳转传参功能完成,NVR摄像头获取视频流时交互样式 2 years ago
巴林闲侠 0594201af5 播放器样式 100% 2 years ago
wenlele 4cb212cbcf 级联摄像头的修改,表格项目信息 2 years ago
巴林闲侠 acc1f98e13 video play UI 88% 2 years ago
巴林闲侠 c0ec917f01 语音样式 2 years ago
巴林闲侠 5cc1e758ef Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 e3d08b97f0 云控样式 2 years ago
wenlele ab8b7bc8d1 级联摄像头修改50% 2 years ago
wenlele 6369ae4c5e Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 53515f4a3d 表格设备名称的条件搜索 2 years ago
巴林闲侠 a15fb7be51 登出、配置 2 years ago
巴林闲侠 b86cbbd98e Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 2c64beb088 跳转 100% 2 years ago
wenlele fa9cabdef0 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 68a7d60fa0 解决冲突 2 years ago
巴林闲侠 3b23a41e80 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 93b4754159 setAuthCrossLoading(false) 2 years ago
wenlele 0a210e2729 解决冲突 2 years ago
wenlele 4b87887396 添加级联摄像头 2 years ago
wenlele ec2b6fd849 添加级联摄像头 2 years ago
巴林闲侠 f0842505d1 暂时的ip配置 2 years ago
yuan_yi b75fee46ea 视频播放组件 40% 2 years ago
yuan_yi 0956159fc8 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 12815a3cee mqtt 引入 40% 2 years ago
wenlele f468021def NVR添加修改的测试校验功能完成 2 years ago
yuan_yi dfcac5c2fb setAuthCrossLoading(false) 2 years ago
yuan_yi c8e54329a7 摄像头验证接口 2 years ago
yuan_yi d9739eed96 摄像头验证接口 2 years ago
yuan_yi 720f3e29ef setAuthCrossLoading(false) 2 years ago
yuan_yi a0e55f01e7 http://10.8.30.82 2 years ago
yuan_yi 51c2f84976 ifream visibility: 'hidden' 2 years ago
wenlele 7dea13915d 添加NVR摄像头,解决NVR页面部分自测问题 2 years ago
wenlele 8fd9b56cc7 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
wenlele b31d5a8c1d 添加NVR摄像头,解决NVR页面部分自测问题 2 years ago
yuan_yi 63e8968c10 AUTH CROSS 2 years ago
yuan_yi f8e5e30e57 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 538fb4630a import react 2 years ago
wenlele 205f8f177e 萤石云摄像头和IPC摄像头的添加,摄像头删除 2 years ago
yuan_yi 4794d63ffe 监控中心 2 years ago
yuan_yi f7bd48bfaa 监控中心页 2 years ago
yuan_yi ce47dbadcf 完善sider选择逻辑 2 years ago
yuan_yi 77efe48d7c 回收站建设页 2 years ago
yuan_yi 377503cbcb 导出实操 2 years ago
yuan_yi 33e9e9b42a 导出实操 2 years ago
yuan_yi 9d1096583e ipc 摄像头添加 2 years ago
yuan_yi cffc4e95be 摄像头信息导出 2 years ago
yuan_yi 44606dfd4c nvr 信息导出 2 years ago
yuan_yi 8c5407347d xlsx简单文件通用下载 2 years ago
wenlele 345a2014db 解决冲突 2 years ago
yuan_yi 8589ead102 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 6dbcca3fa9 导出通用接口 30% 2 years ago
yuan_yi e175e6ade5 导出通用接口 30% 2 years ago
wenlele 1fd486536b 解决了表格数据展现的BUG 2 years ago
yuan_yi b009f18bc2 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 24c1294aad 安心云数据查询bug 2 years ago
wenlele e632b74387 数据修改 2 years ago
wenlele 6efe633899 添加骨架屏 2 years ago
deartibers 5a86abc520 摄像头添加 2 years ago
yuan_yi 8a9b814ea6 nvr table 2 years ago
wenlele 28e2133a7c Merge branch 'dev_trial' of ssh://gitea.free-sun.vip:2022/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 3f3d357f1e 解决报错问题 2 years ago
yuan_yi efab54dbdc Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 5919ec2850 摄像头萤石 2 years ago
wenlele 5c5334ff72 摄像头分页 2 years ago
wenlele cf93351a5a 表格查看和其它功能的数据对接 2 years ago
yuan_yi 5750c3872e 萤石摄像头添加 2 years ago
yuan_yi 96954a8a6e "babel-polyfill": "^6.26.0", 2 years ago
yuan_yi f638047ae7 webpack 2 years ago
yuan_yi 7801359f73 统一提示 2 years ago
yuan_yi fff6d76346 数据接口 2 years ago
yuan_yi a033e13a2e 设备筛选 2 years ago
yuan_yi ddc013104d 高德服务 2 years ago
yuan_yi c61d69a720 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 79d4f26ec1 摄像头若干接口 2 years ago
deartibers a1c20552b1 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
deartibers 38f9bf91da 设备厂家必填 2 years ago
wenlele 70080015d7 表格设置和查询的修改 2 years ago
yuan_yi 64fa1bc28c AXY_API_URL 2 years ago
yuan_yi 1efb405f19 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 974455267e 多平台请求抽象化 2 years ago
deartibers 20daa99a47 添加摄像头弹框 2 years ago
yuan_yi 54737dba51 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yuan_yi 9dc3554c7d 摄像头获取接口 2 years ago
wenlele 99b8aca186 查询功能样式完成 3 years ago
wenlele dc0136a212 设备信息和头部样式 3 years ago
wenlele 70d75b164a 列表的设置选择问题 3 years ago
wenlele 1d6877ce2d Merge branch 'dev_trial' of ssh://gitea.free-sun.vip:2022/free-sun/FS-IOT into dev_trial 3 years ago
wenlele 068ccda661 摄像头列表设置完成 3 years ago
deartibers 47a80141b0 修改less文件位置 3 years ago
deartibers b4f2dc62e3 首页样式修改 3 years ago
yuan_yi 224bc45174 socket 优化 3 years ago
yuan_yi 9e8de3ff47 socket 优化 3 years ago
yuan_yi caa85094bd socket 优化 3 years ago
yuan_yi d1be1ce22d Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
yuan_yi 0c1b8f8d99 websocket 3 years ago
deartibers 25c88dea6b nvr新增刷新列表 3 years ago
wenlele f1f3a17be3 解决冲突 3 years ago
wenlele 870afbcd47 解决冲突 3 years ago
deartibers ee8881a661 修改nvr 3 years ago
wenlele b9ac39955c 表格功能完成 3 years ago
wenlele c23c764238 表格功能完成 3 years ago
deartibers 981dc894c4 nvr接口调试以及摄像头页面 3 years ago
yuan_yi 37779c29b9 注释以运行 3 years ago
yuan_yi 255466ef39 api -u 3 years ago
yuan_yi 12be6e0ba6 redis精简 3 years ago
yuan_yi 29de0083a4 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
yuan_yi 685f65affd 获取nvr的接口 3 years ago
wenlele 2bee6dc9a3 Merge branch 'dev_trial' of ssh://gitea.free-sun.vip:2022/free-sun/FS-IOT into dev_trial 3 years ago
wenlele 7113aaf672 表格设置完成 3 years ago
deartibers a45a0a9a50 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
deartibers c3a82d8979 添加摄像头页面 3 years ago
yuan_yi 4168be60d7 删除 AUTH 3 years ago
yuan_yi 8c4cffa8b5 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
yuan_yi 068c0a6e50 NVR 增删接口 3 years ago
deartibers bdbd43ef73 删除px 3 years ago
deartibers b1d1b4bfb5 nvr弹出框交互 3 years ago
wenlele 525d99c736 BUG修改 3 years ago
yuan_yi 90b6c11a3f auth 参数配置 3 years ago
yuan_yi 6f23175395 namePresent 3 years ago
yuan_yi 3e898f7a3e 登录登出 3 years ago
yuan_yi 85b64e95c4 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
yuan_yi d18dfa9c30 登录登出 3 years ago
deartibers 27594bada8 弹框修改 3 years ago
wenlele 5744fe52b8 表格修改 3 years ago
wenlele 6c712920c8 Merge branch 'dev_trial' of ssh://gitea.free-sun.vip:2022/free-sun/FS-IOT into dev_trial 3 years ago
wenlele b6ed892275 冲突更改 3 years ago
deartibers 1aad3c3bef 修改问题 3 years ago
wenlele 3f5742570b 表格 3 years ago
deartibers 00610e8c2a Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
deartibers 1ebc1f15ae 添加nvr弹框 3 years ago
yuan_yi f1c3748571 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
yuan_yi c494dce09e recycle_banner.mp4 3 years ago
deartibers 72f2e341b4 nvr管理头部弹框 3 years ago
yuan_yi 07f13a617f video banner 3 years ago
yuan_yi d192b64407 camera_banner 3 years ago
yuan_yi 333330d9c3 nvr banner 3 years ago
yuan_yi b122c1e11c Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
yuan_yi 06648ff786 DB模型 3 years ago
deartibers 33b42ed889 banner视频 3 years ago
wenlele a8f7b63cac 格式 3 years ago
wenlele 29a904dce8 冲突解决 3 years ago
wenlele 911e502bf4 Merge 3 years ago
wenlele 6e92a71354 测试 3 years ago
deartibers 67c41bd4d9 nvr头部 3 years ago
deartibers 15420f0c96 Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 3 years ago
deartibers 26390a2a81 创建设备仓库文件 3 years ago
yuan_yi 40a022484b bg-img 3 years ago
yuan_yi 05e60fb524 fix utils 3 years ago
yuan_yi 052d73e231 fix utils 3 years ago
  1. 1
      .gitignore
  2. 89
      code/VideoAccess-VCMP/api/.vscode/launch.json
  3. 19
      code/VideoAccess-VCMP/api/Dockerfile
  4. 189
      code/VideoAccess-VCMP/api/app/lib/controllers/auth/index.js
  5. 571
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js
  6. 565
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js
  7. 463
      code/VideoAccess-VCMP/api/app/lib/controllers/nvr/index.js
  8. 23
      code/VideoAccess-VCMP/api/app/lib/controllers/vender/index.js
  9. 70
      code/VideoAccess-VCMP/api/app/lib/index.js
  10. 2
      code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js
  11. 26
      code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js
  12. 50
      code/VideoAccess-VCMP/api/app/lib/middlewares/business-rest.js
  13. 40
      code/VideoAccess-VCMP/api/app/lib/models/ax_project.js
  14. 284
      code/VideoAccess-VCMP/api/app/lib/models/camera.js
  15. 34
      code/VideoAccess-VCMP/api/app/lib/models/camera_ability.js
  16. 56
      code/VideoAccess-VCMP/api/app/lib/models/camera_ability_bind.js
  17. 34
      code/VideoAccess-VCMP/api/app/lib/models/camera_kind.js
  18. 52
      code/VideoAccess-VCMP/api/app/lib/models/camera_remark.js
  19. 169
      code/VideoAccess-VCMP/api/app/lib/models/gb_camera.js
  20. 128
      code/VideoAccess-VCMP/api/app/lib/models/nvr.js
  21. 67
      code/VideoAccess-VCMP/api/app/lib/models/secret_yingshi.js
  22. 108
      code/VideoAccess-VCMP/api/app/lib/models/user.js
  23. 44
      code/VideoAccess-VCMP/api/app/lib/models/vender.js
  24. 32
      code/VideoAccess-VCMP/api/app/lib/routes/auth/index.js
  25. 76
      code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js
  26. 18
      code/VideoAccess-VCMP/api/app/lib/routes/index.js
  27. 23
      code/VideoAccess-VCMP/api/app/lib/routes/nvr/index.js
  28. 8
      code/VideoAccess-VCMP/api/app/lib/routes/vender/index.js
  29. 151
      code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js
  30. 33
      code/VideoAccess-VCMP/api/app/lib/schedule/index.js
  31. 40
      code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js
  32. 67
      code/VideoAccess-VCMP/api/app/lib/service/paasRequest.js
  33. 41
      code/VideoAccess-VCMP/api/app/lib/service/redis.js
  34. 33
      code/VideoAccess-VCMP/api/app/lib/service/socket.js
  35. 171
      code/VideoAccess-VCMP/api/app/lib/utils/camera.js
  36. 16
      code/VideoAccess-VCMP/api/app/lib/utils/index.js
  37. 154
      code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js
  38. 82
      code/VideoAccess-VCMP/api/app/lib/utils/xlsxDownload.js
  39. 228
      code/VideoAccess-VCMP/api/config.js
  40. 7
      code/VideoAccess-VCMP/api/package.json
  41. 66
      code/VideoAccess-VCMP/api/sequelize-automate.config.js
  42. 15
      code/VideoAccess-VCMP/api/utils/forward-api.js
  43. 543
      code/VideoAccess-VCMP/script/0.0.1/0_init_db.sql
  44. 14
      code/VideoAccess-VCMP/script/1.1.0/1.camera_remark.sql
  45. 5
      code/VideoAccess-VCMP/web/.vscode/extensions.json
  46. 20
      code/VideoAccess-VCMP/web/Dockerfile
  47. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/Reset.png
  48. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/backGround.png
  49. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/blue.png
  50. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/building.png
  51. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/camera.png
  52. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/cascade.png
  53. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/copy1.png
  54. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/copy2.png
  55. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/formchoose.png
  56. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/green.png
  57. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/grey.png
  58. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/header.png
  59. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/ipc.png
  60. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/location.png
  61. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/loginBackground.gif
  62. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/loginbg.png
  63. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/logo.png
  64. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/notice.png
  65. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/nvr.png
  66. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/nvr_banner.png
  67. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/password.png
  68. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon0.png
  69. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon1.png
  70. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon2.png
  71. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon3.png
  72. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/red.png
  73. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/setup.png
  74. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera1.png
  75. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera2.png
  76. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/store1.png
  77. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/store2.png
  78. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/straightline.png
  79. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/talk.png
  80. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/talking.png
  81. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/test.png
  82. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/topchoose.png
  83. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/up.png
  84. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/user_login.png
  85. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/username.png
  86. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-control-select.png
  87. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-control-unselect.png
  88. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-fullScreen-select.png
  89. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-fullScreen-unselect.png
  90. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-histroy-select.png
  91. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-histroy-unselect.png
  92. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-talk-select.png
  93. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/video-icon-talk-unselect.png
  94. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/videoPlayBg.png
  95. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/warning.png
  96. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/ysy.png
  97. BIN
      code/VideoAccess-VCMP/web/client/assets/images/logo/figure.png
  98. 1
      code/VideoAccess-VCMP/web/client/assets/js/jessibuca/decoder.js
  99. BIN
      code/VideoAccess-VCMP/web/client/assets/js/jessibuca/decoder.wasm
  100. 1
      code/VideoAccess-VCMP/web/client/assets/js/jessibuca/jessibuca.js

1
.gitignore

@ -138,3 +138,4 @@ dist
*yarn.lock *yarn.lock
*package-lock.json *package-lock.json
*log/ *log/
*downloadFiles/

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

@ -1,41 +1,52 @@
{ {
// 使 IntelliSense // 使 IntelliSense
// //
// 访: https://go.microsoft.com/fwlink/?linkid=830387 // 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"name": "启动API", "name": "启动API",
"program": "${workspaceRoot}/server.js", "program": "${workspaceRoot}/server.js",
"env": { "env": {
"NODE_ENV": "development" "NODE_ENV": "development"
}, },
"args": [ "args": [
"-p 14000", "-p 4000",
"-f http://localhost:14000", "-f http://localhost:4000",
// "-g postgres://postgres:123@10.8.30.32:5432/yinjiguanli", "-g postgres://postgres:123@10.8.30.32:5432/video_access",
// "-g postgres://postgres:123456@221.230.55.27:5432/yinjiguanli", "--redisHost 127.0.0.1",
// "-g postgres://FashionAdmin:123456@10.8.30.156:5432/SmartEmergency", "--redisPort 6379",
"-g postgres://postgres:Mantis1921@116.63.50.139:54327/smartYingji" "--axyApiUrl http://127.0.0.1:4100",
] "--iotAuthApi http://127.0.0.1:4200",
}, "--godUrl https://restapi.amap.com/v3",
{ "--godKey 21c2d970e1646bb9a795900dd00093ce",
"type": "node", "--mqttVideoServer mqtt://10.8.30.71:30883",
"request": "launch", "--iotVideoServerUrl http://221.230.55.27:8081",
"name": "run mocha", // "--iotVideoServerUrl http://10.8.30.59:8080",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", "--cameraPlayWsHost ws://221.230.55.27:8081",
"stopOnEntry": false, "--cameraPlayHttpFlvHost http://221.230.55.27:2020",
"args": [ "--cameraPlayHlsHost http://221.230.55.27:8081",
"app/test/*.test.js", "--cameraPlayRtmpHost rtmp://221.230.55.27:1935",
"--no-timeouts" "--cameraPlayRtspHost rtsp://221.230.55.27:554"
], ]
"cwd": "${workspaceRoot}", },
"runtimeExecutable": null, {
"env": { "type": "node",
"NODE_ENV": "development" "request": "launch",
} "name": "run mocha",
} "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
] "stopOnEntry": false,
"args": [
"app/test/*.test.js",
"--no-timeouts"
],
"cwd": "${workspaceRoot}",
"runtimeExecutable": null,
"env": {
"NODE_ENV": "development"
}
}
]
} }

19
code/VideoAccess-VCMP/api/Dockerfile

@ -1,7 +1,4 @@
FROM repository.anxinyun.cn/devops/node:12-dev as builder
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
MAINTAINER liuxinyi "liu.xinyi@free-sun.com.cn"
COPY . /var/app COPY . /var/app
@ -9,6 +6,16 @@ WORKDIR /var/app
EXPOSE 8080 EXPOSE 8080
CMD ["-g", "postgres://FashionAdmin:123456@iota-m1:5433/SmartRiver", "--qnak", "5XrM4wEB9YU6RQwT64sPzzE6cYFKZgssdP5Kj3uu", "--qnsk", "w6j2ixR_i-aelc6I7S3HotKIX-ukMzcKmDfH6-M5", "--qnbkt", "anxinyun-test", "--qndmn", "http://test.resources.anxinyun.cn"] RUN npm config set registry=http://10.8.30.22:7000
RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
RUN npm cache clean -f
RUN rm -rf package-lock.json
RUN npm install --registry http://10.8.30.22:7000
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12
COPY --from=builder --chown=node /var/app /home/node/app
WORKDIR /home/node/app
ENTRYPOINT [ "node", "server.js" ] CMD ["node", "server.js"]

189
code/VideoAccess-VCMP/api/app/lib/controllers/auth/index.js

@ -1,189 +0,0 @@
'use strict';
const Hex = require('crypto-js/enc-hex');
const MD5 = require('crypto-js/md5');
const moment = require('moment');
const uuid = require('uuid');
async function login(ctx, next) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const params = ctx.request.body;
let password = Hex.stringify(MD5(params.password));
const userRes = await models.User.findOne({
where: {
username: params.username,
password: password,
delete: false,
},
attributes: { exclude: ['password'] },
include: [{
attributes: ["resourceId"],
model: models.UserResource
}]
});
if (!userRes) {
ctx.status = 400;
ctx.body = {
"message": "账号或密码错误"
}
} else if (!userRes.enable) {
ctx.status = 400;
ctx.body = { message: "该用户已被禁用" }
} else {
const token = uuid.v4();
let userRslt = Object.assign(userRes.dataValues, {
authorized: true,
token: token,
userResources: userRes.userResources.map(r => r.resourceId),
});
await models.UserToken.create({
token: token,
userInfo: userRslt,
expired: moment().add(30, 'days').format()
});
ctx.status = 200;
ctx.body = userRslt;
}
await transaction.commit();
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "登录失败"
}
}
}
/**
* 微信小程序登录
* @@requires.body {phone-手机号, password-密码} ctx
*/
async function wxLogin(ctx, next) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const params = ctx.request.body;
let password = Hex.stringify(MD5(params.password));
const userRes = await models.User.findOne({
where: {
phone: params.phone,
password: password,
delete: false,
},
attributes: { exclude: ['password'] }
});
if (!userRes) {
ctx.status = 400;
ctx.body = { message: "手机号或密码错误" }
} else if (!userRes.enable) {
ctx.status = 400;
ctx.body = { message: "该用户已被禁用" }
} else {
const token = uuid.v4();
//获取用户关注区域信息
const departmentRes = await models.Department.findOne({ where: { id: userRes.departmentId } });
let attentionRegion = departmentRes;
while (attentionRegion.dependence && attentionRegion.type != 1) {
const departmentParent = await models.Department.findOne({ where: { id: attentionRegion.dependence } });
attentionRegion = {
...departmentParent.dataValues,
nextRegin: attentionRegion
}
}
//获取用户权限信息
const resourceRes = await models.UserResource.findAll({
where: {
userId: userRes.id
},
include: [{
model: models.Resource,
attributes: ['code', 'name'],
}],
attributes: []
});
let userRslt = Object.assign({
authorized: true,
token: token,
...userRes.dataValues
});
await models.UserToken.create({
token: token,
userInfo: userRslt,
expired: moment().add(30, 'day').format('YYYY-MM-DD HH:mm:ss')
}, { transaction: transaction });
ctx.status = 200;
ctx.body = Object.assign({
...userRslt,
userRegionType: departmentRes.type,//1-市级,2-区县级,3-乡镇级,4-村级
attentionRegion: attentionRegion,
resources: resourceRes.map(r => r.resource)
});
}
await transaction.commit();
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "登录失败"
}
}
}
async function logout(ctx) {
try {
const { token, code } = ctx.request.body;
const models = ctx.fs.dc.models;
await models.UserToken.destroy({
where: {
token: token,
},
});
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "登出失败"
}
}
}
/**
* 微信小程序登出
* @request.body {token-用户登录Token} ctx
*/
async function wxLogout(ctx) {
try {
const { token } = ctx.request.body;
const models = ctx.fs.dc.models;
await models.UserToken.destroy({
where: {
token: token,
},
});
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "登出失败"
}
}
}
module.exports = {
login,
wxLogin,
logout,
wxLogout
};

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

@ -0,0 +1,571 @@
'use strict';
const moment = require('moment')
async function verifyYingshi (ctx) {
let errMsg = '校验萤石摄像头信息失败'
const { utils: { verifyYingshiInfo } } = ctx.app.fs
try {
const { serialNo } = ctx.request.body;
await verifyYingshiInfo({ serialNo })
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function createYingshi (ctx) {
let errMsg = '萤石摄像头失败'
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { verifyYingshiInfo } } = ctx.app.fs
const {
id, name, cloudControl, highDefinition, memoryCard,
voice, kindId, abilityId, rtmp, serialNo, longitude, latitude,
} = ctx.request.body;
let handleCameraId = id
errMsg = (handleCameraId ? '修改' : '添加') + errMsg
const beloneSecret = await verifyYingshiInfo({ serialNo })
const corGbYingshiRes = await models.GbCamera.findOne({
where: {
streamid: String(serialNo).toUpperCase(),
ipctype: 'yingshi'
}
})
let storageData = {
type: 'yingshi', name, cloudControl, highDefinition, memoryCard,
voice, longitude, latitude, kindId, rtmp,
serialNo: String(serialNo).toUpperCase(),
yingshiSecretId: beloneSecret.id,
gbId: corGbYingshiRes ? corGbYingshiRes.id : null
}
if (handleCameraId) {
await models.Camera.update(storageData, {
where: {
id: handleCameraId,
},
transaction
})
} else {
storageData.createTime = moment().format()
storageData.createUserId = userId
storageData.forbidden = false
const createRes = await models.Camera.create(storageData, {
transaction
})
handleCameraId = createRes.id
}
await models.CameraAbilityBind.destroy({
where: {
cameraId: handleCameraId
},
transaction
})
if (abilityId && handleCameraId) {
let storageData = abilityId.map(aid => {
return {
cameraId: handleCameraId,
abilityId: aid
}
})
if (storageData.length) {
await models.CameraAbilityBind.bulkCreate(storageData, {
transaction
})
}
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function getNvrSteam (ctx) {
let errMsg = '获取 NVR 视频流失败'
try {
const { models } = ctx.fs.dc
const { streamId } = ctx.query
const { utils: { getGbCameraLevel3ByStreamId, getPlayUrl } } = ctx.app.fs
const nvrRes = await models.Nvr.findOne({
where: {
serialNo: streamId,
}
})
if (!nvrRes) {
errMsg = '没有找到已配置的 NVR 信息'
throw errMsg
}
const addedRes = await models.Camera.findAll({
attributes: ['id', 'name', 'serialNo', 'cloudControl'],
where: {
nvrId: nvrRes.id
},
include: [{
model: models.CameraRemark,
attributes: ['remark'],
order: [
['id', 'DESC']
],
}],
})
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
}
c.dataValues.playUrl = await getPlayUrl({ topSerialNo: streamId, serialNo: c.dataValues.streamid })
}
ctx.status = 200;
ctx.body = cameraRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function getNvrSteamById (ctx) {
try {
const { models } = ctx.fs.dc
const { nvrId } = ctx.params
const { utils: { getGbCameraLevel3ByStreamId } } = ctx.app.fs
const cameraRes = await getGbCameraLevel3ByStreamId({ streamId, errMsg })
const nvrRes = await models.Nvr.findOne({
where: {
id: nvrId
}
})
ctx.status = 200;
ctx.body = {
serialNo: nvrRes.dataValues.serialNo,
stream: cameraRes
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function createNvrCamera (ctx) {
let errMsg = ''
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { getGbCameraLevel3ByStreamId } } = ctx.app.fs
const data = ctx.request.body
const { data: camera, serialNo } = data
if (!serialNo || !camera) {
errMsg = '参数错误'
throw errMsg
}
const nvrRes = await models.Nvr.findOne({
where: {
serialNo
}
})
if (!nvrRes) {
errMsg = '尚未添加相应的 NVR 设备'
throw errMsg
}
const addedCameraRes = await models.Camera.findAll({
where: {
nvrId: nvrRes.id
}
})
const allCameraRes = await getGbCameraLevel3ByStreamId({ streamId: serialNo })
let createData = []
let updateData = []
for (let c of camera) {
const corCamera = allCameraRes.find(ac => ac.streamid == c.streamid)
if (corCamera) {
const addedData = addedCameraRes.find(ac => ac.serialNo == c.streamid)
if (addedData) {
updateData.push({
...addedData.dataValues,
serialNo: c.streamid,
topSerialNo: serialNo,
name: c.name,
sip: corCamera.sipip,
cloudControl: c.cloudControl,
gbId: corCamera.id,
})
} else {
createData.push({
type: 'nvr',
serialNo: c.streamid,
topSerialNo: serialNo,
name: c.name,
sip: corCamera.sipip,
cloudControl: c.cloudControl,
nvrId: nvrRes.id,
createTime: moment().format(),
createUserId: userId,
forbidden: false,
gbId: corCamera.id,
})
}
} else {
errMsg = '参数错误'
throw errMsg
}
}
if (createData.length) {
await models.Camera.bulkCreate(createData, {
transaction
})
}
if (updateData.length) {
for (let u of updateData) {
await models.Camera.update(u, {
where: {
id: u.id
},
transaction
})
}
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: errMsg ? undefined : errMsg
}
}
}
async function verifyIpcCamera (ctx) {
let errMsg = '校验萤石摄像头信息失败'
try {
const { utils: { verifyIpcInfo } } = ctx.app.fs
const { serialNo, } = ctx.request.body;
await verifyIpcInfo({ serialNo })
ctx.status = 204;
} catch (error) {
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function createIpcCamera (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
let errMsg = ' IPC 网络摄像头失败'
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { verifyIpcInfo } } = ctx.app.fs
const {
id, name, cloudControl, memoryCard,
voice, longitude, latitude, venderId, rtmp,
serialNo, kindId, abilityId,
} = ctx.request.body;
let handleCameraId = id
errMsg = (handleCameraId ? '修改' : '添加') + errMsg
let storageData = {
type: 'ipc', name, cloudControl, memoryCard,
voice, longitude, latitude, rtmp, venderId,
serialNo, kindId,
}
const gbCameraRes = await verifyIpcInfo({ serialNo })
storageData.sip = gbCameraRes.sipip
storageData.gbId = gbCameraRes.id
if (handleCameraId) {
await models.Camera.update(storageData, {
where: {
id: handleCameraId,
},
transaction
})
} else {
storageData.createTime = moment().format()
storageData.createUserId = userId
storageData.forbidden = false
const createRes = await models.Camera.create(storageData, {
transaction
})
handleCameraId = createRes.id
}
// 保存设备能力
await models.CameraAbilityBind.destroy({
where: {
cameraId: handleCameraId
},
transaction
})
if (abilityId && handleCameraId) {
let storageData = abilityId.map(aid => {
return {
cameraId: handleCameraId,
abilityId: aid
}
})
if (storageData.length) {
await models.CameraAbilityBind.bulkCreate(storageData, {
transaction
})
}
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function getCascadeSipList (ctx) {
try {
const { models } = ctx.fs.dc
const sipListRes = await models.GbCamera.findAll({
attributes: ['id', 'streamid', 'sipip'],
where: {
level: 0,
ipctype: '级联',
// sipip: { $ne: null }
}
})
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 {
const { utils: { verifyCascadeInfo } } = ctx.app.fs
const { streamId } = ctx.request.body
await verifyCascadeInfo({ streamId })
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function getCascadeSteam (ctx) {
let errMsg = '获取级联摄像头视频流失败'
try {
const { models } = ctx.fs.dc
const { streamId } = ctx.query
const { utils: { getGbCameraLevel3ByStreamId, getPlayUrl } } = ctx.app.fs
const cascadeRes = await models.GbCamera.findOne({
where: {
streamid: streamId
}
})
if (!cascadeRes) {
errMsg = '没有找到已记录的级联摄像头信息'
throw errMsg
}
const cameraRes = await getGbCameraLevel3ByStreamId({ streamId: cascadeRes.streamid })
const allStreamid = cameraRes.map(c => c.streamid)
const addedRes = await models.Camera.findAll({
attributes: ['id', 'name', 'serialNo'],
where: {
serialNo: { $in: allStreamid }
},
include: [{
model: models.CameraRemark,
attributes: ['remark'],
order: [
['id', 'DESC']
],
}],
})
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
}
c.dataValues.playUrl = await getPlayUrl({ topSerialNo: cascadeRes.streamid, serialNo: c.dataValues.streamid })
}
ctx.status = 200;
ctx.body = cameraRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function getCascadeCameraGrandParentSip (ctx) {
let errMsg = '查询级联设备失败'
try {
const { models } = ctx.fs.dc
const { cameraSerialNo } = ctx.query
const { utils: { getGbCameraLevel1ByStreamId } } = ctx.app.fs
const parent = await getGbCameraLevel1ByStreamId({
streamId: cameraSerialNo,
where: { ipctype: '级联' }
})
if (!parent) {
errMsg = `没有找到相应级联设备`
throw errMsg
}
ctx.status = 200;
ctx.body = parent
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
async function createCascadeCamera (ctx) {
let errMsg = '添加级联摄像头信息失败'
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { streamId, camera = [], externalDomain, cascadeType } = ctx.request.body
const { utils: { getGbCameraLevel3ByStreamId, verifyCascadeInfo } } = ctx.app.fs
const cameraParentRes = await verifyCascadeInfo({ streamId })
const allCameraRes = await getGbCameraLevel3ByStreamId({ streamId: cameraParentRes.streamid })
const allCameraIds = allCameraRes.map(c => c.id)
const addedCmeraRes = allCameraIds.length ?
await models.Camera.findAll({
where: {
type: 'cascade',
gbId: { $in: allCameraIds },
delete: false
}
}) : []
let addData = []
let updateData = []
for (let c of camera) {
const corGbCamera = allCameraRes.find(ac => ac.id == c.id)
if (!corGbCamera) {
errMsg = '数据信息错误'
throw errMsg
}
let storageData = {
externalDomain,
cascadeType,
serialNo: corGbCamera.streamid,
topSerialNo: cameraParentRes.streamid,
sip: corGbCamera.sipip,
name: c.name,
gbId: corGbCamera.id,
}
const added = addedCmeraRes.find(ac => ac.gbId == corGbCamera.id)
if (added) {
let data = {
...storageData,
id: added.id,
}
updateData.push(data)
await models.Camera.update(data, {
where: { id: added.id },
transaction
})
} else {
addData.push({
...storageData,
type: 'cascade',
createTime: moment().format(),
createUserId: userId,
forbidden: false
})
}
}
await models.Camera.bulkCreate(addData, {
transaction
})
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : errMsg
}
}
}
module.exports = {
verifyYingshi,
createYingshi,
getNvrSteam,
getNvrSteamById,
createNvrCamera,
verifyIpcCamera,
createIpcCamera,
getCascadeSipList,
verifyCascadeCamera,
getCascadeSteam,
getCascadeCameraGrandParentSip,
createCascadeCamera,
};

565
code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js

@ -0,0 +1,565 @@
'use strict';
const fs = require('fs');
const moment = require('moment')
async function getCameraProject (ctx, next) {
try {
const models = ctx.fs.dc.models;
const { limit, page, orderBy, orderDirection, keyword, abilityId, type, venderId, nvrId, externalDomain, state } = ctx.query
const { userId, token } = ctx.fs.api
const { utils: { getPlayUrl } } = ctx.app.fs
let findOption = {
attributes: { exclude: ['delete', 'recycleTime',] },
where: {
createUserId: userId,
recycleTime: null,
delete: false
},
order: [
[orderBy || 'id', orderDirection || 'DESC']
],
include: [{
model: models.CameraKind
}, {
model: models.Nvr,
where: nvrId ? {
id: nvrId
} : {},
required: Boolean(nvrId),
attributes: ['id', 'name', 'serialNo']
}, {
model: models.SecretYingshi,
attributes: ['token']
}, {
model: models.CameraRemark,
attributes: ['id', 'remark'],
order: ['id']
}],
distinct: true
}
let abilityFind = {
model: models.CameraAbility
}
let gbCameraOption = {
model: models.GbCamera,
attributes: ['id', 'online', 'playUrl'],
required: false
}
if (limit) {
findOption.limit = limit
}
if (page && limit) {
findOption.offset = page * limit
}
if (keyword) {
// findOption.where.name = { $like: `%${keyword}%` }
findOption.where.$or = [
{
name: { $like: `%${keyword}%` }
},
// {
// serialNo: { $like: `%${keyword}%` }
// }
]
}
if (type) {
findOption.where.type = type
}
if (venderId) {
findOption.where.venderId = venderId
}
if (abilityId) {
abilityFind.where = {
abilityId: abilityId
}
}
if (externalDomain) {
findOption.where.externalDomain = externalDomain
}
if (state) {
if (state == 'DISABLED') {
findOption.where.forbidden = true
} else {
findOption.where.forbidden = false
const onLineMap = {
ON: ['ON', 'ONLINE'],
OFF: ['OFF'],
// UNKONW: [],
// DISABLED: []
}
let unknowState = []
for (let k in onLineMap) {
unknowState = unknowState.concat(onLineMap[k])
}
gbCameraOption.where = {
online: state == 'UNKONW' ?
{ $notIn: unknowState }
: { $in: onLineMap[state] }
}
gbCameraOption.required = true
}
}
findOption.include.push(gbCameraOption)
findOption.include.push(abilityFind)
const cameraRes = await models.Camera.findAll(findOption)
// const cameraRes = await models.Camera.findAndCountAll(findOption)
delete findOption.order
delete findOption.limit
delete findOption.offset
delete findOption.attributes
const total = await models.Camera.count(findOption)
let cameraIds = []
let createUserIds = new Set()
for (let c of cameraRes) {
cameraIds.push(c.dataValues.id)
createUserIds.add(c.dataValues.createUserId)
}
// 查在安心云绑定的数据
const axbindCameraRes = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
// 查对应创建者信息
const corUsers =
createUserIds.size ?
await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, {
query: { token }
})
: []
for (let { dataValues: camera } of cameraRes) {
const corBindCamera = axbindCameraRes.filter(b => b.cameraId == camera.id)
camera.station = corBindCamera.reduce((station, c) => {
return station.concat.apply(station, c.stations)
}, [])
const corUser = corUsers.find(u => u.id == camera.createUserId)
camera.createUser = {
namePresent: corUser ? corUser.namePresent : ''
}
if (camera.type != 'yingshi') {
const playUrl = await getPlayUrl({ topSerialNo: camera.topSerialNo, serialNo: camera.serialNo })
camera.gbCamera.dataValues.playUrl = playUrl
}
}
ctx.status = 200;
ctx.body = {
total: total,
data: cameraRes
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function getCamera (ctx) {
try {
const { models } = ctx.fs.dc;
const { cameraId } = ctx.query
const cameraRes = await models.Camera.findAll({
attributes: { exclude: ['delete', 'recycleTime',] },
where: {
id: { $in: cameraId.split(',') }
},
include: [{
model: models.CameraAbility
}, {
model: models.CameraKind
}, {
model: models.Vender
}, {
model: models.SecretYingshi,
attributes: ['token']
}, {
model: models.GbCamera,
attributes: ['id', 'online', 'playUrl'],
required: false
}, {
model: models.CameraRemark,
attributes: ['remark'],
order: [
['id', 'DESC']
],
}]
})
ctx.status = 200;
ctx.body = cameraRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function detail (ctx) {
let errMsg = `获取摄像头详情失败`
try {
const { models } = ctx.fs.dc;
const { cameraId } = ctx.params
const { userId, token } = ctx.fs.api
const { utils: { getPlayUrl } } = ctx.app.fs
const cameraRes = await models.Camera.findOne({
where: {
id: cameraId
},
include: {
model: models.GbCamera,
attributes: ['id', 'online', 'playUrl'],
required: false
}
})
if (!cameraRes) {
throw errMsg
}
const cameraProject = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraRes.id } })
const bindStations = []
for (let c of cameraProject) {
for (let s of c.stations) {
bindStations.push(s)
}
}
const corUser = await ctx.app.fs.authRequest.get(`user/${cameraRes.createUserId}/message`, { query: { token } })
let rslt = {
...cameraRes.dataValues,
station: bindStations,
createUser: {
namePresent: corUser[0].namePresent
}
}
if (cameraRes.type != 'yingshi') {
rslt.gbCamera.playUrl = await getPlayUrl({ topSerialNo: cameraRes.topSerialNo, serialNo: cameraRes.serialNo })
}
ctx.status = 200;
ctx.body = rslt
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: errMsg
}
}
}
async function getCameraListAll (ctx) {
try {
const { models } = ctx.fs.dc;
const cameraRes = await models.Camera.findAll({
attributes: ['id', 'name', 'type'],
where: {
delete: false,
recycleTime: null,
}
})
ctx.status = 200;
ctx.body = cameraRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function banned (ctx) {
try {
const { models } = ctx.fs.dc;
const data = ctx.request.body;
// 向视频服务发送通知
// 库记录
await models.Camera.update({
forbidden: data.forbidden
}, {
where: {
id: data.cameraId
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function del (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
const { cameraId } = ctx.params
const { token } = ctx.fs.api
await models.CameraAbilityBind.destroy({
where: {
cameraId: cameraId
},
transaction
})
await models.CameraRemark.destroy({
where: {
cameraId: cameraId
},
transaction
})
await models.Camera.destroy({
where: {
id: cameraId
},
transaction
})
if (cameraId) {
await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraId } })
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function cameraExport (ctx) {
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { simpleExcelDown } } = ctx.app.fs
const header = [{
title: "设备名称",
key: "name",
}, {
title: "设备厂家",
key: "vender",
}, {
title: "接入类型",
key: "type",
}, {
title: "设备状态",
key: "state",
}, {
title: "云台支持",
key: "cloudControl",
}, {
title: "内存卡信息",
key: "memoryCard",
}, {
title: "设备创建时间",
key: "createTime",
}, {
title: "设备添加账号",
key: "createUser",
}, {
title: "项目名称",
key: "projectName",
}, {
title: "pcode",
key: "pcode",
}, {
title: "结构物",
key: "structure",
}, {
title: "测点",
key: "stationName",
}, {
title: "监测因素",
key: "factor",
},];
const cameraRes = await models.Camera.findAll({
where: {
createUserId: userId,
recycleTime: null,
delete: false
},
include: [{
model: models.CameraAbility
}, {
model: models.CameraKind
}, {
model: models.Vender
}]
})
let cameraIds = []
let createUserIds = new Set()
for (let c of cameraRes) {
cameraIds.push(c.dataValues.id)
createUserIds.add(c.dataValues.createUserId)
}
// 查在安心云绑定的数据
const axbindCameraRes = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
// 查对应创建者信息
const corUsers = await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, { query: { token } })
let exportData = []
let typeMap = {
yingshi: '萤石云平台摄像头',
nvr: 'NVR摄像头',
ipc: 'IPC 网络摄像头',
cascade: '不明厂家',
}
for (let { dataValues: camera } of cameraRes) {
camera.vender = camera.vender ? camera.vender.name : ''
camera.type = typeMap[camera.type]
const corUser = corUsers.find(u => u.id == camera.createUserId)
camera.createUser = corUser ? corUser.username : ''
let stationName = new Set(),
projectName = new Set(),
pcode = new Set(),
structure = new Set(),
factor = new Set()
const corBindCamera = axbindCameraRes.find(b => b.cameraId == camera.id)
if (corBindCamera) {
for (let station of corBindCamera.stations) {
stationName.add(station.name)
factor.add(station.factor.name)
structure.add(station.structure.name)
for (let project of station.structure.projects) {
projectName.add(project.name)
pcode.add(project.url)
}
}
}
camera.stationName = [...stationName].join('\r\n')
camera.factor = [...factor].join('\r\n')
camera.projectName = [...projectName].join('\r\n')
camera.pcode = [...pcode].join('\r\n')
camera.structure = [...structure].join('\r\n')
exportData.push(camera)
}
const fileName = `摄像头信息列表_${userId}_${moment().format('YYYYMMDDHHmmss')}` + '.csv'
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName })
const fileData = fs.readFileSync(filePath);
ctx.status = 200;
ctx.set('Content-Type', 'application/x-xls');
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
ctx.body = fileData;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function getAbility (ctx) {
try {
const { models } = ctx.fs.dc;
const abilityRes = await models.CameraAbility.findAll()
ctx.status = 200;
ctx.body = abilityRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function getKind (ctx) {
try {
const { models } = ctx.fs.dc;
const kindRes = await models.CameraKind.findAll()
ctx.status = 200;
ctx.body = kindRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function remark (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
let errMsg = undefined
try {
const { models } = ctx.fs.dc
const { cameraId, remark, } = ctx.request.body;
const cameraRes = await models.Camera.findOne({
where: {
id: cameraId
}
})
if (!cameraRes) {
errMsg = '摄像头不存在'
}
await models.CameraRemark.destroy({
where: {
cameraId
},
transaction
})
await models.CameraRemark.bulkCreate(remark.map(r => {
return {
cameraId,
remark: r
}
}), {
transaction
})
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: errMsg
}
}
}
module.exports = {
getCameraProject,
getCamera,
getCameraListAll,
detail,
banned,
del,
cameraExport,
getAbility,
getKind,
remark,
};

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

@ -0,0 +1,463 @@
'use strict';
const fs = require('fs');
const moment = require('moment')
async function edit (ctx, next) {
let errMsg = '添加 NVR 设备失败'
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { utils: { getGbCameraLevel3ByStreamId } } = ctx.app.fs
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const data = ctx.request.body;
const { serialNo } = data
const nvrGbRes = await models.GbCamera.findOne({
where: {
streamid: serialNo,
level: 0,
// ipctype: 'nvr'
}
})
if (!nvrGbRes) {
errMsg = '没有找到已接入的 NVR 服务信息'
throw errMsg
}
const channelRes = await getGbCameraLevel3ByStreamId({ streamId: serialNo, errMsg })
// 或取其他服务信息
const nvrData = {
channelCount: channelRes.length,
port: 8080,
sip: nvrGbRes.sipip,
}
if (data.id) {
// 修改
const storageData = Object.assign({}, data, nvrData)
await models.Nvr.update(storageData, {
where: {
id: data.id
},
transaction
})
} else {
// 添加
const storageData = Object.assign({}, data, nvrData, {
createTime: moment().format(),
createUserId: userId,
delete: false,
})
await models.Nvr.create(storageData, { transaction })
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: errMsg
}
}
}
async function verify (ctx, next) {
let errMsg = '校验 NVR 设备信息失败'
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const data = ctx.request.body;
const { serialNo } = data
const nvrGbRes = await models.GbCamera.findOne({
where: {
streamid: serialNo,
level: 0,
// ipctype: 'nvr'
}
})
if (!nvrGbRes) {
errMsg = '没有找到已接入的 NVR 服务信息'
throw errMsg
}
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
resaon: errMsg
}
}
}
async function get (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const { limit, page, orderBy, orderDirection, keyword, venderId, state } = ctx.query
let findOption = {
attributes: { exclude: ['delete'] },
where: {
createUserId: userId,
delete: false,
},
order: [
[orderBy || 'id', orderDirection || 'DESC']
],
include: [],
distinct: true
}
let gbNvrOption = {
model: models.GbCamera,
as: 'gbNvr',
// attributes: ['id', 'address', 'name', 'online'],
required: false
}
if (limit) {
findOption.limit = limit
}
if (page && limit) {
findOption.offset = page * limit
}
if (keyword) {
findOption.where.name = { $like: `%${keyword}%` }
}
if (venderId) {
findOption.where.venderId = venderId
}
if (state) {
const onLineMap = {
ON: ['ON', 'ONLINE'],
OFF: ['OFF'],
// UNKONW: [],
DISABLED: []
}
let unknowState = []
for (let k in onLineMap) {
unknowState = unknowState.concat(onLineMap[k])
}
gbNvrOption.where = {
online: state == 'UNKONW' ?
{ $notIn: unknowState }
: { $in: onLineMap[state] }
}
gbNvrOption.required = true
}
findOption.include.push(gbNvrOption)
const nvrRes = await models.Nvr.findAndCountAll(findOption)
const nvrIds = nvrRes.rows.map(r => r.id)
const cameraRes = await models.Camera.findAll({
where: {
nvrId: { $in: nvrIds }
}
})
let createUserIds = new Set()
let cameraIds = []
for (let c of cameraRes) {
cameraIds.push(c.id)
createUserIds.add(c.createUserId)
}
// 查在安心云绑定的数据
const axbindCameraRes = cameraIds.length ?
await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
: []
// 查用户信息
const createUserRes = await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, { query: { token } })
for (let { dataValues: n } of nvrRes.rows) {
const corCameras = cameraRes.filter(c => c.nvrId == n.id)
const corBind = axbindCameraRes.filter(b => corCameras.some(c => c.id == b.cameraId))
const corCreateUser = createUserRes.find(u => u.id == n.createUserId)
n.createUser = {
name: corCreateUser ? corCreateUser.username : ''
}
if (corBind.length) {
n.station = []
for (let c of corBind) {
n.station = n.station.concat(c.stations)
}
} else {
n.station = []
}
}
ctx.status = 200;
ctx.body = {
total: nvrRes.count,
data: nvrRes.rows
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function del (ctx, next) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const { nvrId } = ctx.params
await models.Nvr.destroy({
where: {
id: nvrId
},
transaction
})
const cameraRes = await models.Camera.findAll({
where: {
nvrId
}
})
const cameraIds = cameraRes.map(c => c.id)
await models.Camera.destroy({
where: {
nvrId,
}
})
if (cameraIds.length) {
await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function detail (ctx) {
let errMsg = '获取 NVR 详情失败'
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const { nvrId } = ctx.params
const nvrRes = await models.Nvr.findOne({
attributes: { exclude: ['delete'] },
where: {
id: nvrId
},
include: [{
model: models.Vender
}, {
model: models.GbCamera,
as: 'gbNvr',
// attributes: ['id', 'address', 'name', 'online', 'registerTime', 'updateTime'],
required: false
}]
})
if (!nvrRes) {
throw errMsg
}
// 查询对应的后端服务相关信息
const cameraRes = await models.Camera.findAll({
attributes: ['id', 'name', 'channelName', 'serialNo', 'rtmp'],
where: {
nvrId
}
})
let cameras = []
let cameraIds = []
for (let c of cameraRes) {
cameraIds.push(c.id)
cameras.push(c.dataValues)
}
const cameraProject = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
const bindStations = []
for (let c of cameraProject) {
for (let s of c.stations) {
bindStations.push(s)
}
}
const corUser = await ctx.app.fs.authRequest.get(`user/${nvrRes.createUserId}/message`, { query: { token } })
const serverDRes = (await ctx.app.fs.videoServerRequest.post(`gb28181/api/plugins`) || '')
// const serverDRes = (await ctx.app.fs.videoServerRequest.post(`gateway/plugins`) || '')
const serverDArr = JSON.parse(serverDRes.replace(/'/g, '"')) || []
const serverDConfig = serverDArr.find(s => s.Name == 'GB28181')
let serveD = {}
if (serverDConfig) {
const { Config } = serverDConfig
let ConfigArr = Config.split('\n')
for (let c of ConfigArr) {
let config = c.split(' = ')
if (config.length == 2) {
serveD[config[0].trim()] = config[1].trim().replace(/\"/g, '')
}
}
}
let nvrDetail = {
...nvrRes.dataValues,
station: bindStations,
camera: cameras,
createUser: {
namePresent: corUser[0].namePresent
},
accessWay: 'GB/T28181',
accessInfo: serveD
}
ctx.status = 200;
ctx.body = nvrDetail
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: errMsg }
}
}
async function nvrExport (ctx) {
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { simpleExcelDown } } = ctx.app.fs
const header = [{
title: "设备名称",
key: "name",
}, {
title: "SIP地址",
key: "sip",
}, {
title: "设备厂家",
key: "vender",
}, {
title: "添加账号",
key: "createUser",
}, {
title: "通道数",
key: "channelCount",
}, {
title: "端口",
key: "port",
}, {
title: "设备状态",
key: "state",
}, {
title: "创建时间",
key: "createTime",
}, {
title: "项目名称",
key: "projectName",
}, {
title: "pcode",
key: "pcode",
}, {
title: "结构物",
key: "structure",
},];
const nvrRes = await models.Nvr.findAll({
where: {
createUserId: userId,
},
include: [{
model: models.Vender
}]
})
const nvrIds = nvrRes.map(r => r.id)
const cameraRes = await models.Camera.findAll({
where: {
nvrId: { $in: nvrIds }
}
})
let createUserIds = new Set()
let cameraIds = []
for (let c of cameraRes) {
cameraIds.push(c.id)
createUserIds.add(c.createUserId)
}
// 查在安心云绑定的数据
const axbindCameraRes =
cameraIds.length ?
await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
: []
// 查用户信息
const createUserRes = await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, { query: { token } })
let exportData = []
for (let { dataValues: n } of nvrRes) {
const corCameras = cameraRes.filter(c => c.nvrId == n.id)
const corBind = axbindCameraRes.filter(b => corCameras.some(c => c.id == b.cameraId))
const corCreateUser = createUserRes.find(u => u.id == n.createUserId)
n.createUser = {
name: corCreateUser ? corCreateUser.username : ''
}
n.vender = n.vender ? n.vender.name : ''
n.createTime = moment(n.createTime).format('YYYY-MM-DD HH:mm:ss')
let projectName = new Set(),
pcode = new Set(),
structure = new Set();
if (corBind.length) {
for (let c of corBind) {
for (let station of c.stations) {
structure.add(station.structure.name)
for (let project of station.structure.projects) {
projectName.add(project.name)
pcode.add(project.url)
}
}
}
}
n.projectName = [...projectName].join('\r\n')
n.pcode = [...pcode].join('\r\n')
n.structure = [...structure].join('\r\n')
exportData.push(n)
}
const fileName = `NVR信息列表_${userId}_${moment().format('YYYYMMDDHHmmss')}` + '.csv'
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName })
const fileData = fs.readFileSync(filePath);
ctx.status = 200;
ctx.set('Content-Type', 'application/x-xls');
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
ctx.body = fileData;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
module.exports = {
edit,
verify,
get,
del,
detail,
nvrExport,
};

23
code/VideoAccess-VCMP/api/app/lib/controllers/vender/index.js

@ -0,0 +1,23 @@
'use strict';
async function get (ctx) {
const models = ctx.fs.dc.models;
try {
const res = await models.Vender.findAll({
order: [
['id', 'ASC']
]
})
ctx.status = 200;
ctx.body = res
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
module.exports = {
get,
};

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

@ -1,36 +1,62 @@
'use strict'; 'use strict';
const fs = require('fs');
const path = require('path');
const utils = require('./utils')
const routes = require('./routes'); 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 authenticator = require('./middlewares/authenticator');
const schedule = require('./schedule')
// const apiLog = require('./middlewares/api-log'); // const apiLog = require('./middlewares/api-log');
const businessRest = require('./middlewares/business-rest');
module.exports.entry = function (app, router, opts) { module.exports.entry = function (app, router, opts) {
app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.'); app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.');
app.fs.api = app.fs.api || {}; app.fs.api = app.fs.api || {};
app.fs.api.authAttr = app.fs.api.authAttr || {}; app.fs.utils = app.fs.utils || {};
app.fs.api.logAttr = app.fs.api.logAttr || {}; app.fs.api.authAttr = app.fs.api.authAttr || {};
app.fs.api.logAttr = app.fs.api.logAttr || {};
router.use(authenticator(app, opts)); // 顺序固定 ↓
router.use(businessRest(app, router, opts)); redisConnect(app, opts)
// router.use(apiLog(app, opts)); socketConect(app, opts)
mqttVideoServer(app, opts)
router = routes(app, router, opts); // 实例其他平台请求方法
paasRequest(app, opts)
// 工具类函数
utils(app, opts)
// 定时任务
schedule(app, opts)
// 鉴权中间件
router.use(authenticator(app, opts));
// 日志记录
// router.use(apiLog(app, opts));
router = routes(app, router, opts);
}; };
module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Sequelize, models: {} } module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Sequelize, models: {} }
require('./models/user')(dc); require('./models/nvr')(dc);
require('./models/user_token')(dc); require('./models/camera_ability')(dc);
require('./models/department')(dc); require('./models/camera_kind')(dc);
require('./models/resource')(dc); require('./models/camera')(dc);
require('./models/user_resource')(dc); require('./models/camera_ability_bind')(dc);
require('./models/places')(dc); require('./models/vender')(dc);
require('./models/user_placeSecurityRecord')(dc); require('./models/secret_yingshi')(dc);
require('./models/report_type')(dc); require('./models/gb_camera')(dc);
require('./models/report_downManage')(dc); require('./models/ax_project')(dc);
require('./models/department')(dc); require('./models/camera_remark')(dc);
require('./models/report_configition')(dc);
require('./models/report_collection')(dc); // TODO 模型关系摘出来 初始化之后再定义关系才行
require('./models/report_rectify')(dc); // fs.readdirSync(path.join(__dirname, '/models')).forEach((filename) => {
// require(`./models/${filename}`)(dc)
// });
}; };

2
code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js

@ -71,7 +71,7 @@ function factory(app, opts) {
partition: 0 partition: 0
}]; }];
await sendToEsAsync(producer, payloads); // await sendToEsAsync(producer, payloads);
} catch (e) { } catch (e) {
ctx.fs.logger.error(`日志记录失败: ${e}`); ctx.fs.logger.error(`日志记录失败: ${e}`);

26
code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js

@ -13,13 +13,13 @@ class ExcludesUrls {
this.reload(opts); this.reload(opts);
} }
sanitizePath(path) { sanitizePath (path) {
if (!path) return '/'; if (!path) return '/';
const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/');
return p; return p;
} }
reload(opts) { reload (opts) {
// load all url // load all url
if (!this.allUrls) { if (!this.allUrls) {
this.allUrls = opts; this.allUrls = opts;
@ -37,7 +37,7 @@ class ExcludesUrls {
} }
} }
isExcluded(path, method) { isExcluded (path, method) {
return this.allUrls.some(function (url) { return this.allUrls.some(function (url) {
return !url.auth return !url.auth
&& url.pregexp.test(path) && url.pregexp.test(path)
@ -58,9 +58,7 @@ let isPathExcluded = function (opts, path, method) {
if (!excludeAll) { if (!excludeAll) {
let excludeOpts = opts.exclude || []; let excludeOpts = opts.exclude || [];
excludeOpts.push({ p: '/login', o: 'POST' }); excludeOpts.push({ p: '/login', o: 'POST' });
excludeOpts.push({ p: '/wxLogin', o: 'POST' });
excludeOpts.push({ p: '/logout', o: 'PUT' }); excludeOpts.push({ p: '/logout', o: 'PUT' });
excludeOpts.push({ p: '/wxLogout', o: 'PUT' });
excludes = new ExcludesUrls(excludeOpts); excludes = new ExcludesUrls(excludeOpts);
} }
let excluded = excludeAll || excludes.isExcluded(path, method); let excluded = excludeAll || excludes.isExcluded(path, method);
@ -72,14 +70,10 @@ let authorizeToken = async function (ctx, token) {
const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g;
if (token && tokenFormatRegexp.test(token)) { if (token && tokenFormatRegexp.test(token)) {
try { try {
const axyRes = await ctx.fs.dc.models.UserToken.findOne({ const expired = await ctx.redis.hget(token, 'expired');
where: {
token: token, if (expired && moment().valueOf() <= moment(expired).valueOf()) {
expired: { $gte: moment().format('YYYY-MM-DD HH:mm:ss') } const userInfo = JSON.parse(await ctx.redis.hget(token, 'userInfo'));
}
});
const { userInfo, expired } = axyRes;
if (!expired || moment().valueOf() <= moment(expired).valueOf()) {
rslt = { rslt = {
'authorized': userInfo.authorized, 'authorized': userInfo.authorized,
'resources': (userInfo || {}).resources || [], 'resources': (userInfo || {}).resources || [],
@ -100,7 +94,6 @@ let isResourceAvailable = function (resources, options) {
let authCode = null; let authCode = null;
// authorize user by authorization attribute // authorize user by authorization attribute
const { authAttr, method, path } = options; const { authAttr, method, path } = options;
console.log(resources, options)
for (let prop in authAttr) { for (let prop in authAttr) {
let keys = []; let keys = [];
let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys);
@ -112,13 +105,14 @@ let isResourceAvailable = function (resources, options) {
return !authCode || (resources || []).some(code => code === authCode); return !authCode || (resources || []).some(code => code === authCode);
}; };
function factory(app, opts) { function factory (app, opts) {
return async function auth(ctx, next) { return async function auth (ctx, next) {
const { path, method, header, query } = ctx; const { path, method, header, query } = ctx;
ctx.fs.logger.log('[AUTH] start', path, method); ctx.fs.logger.log('[AUTH] start', path, method);
ctx.fs.api = ctx.fs.api || {}; ctx.fs.api = ctx.fs.api || {};
ctx.fs.port = opts.port; ctx.fs.port = opts.port;
ctx.redis = app.redis; ctx.redis = app.redis;
ctx.redisTools = app.redisTools;
let error = null; let error = null;
if (path) { if (path) {
if (!isPathExcluded(opts, path, method)) { if (!isPathExcluded(opts, path, method)) {

50
code/VideoAccess-VCMP/api/app/lib/middlewares/business-rest.js

@ -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;

40
code/VideoAccess-VCMP/api/app/lib/models/ax_project.js

@ -0,0 +1,40 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const AxProject = sequelize.define("axProject", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: false,
unique: "ax_project_id_uindex"
},
name: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "name",
autoIncrement: false
}
}, {
tableName: "ax_project",
comment: "",
indexes: []
});
const Nvr = dc.models.Nvr;
// Nvr.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
// User.hasMany(Nvr, { foreignKey: 'userId', sourceKey: 'id' });
dc.models.AxProject = AxProject;
return AxProject;
};

284
code/VideoAccess-VCMP/api/app/lib/models/camera.js

@ -0,0 +1,284 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Camera = sequelize.define("camera", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_id_uindex"
},
type: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "设备类型:yingshi - 萤石;nvr - NVR摄像头;ipc - IPC 网络摄像头;cascade - 级联摄像头",
primaryKey: false,
field: "type",
autoIncrement: false
},
name: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "设备名称/安装位置",
primaryKey: false,
field: "name",
autoIncrement: false
},
channelName: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "通道名称",
primaryKey: false,
field: "channel_name",
autoIncrement: false
},
externalDomain: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "外域名称",
primaryKey: false,
field: "external_domain",
autoIncrement: false
},
rtmp: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "rtmp",
autoIncrement: false
},
serialNo: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "设备编号",
primaryKey: false,
field: "serial_no",
autoIncrement: false
},
topSerialNo: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "gb设备 level=0 的 steamid ",
primaryKey: false,
field: "top_serial_no",
autoIncrement: false
},
cloudControl: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: null,
comment: "云台控制",
primaryKey: false,
field: "cloud_control",
autoIncrement: false
},
highDefinition: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: null,
comment: "高清支持",
primaryKey: false,
field: "high_definition",
autoIncrement: false
},
voice: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: null,
comment: "语音对讲支持",
primaryKey: false,
field: "voice",
autoIncrement: false
},
memoryCard: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "内存卡容量",
primaryKey: false,
field: "memory_card",
autoIncrement: false
},
venderId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "设备厂商id",
primaryKey: false,
field: "vender_id",
autoIncrement: false,
references: {
key: "id",
model: "vender"
}
},
cascadeType: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "级联方式:up - 上级联;down - 下级联",
primaryKey: false,
field: "cascade_type",
autoIncrement: false
},
sip: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "sip",
autoIncrement: false
},
longitude: {
type: DataTypes.DOUBLE,
allowNull: true,
defaultValue: null,
comment: "经度",
primaryKey: false,
field: "longitude",
autoIncrement: false
},
latitude: {
type: DataTypes.DOUBLE,
allowNull: true,
defaultValue: null,
comment: "维度",
primaryKey: false,
field: "latitude",
autoIncrement: false
},
forbidden: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
comment: "是否禁用",
primaryKey: false,
field: "forbidden",
autoIncrement: false
},
createTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "create_time",
autoIncrement: false
},
recycleTime: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
comment: "放入回收站时间",
primaryKey: false,
field: "recycle_time",
autoIncrement: false
},
delete: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
comment: "是否彻底删除",
primaryKey: false,
field: "delete",
autoIncrement: false
},
createUserId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "create_user_id",
autoIncrement: false
},
nvrId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "nvr_id",
autoIncrement: false,
references: {
key: "id",
model: "nvr"
}
},
model: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "型号",
primaryKey: false,
field: "model",
autoIncrement: false
},
kindId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "kind_id",
autoIncrement: false,
references: {
key: "id",
model: "cameraKind"
}
},
yingshiSecretId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "yingshi_secret_id",
autoIncrement: false,
references: {
key: "id",
model: "secretYingshi"
}
},
gbId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "gb_id",
autoIncrement: false,
},
}, {
tableName: "camera",
comment: "",
indexes: []
});
dc.models.Camera = Camera;
const CameraKind = dc.models.CameraKind;
Camera.belongsTo(CameraKind, { foreignKey: 'kindId', targetKey: 'id' });
CameraKind.hasMany(Camera, { foreignKey: 'kindId', sourceKey: 'id' });
const Nvr = dc.models.Nvr;
Camera.belongsTo(Nvr, { foreignKey: 'nvrId', targetKey: 'id' });
Nvr.hasMany(Camera, { foreignKey: 'nvrId', sourceKey: 'id' });
return Camera;
};

34
code/VideoAccess-VCMP/api/app/lib/models/camera_ability.js

@ -0,0 +1,34 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraAbility = sequelize.define("cameraAbility", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: false,
unique: "camera_ability_id_uindex"
},
ability: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "ability",
autoIncrement: false
}
}, {
tableName: "camera_ability",
comment: "",
indexes: []
});
dc.models.CameraAbility = CameraAbility;
return CameraAbility;
};

56
code/VideoAccess-VCMP/api/app/lib/models/camera_ability_bind.js

@ -0,0 +1,56 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraAbilityBind = sequelize.define("cameraAbilityBind", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_ability_bind_id_uindex"
},
cameraId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "camera_id",
autoIncrement: false,
references: {
key: "id",
model: "camera"
}
},
abilityId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "ability_id",
autoIncrement: false,
references: {
key: "id",
model: "cameraAbility"
}
}
}, {
tableName: "camera_ability_bind",
comment: "",
indexes: []
});
dc.models.CameraAbilityBind = CameraAbilityBind;
const Camera = dc.models.Camera;
const CameraAbility = dc.models.CameraAbility;
Camera.belongsToMany(CameraAbility, { through: CameraAbilityBind, foreignKey: 'cameraId', otherKey: 'abilityId' });
return CameraAbilityBind;
};

34
code/VideoAccess-VCMP/api/app/lib/models/camera_kind.js

@ -0,0 +1,34 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraKind = sequelize.define("cameraKind", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: false,
unique: "camera_kind_id_uindex"
},
kind: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "kind",
autoIncrement: false
}
}, {
tableName: "camera_kind",
comment: "",
indexes: []
});
dc.models.CameraKind = CameraKind;
return CameraKind;
};

52
code/VideoAccess-VCMP/api/app/lib/models/camera_remark.js

@ -0,0 +1,52 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraRemark = sequelize.define("cameraRemark", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_remark_id_uindex"
},
cameraId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "camera_id",
autoIncrement: false,
references: {
key: "id",
model: "camera"
}
},
remark: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "remark",
autoIncrement: false
}
}, {
tableName: "camera_remark",
comment: "",
indexes: []
});
dc.models.CameraRemark = CameraRemark;
const Camera = dc.models.Camera;
CameraRemark.belongsTo(Camera, { foreignKey: 'cameraId', targetKey: 'id' });
Camera.hasMany(CameraRemark, { foreignKey: 'cameraId', sourceKey: 'id' });
return CameraRemark;
};

169
code/VideoAccess-VCMP/api/app/lib/models/gb_camera.js

@ -0,0 +1,169 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const GbCamera = sequelize.define("gbCamera", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "gbcamera_id_uindex"
},
level: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "level",
autoIncrement: false
},
parent: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "parent",
autoIncrement: false
},
streamid: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "streamid",
autoIncrement: false
},
registerTime: {
type: DataTypes.DATEONLY,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "registerTime",
autoIncrement: false
},
updateTime: {
type: DataTypes.DATEONLY,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "updateTime",
autoIncrement: false
},
online: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "online",
autoIncrement: false
},
manufactuer: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "manufactuer",
autoIncrement: false
},
model: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "model",
autoIncrement: false
},
civilCode: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "civilCode",
autoIncrement: false
},
adddress: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "adddress",
autoIncrement: false
},
name: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "name",
autoIncrement: false
},
addr: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "Addr",
autoIncrement: false
},
sipip: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "Sipip",
autoIncrement: false
},
ipctype: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "ipctype",
autoIncrement: false
},
playUrl: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "playUrl",
autoIncrement: false
}
}, {
tableName: "gbCamera",
comment: "",
indexes: []
});
const Nvr = dc.models.Nvr;
Nvr.belongsTo(GbCamera, { foreignKey: 'serialNo', targetKey: 'streamid', as: 'gbNvr' });
GbCamera.hasMany(Nvr, { foreignKey: 'serialNo', sourceKey: 'streamid', as: 'gbNvr' });
const Camera = dc.models.Camera;
Camera.belongsTo(GbCamera, { foreignKey: 'gbId', targetKey: 'id' });
GbCamera.hasMany(Camera, { foreignKey: 'gbId', sourceKey: 'id' });
dc.models.GbCamera = GbCamera;
return GbCamera;
};

128
code/VideoAccess-VCMP/api/app/lib/models/nvr.js

@ -0,0 +1,128 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Nvr = sequelize.define("nvr", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "nvr_id_uindex"
},
name: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "name",
autoIncrement: false
},
venderId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "设备厂家id",
primaryKey: false,
field: "vender_id",
autoIncrement: false,
references: {
key: "id",
model: "vender"
}
},
serialNo: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "设备编号",
primaryKey: false,
field: "serial_no",
autoIncrement: false
},
regionCode: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "行政区码",
primaryKey: false,
field: "region_code",
autoIncrement: false
},
longitude: {
type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "longitude",
autoIncrement: false
},
latitude: {
type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "latitude",
autoIncrement: false
},
createTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: sequelize.fn('now'),
comment: "创建时间",
primaryKey: false,
field: "create_time",
autoIncrement: false
},
channelCount: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "通道数",
primaryKey: false,
field: "channel_count",
autoIncrement: false
},
port: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "端口",
primaryKey: false,
field: "port",
autoIncrement: false
},
delete: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "delete",
autoIncrement: false
},
createUserId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "create_user_id",
autoIncrement: false
}
}, {
tableName: "nvr",
comment: "",
indexes: []
});
dc.models.Nvr = Nvr;
return Nvr;
};

67
code/VideoAccess-VCMP/api/app/lib/models/secret_yingshi.js

@ -0,0 +1,67 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const SecretYingshi = sequelize.define("secretYingshi", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "secret_yingshi_id_uindex"
},
key: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "key",
autoIncrement: false
},
secret: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "secret",
autoIncrement: false
},
token: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "token",
autoIncrement: false
},
expire: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "expire",
autoIncrement: false
}
}, {
tableName: "secret_yingshi",
comment: "",
indexes: []
});
const Camera = dc.models.Camera;
Camera.belongsTo(SecretYingshi, { foreignKey: 'yingshiSecretId', targetKey: 'id' });
SecretYingshi.hasMany(Camera, { foreignKey: 'yingshiSecretId', sourceKey: 'id' });
dc.models.SecretYingshi = SecretYingshi;
return SecretYingshi;
};

108
code/VideoAccess-VCMP/api/app/lib/models/user.js

@ -1,108 +0,0 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const User = sequelize.define("user", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "user_id_uindex"
},
name: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "name",
autoIncrement: false
},
username: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "用户名 账号",
primaryKey: false,
field: "username",
autoIncrement: false
},
password: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "password",
autoIncrement: false
},
departmentId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "部门id",
primaryKey: false,
field: "department_id",
autoIncrement: false
},
email: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "email",
autoIncrement: false
},
enable: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: "启用状态",
primaryKey: false,
field: "enable",
autoIncrement: false
},
delete: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "delete",
autoIncrement: false
},
phone: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "手机号(小程序使用手机号登录)",
primaryKey: false,
field: "phone",
autoIncrement: false
},
post: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "职位",
primaryKey: false,
field: "post",
autoIncrement: false
}
}, {
tableName: "user",
comment: "",
indexes: []
});
dc.models.User = User;
return User;
};

44
code/VideoAccess-VCMP/api/app/lib/models/vender.js

@ -0,0 +1,44 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Vender = sequelize.define("vender", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "vender_id_uindex"
},
name: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "name",
autoIncrement: false
}
}, {
tableName: "vender",
comment: "",
indexes: []
});
const Camera = dc.models.Camera;
Camera.belongsTo(Vender, { foreignKey: 'venderId', targetKey: 'id' });
Vender.hasMany(Camera, { foreignKey: 'venderId', sourceKey: 'id' });
const Nvr = dc.models.Nvr;
Nvr.belongsTo(Vender, { foreignKey: 'venderId', targetKey: 'id' });
Vender.hasMany(Nvr, { foreignKey: 'venderId', sourceKey: 'id' });
dc.models.Vender = Vender;
return Vender;
};

32
code/VideoAccess-VCMP/api/app/lib/routes/auth/index.js

@ -1,32 +0,0 @@
'use strict';
const auth = require('../../controllers/auth');
module.exports = function (app, router, opts) {
/**
* @api {Post} login 登录.
* @apiVersion 1.0.0
* @apiGroup Auth
*/
app.fs.api.logAttr['POST/login'] = { content: '登录', visible: true };
router.post('/login', auth.login);
/**
* @api {POST} wxLogin 微信小程序登录.使用手机号密码登录
* @apiVersion 1.0.0
* @apiGroup Auth
*/
app.fs.api.logAttr['POST/wxLogin'] = { content: '微信小程序登录', visible: true };
router.post('/wxLogin', auth.wxLogin);
app.fs.api.logAttr['PUT/logout'] = { content: '登出', visible: false };
router.put('/logout', auth.logout);
/**
* @api {PUT} wxLogout 微信小程序登出
* @apiVersion 1.0.0
* @apiGroup Auth
*/
app.fs.api.logAttr['PUT/wxLogout'] = { content: '登出', visible: false };
router.put('/wxLogout', auth.wxLogout);
};

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

@ -0,0 +1,76 @@
'use strict';
const camera = require('../../controllers/camera');
const cameraCreate = require('../../controllers/camera/create')
module.exports = function (app, router, opts) {
// 摄像头创建
app.fs.api.logAttr['POST/camera/verify/yingshi'] = { content: '验证萤石摄像头信息', visible: false };
router.post('/camera/verify/yingshi', cameraCreate.verifyYingshi);
app.fs.api.logAttr['POST/camera/create/yingshi'] = { content: '创建萤石摄像头', visible: false };
router.post('/camera/create/yingshi', cameraCreate.createYingshi);
app.fs.api.logAttr['GET/camera/nvr_stream'] = { content: '获取NVR视频流', visible: false };
router.get('/camera/nvr_stream', cameraCreate.getNvrSteam);
app.fs.api.logAttr['GET/nvr/:nvrId/nvr_stream'] = { content: '以 nvrId 获取NVR视频流', visible: false };
router.get('/nvr/:nvrId/nvr_stream', cameraCreate.getNvrSteamById);
app.fs.api.logAttr['POST/camera/create/nvr'] = { content: '记录NVR摄像头', visible: false };
router.post('/camera/create/nvr', cameraCreate.createNvrCamera);
app.fs.api.logAttr['POST/camera/verify/ipc'] = { content: '验证IPC摄像头信息', visible: false };
router.post('/camera/verify/ipc', cameraCreate.verifyIpcCamera);
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);
app.fs.api.logAttr['GET/camera/cascade_stream'] = { content: '获取级联视频流', visible: false };
router.get('/camera/cascade_stream', cameraCreate.getCascadeSteam);
app.fs.api.logAttr['POST/camera/create/cascade'] = { content: '添加级联摄像头', visible: false };
router.post('/camera/create/cascade', cameraCreate.createCascadeCamera);
app.fs.api.logAttr['GET/camera/cascade_device'] = { content: '获取级联摄像头父级设备', visible: false };
router.get('/camera/cascade_device', cameraCreate.getCascadeCameraGrandParentSip);
// 摄像头创建 END
app.fs.api.logAttr['GET/camera/project'] = { content: '获取摄像头列表及项目绑定信息', visible: false };
router.get('/camera/project', camera.getCameraProject);
app.fs.api.logAttr['GET/camera'] = { content: '获取摄像头信息', visible: false };
router.get('/camera', camera.getCamera);
app.fs.api.logAttr['GET/camera/:cameraId/detail'] = { content: '获取摄像头详情', visible: false };
router.get('/camera/:cameraId/detail', camera.detail);
app.fs.api.logAttr['GET/camera/listAll'] = { content: '获取摄像头详情', visible: false };
router.get('/camera/listAll', camera.getCameraListAll);
app.fs.api.logAttr['PUT/camera/banned'] = { content: '禁用摄像头', visible: false };
router.put('/camera/banned', camera.banned);
app.fs.api.logAttr['DEL/camera/:cameraId'] = { content: '删除摄像头', visible: false };
router.delete('/camera/:cameraId', camera.del);
app.fs.api.logAttr['GET/camera/export'] = { content: '导出摄像头信息', visible: false };
router.get('/camera/export', camera.cameraExport);
app.fs.api.logAttr['GET/camera/ability'] = { content: '获取摄像头能力列表', visible: false };
router.get('/camera/ability', camera.getAbility);
app.fs.api.logAttr['GET/camera/kind'] = { content: '获取摄像头种类列表', visible: false };
router.get('/camera/kind', camera.getKind);
app.fs.api.logAttr['POST/camera/remark'] = { content: '编辑摄像头备注', visible: false };
router.post('/camera/remark', camera.remark);
};

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

@ -4,14 +4,14 @@ const path = require('path');
const fs = require('fs'); const fs = require('fs');
module.exports = function (app, router, opts) { module.exports = function (app, router, opts) {
fs.readdirSync(__dirname).forEach((filename) => { fs.readdirSync(__dirname).forEach((filename) => {
if (filename.indexOf('.') !== 0 &&fs.lstatSync(path.join(__dirname, filename)).isDirectory()) { if (filename.indexOf('.') !== 0 && fs.lstatSync(path.join(__dirname, filename)).isDirectory()) {
fs.readdirSync(path.join(__dirname, filename)).forEach((api) => { fs.readdirSync(path.join(__dirname, filename)).forEach((api) => {
if (api.indexOf('.') == 0 || api.indexOf('.js') == -1) return; if (api.indexOf('.') == 0 || api.indexOf('.js') == -1) return;
require(`./${filename}/${api}`)(app, router, opts); require(`./${filename}/${api}`)(app, router, opts);
}); });
} }
}); });
return router; return router;
}; };

23
code/VideoAccess-VCMP/api/app/lib/routes/nvr/index.js

@ -0,0 +1,23 @@
'use strict';
const nvr = require('../../controllers/nvr');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['POST/nvr'] = { content: '添加/修改nvr', visible: false };
router.post('/nvr', nvr.edit);
app.fs.api.logAttr['POST/nvr/verify'] = { content: '校验nvr信息', visible: false };
router.post('/nvr/verify', nvr.verify);
app.fs.api.logAttr['GET/nvr'] = { content: '获取nvr', visible: false };
router.get('/nvr', nvr.get);
app.fs.api.logAttr['GET/nvr/detail/:nvrId'] = { content: '获取nvr详情', visible: false };
router.get('/nvr/detail/:nvrId', nvr.detail);
app.fs.api.logAttr['DEL/nvr/:nvrId'] = { content: '删除nvr', visible: false };
router.del('/nvr/:nvrId', nvr.del);
app.fs.api.logAttr['GET/nvr/export'] = { content: '导出nvr信息', visible: false };
router.get('/nvr/export', nvr.nvrExport);
};

8
code/VideoAccess-VCMP/api/app/lib/routes/vender/index.js

@ -0,0 +1,8 @@
'use strict';
const vender = require('../../controllers/vender');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/vender'] = { content: '获取设备厂商', visible: false };
router.get('/vender', vender.get);
};

151
code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js

@ -0,0 +1,151 @@
const schedule = require('node-schedule');
const moment = require('moment')
module.exports = function (app, opts) {
const freshYingshiState = app.fs.scheduleInit(
{
// interval: '* * 4 * * *',
interval: '*/10 * * * *',
immediate: false,
},
async () => {
try {
const startTime = moment()
const { models } = app.fs.dc
const { token4yingshi, getYingshiPlayUrl, cameraStatePush } = app.fs.utils
const secretRes = await models.SecretYingshi.findAll()
let deviceList = []
for (let s of secretRes) {
const tokenYingshi = await token4yingshi(s.dataValues)
// 查询所有设备
let pageStart = 0
while (pageStart >= 0) {
const deviceRes = await app.fs.yingshiRequest.post('lapp/device/list', {
query: {
accessToken: tokenYingshi,
pageStart,
pageSize: 50
}
})
if (deviceRes.code == 200) {
deviceList = deviceList.concat.apply(deviceList, deviceRes.data)
for (let d of deviceRes.data) {
const existD = await models.GbCamera.findOne({
where: {
streamid: d.deviceSerial
}
})
let storageD = {
level: 0,
ipctype: 'yingshi',
streamid: d.deviceSerial,
online: d.status ? 'ON' : 'OFF',
name: d.deviceName,
}
if (existD) {
if (existD.online != storageD.online) {
// 状态更新
if (storageD.online == 'ON' && !existD.playUrl) {
const playUrlRes = await getYingshiPlayUrl({ deviceSerial: d.deviceSerial, token: tokenYingshi })
storageD.playUrl = playUrlRes
}
await models.GbCamera.update(storageD, {
where: {
id: existD.id
}
})
// 状态更新 END
// 状态推送
cameraStatePush({
gbId: existD.id,
online: storageD.online,
ipctype: storageD.ipctype,
})
}
} else {
const yingshiRes = await models.GbCamera.create(storageD)
await models.Camera.update({
gbId: yingshiRes.id
}, {
where: {
serialNo: d.deviceSerial
}
})
}
}
if (deviceRes.data.length == 50) {
pageStart++
} else {
pageStart = -1
}
}
}
}
// console.log(deviceList);
console.info(`萤石设备 ${deviceList.length} 状态查询用时 ${moment().diff(startTime, 'seconds')} s`)
} catch (error) {
app.fs.logger.error(`sechedule: freshYingshiState, error: ${error}`);
}
});
const freshYingshiPlayUrl = app.fs.scheduleInit(
{
// interval: '0 0 4 */1 *',
// interval: '*/30 * * * *',
interval: '0 34 5 1 * *',
immediate: true,
},
async () => {
try {
const startTime = moment()
const { models } = app.fs.dc
const { token4yingshi, getYingshiPlayUrl } = app.fs.utils
const secretRes = await models.SecretYingshi.findAll()
for (let s of secretRes) {
const tokenYingshi = await token4yingshi(s.dataValues)
// 查询所有设备
let pageStart = 0
while (pageStart >= 0) {
const deviceRes = await app.fs.yingshiRequest.post('lapp/device/list', {
query: {
accessToken: tokenYingshi,
pageStart,
pageSize: 50
}
})
if (deviceRes.code == 200) {
for (let d of deviceRes.data) {
const playUrlRes = await getYingshiPlayUrl({ deviceSerial: d.deviceSerial, token: tokenYingshi })
await models.GbCamera.update({
playUrl: playUrlRes,
}, {
where: {
streamid: d.deviceSerial
}
})
}
if (deviceRes.data.length == 50) {
pageStart++
} else {
pageStart = -1
}
}
}
}
console.info(`萤石设备播放地址更新查询用时 ${moment().diff(startTime, 'seconds')} s`)
} catch (error) {
app.fs.logger.error(`sechedule: freshYingshiPlayUrl, error: ${error}`);
}
}
)
return {
freshYingshiState,
freshYingshiPlayUrl
}
}

33
code/VideoAccess-VCMP/api/app/lib/schedule/index.js

@ -0,0 +1,33 @@
'use strict';
const fs = require('fs');
const nodeSchedule = require('node-schedule');
// 将定时任务汇集未来可根据需要选取操作
module.exports = async function (app, opts) {
const scheduleInit = ({
interval, immediate
}, callback) => {
const j = nodeSchedule.scheduleJob(interval, callback);
if (immediate && !opts.dev) {
setTimeout(callback, 0)
}
return j;
}
app.fs.scheduleInit = scheduleInit
fs.readdirSync(__dirname).forEach((filename) => {
if (!['index.js'].some(f => filename == f)) {
const scheduleList = require(`./${filename}`)(app, opts)
for (let k of Object.keys(scheduleList)) {
console.info(`定时任务 ${k} 启动`);
}
app.fs.schedule = {
...app.fs.schedule,
...scheduleList,
}
}
});
};

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

@ -0,0 +1,40 @@
'use strict';
const mqtt = require('mqtt');
module.exports = async function factory (app, opts) {
console.info(`mqtt connecting ${opts.mqtt.mqttVideoServer}`);
const client = mqtt.connect(opts.mqtt.mqttVideoServer);
client.on('connect', function () {
console.info(`mqtt connect success ${opts.mqtt.mqttVideoServer}`);
client.subscribe('topic/test', { qos: 0 });//订阅主题为test的消息
})
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.on('message', async (top, message) => {
let msgStr = message.toString();
let msg = JSON.parse(msgStr.replace(/\\/g, ''));
if (msg.id && msg.online) {
const { cameraStatePush } = app.fs.utils
const { models } = app.fs.dc
const gbCameraRes = await models.GbCamera.findOne({
where: {
id: msg.id
}
})
if (gbCameraRes) {
cameraStatePush({
gbId: msg.id,
online: msg.online,
ipctype: gbCameraRes.ipctype,
})
}
}
});
app.mqttVideoServer = client
}

67
code/VideoAccess-VCMP/api/app/lib/service/paasRequest.js

@ -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;

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

@ -0,0 +1,41 @@
'use strict';
// https://github.com/luin/ioredis
const redis = require("ioredis")
module.exports = async function factory (app, opts) {
let client = opts.redis.pwd ?
new redis.Cluster([
{
host: opts.redis.host,
port: opts.redis.port
}
], {
redisOptions: {
password: opts.redis.pwd,
},
})
: new redis(opts.redis.port, opts.redis.host, {
password: opts.redis.pwd,
});
client.on("error", function (err) {
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.info(`redis connect success ${opts.redis.host + ':' + opts.redis.port}`);
})
// 自定义方法
async function hdelall (key) {
const obj = await client.hgetall(key);
await client.hdel(key, Object.keys(obj))
}
app.redis = client
app.redisTools = {
hdelall,
}
}

33
code/VideoAccess-VCMP/api/app/lib/service/socket.js

@ -0,0 +1,33 @@
'use strict';
module.exports = async function factory (app, opts) {
app.socket.on('connection', async (socket) => {
console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已连接:' + socket.id);
socket.on('disconnecting', async (reason) => {
console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已断开连接:' + reason);
})
})
// 使用测试 保持链接
setInterval(async () => {
const { connected } = app.socket.sockets
const roomId = 'ROOM_' + Math.random()
// if (connected) {
// for (let c in connected) {
// connected[c].join(roomId)
// }
// app.socket.to(roomId).emit('TEST', { someProperty: `【星域 ROOM:${roomId}】呼叫自然选择号!!!`, })
// }
// app.socket.emit('TEST', { someProperty: '【广播】呼叫青铜时代号!!!', })
// app.socket.emit('CAMERA_ONLINE', {
// ipctype: 'yingshi',
// online: Math.random() > 0.5 ? 'ON' : 'OFF',
// gbId: Math.floor(Math.random() * 100),
// name: 'cameraName'
// })
}, 3000)
}

171
code/VideoAccess-VCMP/api/app/lib/utils/camera.js

@ -0,0 +1,171 @@
module.exports = function (app, opts) {
async function getGbCameraLevel3ByStreamId ({ streamId }) {
const { models } = app.fs.dc
if (!streamId) {
let errMsg = '参数错误'
throw errMsg
}
const streamIdArr = [streamId]
const findChild = async (streamIdArr) => {
const childRes = await models.GbCamera.findAll({
where: {
parent: { $in: streamIdArr },
}
})
if (!childRes.length || childRes.some(c => c.level == 2)) {
return childRes
} else {
const nextLevelStreamIds = childRes.map(level => level.streamid)
return findChild(nextLevelStreamIds)
}
}
const cameraRes = await findChild(streamIdArr)
return cameraRes
}
async function getGbCameraLevel1ByStreamId ({ streamId, where = {} }) {
const { models } = app.fs.dc
if (!streamId) {
let errMsg = '参数错误'
throw errMsg
}
const findParent = async (streamId) => {
const parentRes = await models.GbCamera.findOne({
where: {
streamid: streamId,
...where
}
})
if (!parentRes || parentRes.level == 0) {
return parentRes
} if (!parentRes.parent) {
return
} else {
const lastLevelStreamId = parentRes.parent
return findParent(lastLevelStreamId)
}
}
const deviceRes = await findParent(streamId)
return deviceRes
}
async function verifyYingshiInfo ({ serialNo } = {}) {
const { varifyYingshiBelongSecretBySerialNo } = app.fs.utils
const beloneSecret = await varifyYingshiBelongSecretBySerialNo(serialNo)
if (!beloneSecret) {
let errMsg = '请联系管理员核验或新增萤石云权限'
throw errMsg
}
return beloneSecret
}
async function verifyIpcInfo ({ serialNo } = {}) {
const { models } = app.fs.dc
const gbCameraRes = await models.GbCamera.findOne({
where: {
streamid: serialNo,
// ipctype: 'ipc'
}
})
if (!gbCameraRes) {
let errMsg = '没有找到已接入的 IPC 服务信息'
throw errMsg
}
return gbCameraRes.dataValues
}
async function verifyCascadeInfo ({ streamId } = {}) {
const { models } = app.fs.dc
const gbCameraRes = await models.GbCamera.findOne({
where: {
streamid: streamId,
level: 0,
ipctype: '级联'
}
})
if (!gbCameraRes) {
let errMsg = '没有找到已接入的级联摄像头服务信息'
throw errMsg
}
return gbCameraRes.dataValues
}
async function getPlayUrl ({ topSerialNo, serialNo }) {
const { cameraPlayHost } = opts
if (!topSerialNo || !serialNo) {
return null
}
return {
liveUrl: {
sd: {
'WS-RAW': `${cameraPlayHost.ws}/jessica/${topSerialNo}/${serialNo}`,
'WS-FLV': `${cameraPlayHost.ws}/jessica/${topSerialNo}/${serialNo}.flv`,
'HTTP-FLV': `${cameraPlayHost.httpFlv}/hdl/${topSerialNo}/${serialNo}.flv`,
'HLS': `${cameraPlayHost.httpFlv}/hls/${topSerialNo}/${serialNo}.m3u8`,
'RTMP': `${cameraPlayHost.rtmp}/${topSerialNo}/${serialNo}`,
'RTSP': `${cameraPlayHost.rtsp}/${topSerialNo}/${serialNo}`,
}
}
}
}
async function cameraStatePush ({ gbId, online, ipctype }) {
try {
const { models } = app.fs.dc
const { connected } = app.socket.sockets
const roomId = 'ROOM_' + Math.random() + '_' + gbId
let cameraName = ''
if (connected) {
// TODO 摄像头绑定关系查询
for (let c in connected) {
const { client: { conn: { request: { _query } } } } = connected[c]
if (_query && _query.token) {
let userInfo = await app.redis.hget(_query.token, 'userInfo');
if (userInfo) {
userInfo = JSON.parse(userInfo)
const corCameraRes = await models.Camera.findOne({
where: {
gbId: gbId,
createUserId: userInfo.id
}
})
// TODO 管理员判断
if (corCameraRes) {
cameraName = corCameraRes.name
connected[c].join(roomId)
}
}
}
}
app.socket.to(roomId).emit('CAMERA_ONLINE', {
ipctype: ipctype,
online: online,
gbId: gbId,
name: cameraName
})
}
} catch (error) {
app.fs.logger.error(`utils: cameraStatePush, error: ${error}`);
}
}
return {
getGbCameraLevel1ByStreamId,
getGbCameraLevel3ByStreamId,
verifyYingshiInfo,
verifyIpcInfo,
verifyCascadeInfo,
getPlayUrl,
cameraStatePush,
}
}

16
code/VideoAccess-VCMP/api/app/lib/utils/index.js

@ -0,0 +1,16 @@
'use strict';
const path = require('path');
const fs = require('fs');
module.exports = async function (app, opts) {
fs.readdirSync(__dirname).forEach((filename) => {
if (!['index.js'].some(f => filename == f)) {
const utils = require(`./${filename}`)(app, opts)
app.fs.utils = {
...app.fs.utils,
...utils,
}
}
});
};

154
code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js

@ -0,0 +1,154 @@
'use strict';
const moment = require('moment')
module.exports = function (app, opts) {
async function token4yingshi ({ key, secret, token, expire } = {}) {
const { models } = app.fs.dc
if (!key || !secret) {
throw '参数 { key, secret } 缺一不可'
}
if (token && expire && moment().isBefore(moment(expire))) {
return token
} else {
const secretRes = await models.SecretYingshi.findOne({
where: { key, secret }
})
if (secretRes && secretRes.expire && secretRes.token && moment().isBefore(moment(secretRes.expire))) {
return secretRes.token
}
}
// 也可以做基于 redis 的缓存
const tokenRes = await app.fs.yingshiRequest.post(`lapp/token/get`, {
query: {
appKey: key,
appSecret: secret
}
})
if (tokenRes.code == 200) {
const { accessToken, expireTime } = tokenRes.data
await models.SecretYingshi.update({
token: accessToken,
expire: expireTime
}, {
where: {
key, secret
}
})
return accessToken
} else {
throw tokenRes
}
}
async function varifyYingshiBelongSecretBySerialNo (serialNo) {
const { models } = app.fs.dc
const serialNo_ = String(serialNo).toUpperCase()
const secretRes = await models.SecretYingshi.findAll()
let beloneSecret = null
for (let s of secretRes) {
const tokenYingshi = await token4yingshi(s.dataValues)
// 检测设备所属
const cameraState = await app.fs.yingshiRequest.post('lapp/device/info', {
query: {
accessToken: tokenYingshi,
deviceSerial: serialNo_
}
})
if (cameraState.code == 200) {
beloneSecret = {
...s.dataValues,
token: tokenYingshi
}
break
}
}
return beloneSecret
}
const getYingshiPlayUrl = async ({ deviceSerial, token }) => {
const protocolMap = {
ezopen: 1,
hls: 2,
rtmp: 3,
flv: 4,
}
const qualityMap = {
hd: 1,
sd: 2,
}
const typeMap = {
// live: 1,
local: 2,
cloud: 3
}
let playUrl = {
liveUrl: {// 直播
hd: {// 高清
rtmp: '',
hls: '',
flv: '',
ezopen: '',
},
sd: {// 标清
rtmp: '',
hls: '',
flv: '',
ezopen: '',
}
},
replayUrl: {// 回放
cloud: '',
local: '',
}
}
for (let protocol in protocolMap) {
for (let quality in qualityMap) {
const playUrlRes = await app.fs.yingshiRequest.post('lapp/v2/live/address/get', {
query: {
accessToken: token,
deviceSerial: deviceSerial,
protocol: protocolMap[protocol],
quality: qualityMap[quality],
}
})
if (playUrlRes.code == 200) {
playUrl.liveUrl[quality][protocol] = playUrlRes.data.url
} else {
// return null
}
}
}
for (let type in typeMap) {
try {
const playUrlRes = await app.fs.yingshiRequest.post('lapp/v2/live/address/get', {
query: {
accessToken: token,
deviceSerial: deviceSerial,
type: typeMap[type],
}
})
if (playUrlRes.code == 200) {
playUrl.replayUrl[type] = playUrlRes.data.url
} else {
// return null
}
} catch (error) {
app.fs.logger.error(`sechedule: freshYingshiPlayUrl, error: ${error}`);
}
}
return playUrl
}
return {
token4yingshi,
varifyYingshiBelongSecretBySerialNo,
getYingshiPlayUrl,
}
}

82
code/VideoAccess-VCMP/api/app/lib/utils/xlsxDownload.js

@ -0,0 +1,82 @@
'use strict';
const fs = require('fs');
const xlsx = require('better-xlsx');
const path = require('path')
const moment = require('moment')
module.exports = function (app, opts) {
//递归创建目录 同步方法
async function makeDir (dir) {
if (!fs.existsSync(dir)) {
makeDir(path.dirname(dir))
fs.mkdirSync(dir, function (err) {
if (err) {
throw err
}
});
}
}
async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss') } = {}) {
const fileDirPath = path.join(__dirname, `../../downloadFiles`)
makeDir(fileDirPath)
const file = new xlsx.File();
const sheet_1 = file.addSheet('sheet_1');
// header
const headerStyle = new xlsx.Style();
headerStyle.align.h = 'center';
headerStyle.align.v = 'center';
headerStyle.border.right = 'thin';
headerStyle.border.rightColor = '#000000';
headerStyle.border.bottom = 'thin';
headerStyle.border.bottomColor = '#000000';
const headerRow = sheet_1.addRow();
const indexCell = headerRow.addCell();
indexCell.value = '序号'
indexCell.style = headerStyle
for (let h of header) {
const cell = headerRow.addCell();
cell.value = h.title;
cell.style = headerStyle
}
// data
const style = new xlsx.Style();
style.align.h = 'left';
style.align.v = 'center';
style.border.right = 'thin';
style.border.rightColor = '#000000';
style.border.bottom = 'thin';
style.border.bottomColor = '#000000';
for (let i = 0; i < data.length; i++) {
const row = sheet_1.addRow();
const indexCell = row.addCell();
indexCell.value = i + 1
indexCell.style = headerStyle
for (let h of header) {
const cell = row.addCell();
cell.value = data[i][h.key];
cell.style = style
}
}
const savePath = path.join(fileDirPath, fileName)
await new Promise(function (resolve, reject) {
file.saveAs()
.pipe(fs.createWriteStream(savePath))
.on('finish', () => {
resolve()
});
})
return savePath
}
return {
simpleExcelDown,
makeDir
}
}

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

@ -12,92 +12,180 @@ args.option(['p', 'port'], '启动端口');
args.option(['g', 'pg'], 'postgre服务URL'); args.option(['g', 'pg'], 'postgre服务URL');
args.option(['f', 'fileHost'], '文件中心本地化存储: WebApi 服务器地址(必填), 该服务器提供文件上传Web服务'); args.option(['f', 'fileHost'], '文件中心本地化存储: WebApi 服务器地址(必填), 该服务器提供文件上传Web服务');
args.option('redisHost', 'redisHost');
args.option('redisPort', 'redisPort');
args.option('redisPswd', 'redisPassword');
args.option('axyApiUrl', '安心云 api');
args.option('iotAuthApi', 'IOT 鉴权 api');
args.option('godUrl', '高德地图API请求地址');
args.option('godKey', '高德地图API key');
args.option('iotVideoServerUrl', '视频后端服务地址');
args.option('mqttVideoServer', '视频后台 mqtt 服务 URL');
args.option('cameraPlayWsHost', '视频播放地址 ws://xxx:xxx');
args.option('cameraPlayHttpFlvHost', '视频播放地址 httpFlv');
args.option('cameraPlayHlsHost', '视频播放地址 hls');
args.option('cameraPlayRtmpHost', '视频播放地址 rtmp');
args.option('cameraPlayRtspHost', '视频播放地址 rtsp');
const flags = args.parse(process.argv); const flags = args.parse(process.argv);
const IOT_VIDEO_ACCESS_DB = process.env.IOT_VIDEO_ACCESS_DB || flags.pg; const IOT_VIDEO_ACCESS_DB = process.env.IOT_VIDEO_ACCESS_DB || flags.pg;
const IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN = process.env.IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || flags.fileHost; const IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN = process.env.IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || flags.fileHost;
if (!IOT_VIDEO_ACCESS_DB) { const IOTA_REDIS_SERVER_HOST = process.env.IOTA_REDIS_SERVER_HOST || flags.redisHost || "localhost";//redis IP
console.log('缺少启动参数,异常退出'); const IOTA_REDIS_SERVER_PORT = process.env.IOTA_REDIS_SERVER_PORT || flags.redisPort || "6379";//redis 端口
args.showHelp(); const IOTA_REDIS_SERVER_PWD = process.env.IOTA_REDIS_SERVER_PWD || flags.redisPswd || "";//redis 密码
process.exit(-1);
const IOT_AUTH_API = process.env.IOT_AUTH_API || flags.iotAuthApi;
const AXY_API_URL = process.env.AXY_API_URL || flags.axyApiUrl;
const GOD_URL = process.env.GOD_URL || flags.godUrl || 'https://restapi.amap.com/v3';
const GOD_KEY = process.env.GOD_KEY || flags.godKey;
const YINGSHI_URL = process.env.YINGSHI_URL || flags.yingshiUrl || 'https://open.ys7.com/api';
const MQTT_VIDEO_SERVER = process.env.MQTT_VIDEO_SERVER || flags.mqttVideoServer;
const IOT_VIDEO_SERVER_URL = process.env.IOT_VIDEO_SERVER_URL || flags.iotVideoServerUrl
const CAMERA_PLAY_WS_HOST = process.env.CAMERA_PLAY_WS_HOST || flags.cameraPlayWsHost;
const CAMERA_PLAY_HTTP_FLV_HOST = process.env.CAMERA_PLAY_HTTP_FLV_HOST || flags.cameraPlayHttpFlvHost;
const CAMERA_PLAY_HLS_HOST = process.env.CAMERA_PLAY_HLS_HOST || flags.cameraPlayHlsHost;
const CAMERA_PLAY_RTMP_HOST = process.env.CAMERA_PLAY_RTMP_HOST || flags.cameraPlayRtmpHost;
const CAMERA_PLAY_RTSP_HOST = process.env.CAMERA_PLAY_RTSP_HOST || flags.cameraPlayRtspHost;
if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY || !MQTT_VIDEO_SERVER ||
!AXY_API_URL || !IOT_VIDEO_SERVER_URL || !IOT_AUTH_API ||
!CAMERA_PLAY_WS_HOST || !CAMERA_PLAY_HTTP_FLV_HOST || !CAMERA_PLAY_HLS_HOST || !CAMERA_PLAY_RTMP_HOST || !CAMERA_PLAY_RTSP_HOST
) {
console.log('缺少启动参数,异常退出');
args.showHelp();
process.exit(-1);
} }
const product = { const product = {
port: flags.port || 8080, port: flags.port || 8080,
staticDirs: ['static'], staticDirs: ['static'],
mws: [ mws: [
{ {
entry: require('@fs/attachment').entry, entry: require('@fs/attachment').entry,
opts: { opts: {
local: { local: {
origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`, origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`,
rootPath: 'static', rootPath: 'static',
childPath: 'upload', childPath: 'upload',
}, },
maxSize: 104857600, // 100M maxSize: 104857600, // 100M
} }
}, { }, {
entry: require('./app').entry, entry: require('./app').entry,
opts: { opts: {
exclude: [], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 dev,
} exclude: [
} { p: '/camera', o: 'GET' }, // 暂时滴
], ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
dc: { redis: {
url: IOT_VIDEO_ACCESS_DB, host: IOTA_REDIS_SERVER_HOST,
opts: { port: IOTA_REDIS_SERVER_PORT,
pool: { pwd: IOTA_REDIS_SERVER_PWD
max: 80, },
min: 10, mqtt: {
idle: 10000 mqttVideoServer: MQTT_VIDEO_SERVER,
}, },
define: { cameraPlayHost: {
freezeTableName: true, // 固定表名 ws: CAMERA_PLAY_WS_HOST,
timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt" httpFlv: CAMERA_PLAY_HTTP_FLV_HOST,
hls: CAMERA_PLAY_HLS_HOST,
rtmp: CAMERA_PLAY_RTMP_HOST,
rtsp: CAMERA_PLAY_RTSP_HOST,
}, },
timezone: '+08:00', pssaRequest: [
logging: false {// name 会作为一个 request 出现在 ctx.app.fs
}, name: 'authRequest',
models: [require('./app').models] root: IOT_AUTH_API
}, }, {
logger: { name: 'axyRequest',
level: 'info', root: AXY_API_URL
json: false, }, {
filename: path.join(__dirname, 'log', 'runtime.log'), name: 'godRequest',
colorize: false, root: GOD_URL,
maxsize: 1024 * 1024 * 5, params: {
rotationFormat: false, query: {
zippedArchive: true, key: GOD_KEY
maxFiles: 10, }
prettyPrint: true, }
label: '', }, {
timestamp: () => moment().format('YYYY-MM-DD HH:mm:ss.SSS'), name: 'yingshiRequest',
eol: os.EOL, root: YINGSHI_URL,
tailable: true, params: {
depth: null, query: {
showLevel: true, key: GOD_KEY
maxRetries: 1 }
} }
}, {
name: 'videoServerRequest',
root: IOT_VIDEO_SERVER_URL + '/api',
dataWord: 'text'
},
]
}
}
],
dc: {
url: IOT_VIDEO_ACCESS_DB,
opts: {
pool: {
max: 80,
min: 10,
idle: 10000
},
define: {
freezeTableName: true, // 固定表名
timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt"
},
timezone: '+08:00',
logging: false
},
models: [require('./app').models]
},
logger: {
level: 'info',
json: false,
filename: path.join(__dirname, 'log', 'runtime.log'),
colorize: false,
maxsize: 1024 * 1024 * 5,
rotationFormat: false,
zippedArchive: true,
maxFiles: 10,
prettyPrint: true,
label: '',
timestamp: () => moment().format('YYYY-MM-DD HH:mm:ss.SSS'),
eol: os.EOL,
tailable: true,
depth: null,
showLevel: true,
maxRetries: 1
}
}; };
const development = { const development = {
port: product.port, port: product.port,
staticDirs: product.staticDirs, staticDirs: product.staticDirs,
mws: product.mws, mws: product.mws,
dc: product.dc, dc: product.dc,
logger: product.logger logger: product.logger
}; };
if (dev) { if (dev) {
// mws // mws
for (let mw of development.mws) { for (let mw of development.mws) {
// if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由 // if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由
} }
// logger // logger
development.logger.filename = path.join(__dirname, 'log', 'development.log'); development.logger.filename = path.join(__dirname, 'log', 'development.log');
development.logger.level = 'debug'; development.logger.level = 'debug';
development.dc.opts.logging = console.log; development.dc.opts.logging = console.log;
} }
module.exports = dev ? development : product; module.exports = dev ? development : product;

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

@ -5,7 +5,7 @@
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
"test": "set DEBUG=true&&\"node_modules/.bin/mocha\" --harmony --reporter spec app/test/*.test.js", "test": "set DEBUG=true&&\"node_modules/.bin/mocha\" --harmony --reporter spec app/test/*.test.js",
"start": "set NODE_ENV=development&&node server -p 14000 -g postgres://postgres:123@10.8.30.32:5432/yinjiguanli -f http://localhost:14000", "start": "set NODE_ENV=development&&node server -p 4000 -g postgres://postgres:123@10.8.30.32:5432/video_access -f http://localhost:4000",
"start:linux": "export NODE_ENV=development&&node server -p 4000 -g postgres://FashionAdmin:123456@10.8.30.39:5432/pm1", "start:linux": "export NODE_ENV=development&&node server -p 4000 -g postgres://FashionAdmin:123456@10.8.30.39:5432/pm1",
"automate": "sequelize-automate -c sequelize-automate.config.js" "automate": "sequelize-automate -c sequelize-automate.config.js"
}, },
@ -15,13 +15,16 @@
"dependencies": { "dependencies": {
"@fs/attachment": "^1.0.0", "@fs/attachment": "^1.0.0",
"args": "^3.0.7", "args": "^3.0.7",
"better-xlsx": "^0.7.6",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
"file-saver": "^2.0.2", "file-saver": "^2.0.2",
"fs-web-server-scaffold": "^2.0.2", "fs-web-server-scaffold": "^2.0.2",
"ioredis": "^4.19.4", "ioredis": "^5.0.4",
"koa-convert": "^1.2.0", "koa-convert": "^1.2.0",
"koa-proxy": "^0.9.0", "koa-proxy": "^0.9.0",
"moment": "^2.24.0", "moment": "^2.24.0",
"mqtt": "^4.3.7",
"node-schedule": "^2.1.0",
"path": "^0.12.7", "path": "^0.12.7",
"path-to-regexp": "^3.0.0", "path-to-regexp": "^3.0.0",
"pg": "^7.9.0", "pg": "^7.9.0",

66
code/VideoAccess-VCMP/api/sequelize-automate.config.js

@ -1,35 +1,35 @@
module.exports = { module.exports = {
// 数据库配置 与 sequelize 相同 // 数据库配置 与 sequelize 相同
dbOptions: { dbOptions: {
database: 'yinjiguanli', database: 'video_access',
username: 'postgres', username: 'postgres',
password: '123', password: '123',
dialect: 'postgres', dialect: 'postgres',
host: '10.8.30.32', host: '10.8.30.32',
port: 5432, port: 5432,
define: { define: {
underscored: false, underscored: false,
freezeTableName: false, freezeTableName: false,
charset: 'utf8mb4', charset: 'utf8mb4',
timezone: '+00: 00', timezone: '+00: 00',
dialectOptions: { dialectOptions: {
collate: 'utf8_general_ci', collate: 'utf8_general_ci',
}, },
timestamps: false, timestamps: false,
}, },
}, },
options: { options: {
type: 'freesun', // 指定 models 代码风格 type: 'freesun', // 指定 models 代码风格
camelCase: true, // Models 文件中代码是否使用驼峰命名 camelCase: true, // Models 文件中代码是否使用驼峰命名
modalNameSuffix: false, // 模型名称是否带 ‘Model’ 后缀 modalNameSuffix: false, // 模型名称是否带 ‘Model’ 后缀
fileNameCamelCase: false, // Model 文件名是否使用驼峰法命名,默认文件名会使用表名,如 `user_post.js`;如果为 true,则文件名为 `userPost.js` fileNameCamelCase: false, // Model 文件名是否使用驼峰法命名,默认文件名会使用表名,如 `user_post.js`;如果为 true,则文件名为 `userPost.js`
dir: './app/lib/models', // 指定输出 models 文件的目录 dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义 typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir` emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: ['user_placeSecurityRecord', 'places'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 tables: ['camera_remark'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: ['user'], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性 skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中 tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面 ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面
attrLength: false, // 在生成模型的字段中 是否生成 如 var(128)这种格式,公司一般使用 String ,则配置为 false attrLength: false, // 在生成模型的字段中 是否生成 如 var(128)这种格式,公司一般使用 String ,则配置为 false
}, },
} }

15
code/VideoAccess-VCMP/api/utils/forward-api.js

@ -1,15 +0,0 @@
'use strict';
const proxy = require('koa-proxy');
const convert = require('koa-convert');
module.exports = {
entry: function (app, router, opts) {
app.use(convert(proxy({
host: opts.host,
match: opts.match,
map: function (path) {
return path.replace(opts.match, '');
}
})));
}
};

543
code/VideoAccess-VCMP/script/0.0.1/0_init_db.sql

@ -0,0 +1,543 @@
/*
Navicat Premium Data Transfer
Source Server : 10.8.30.32
Source Server Type : PostgreSQL
Source Server Version : 90515
Source Host : 10.8.30.32:5432
Source Catalog : video_access
Source Schema : public
Target Server Type : PostgreSQL
Target Server Version : 90515
File Encoding : 65001
Date: 06/07/2022 11:45:25
*/
-- ----------------------------
-- Sequence structure for camera_ability_bind_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."camera_ability_bind_id_seq";
CREATE SEQUENCE "public"."camera_ability_bind_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for camera_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."camera_id_seq";
CREATE SEQUENCE "public"."camera_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for camera_remark_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."camera_remark_id_seq";
CREATE SEQUENCE "public"."camera_remark_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for gbCamera_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."gbCamera_id_seq";
CREATE SEQUENCE "public"."gbCamera_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for gb_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."gb_id_seq";
CREATE SEQUENCE "public"."gb_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for nvr_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."nvr_id_seq";
CREATE SEQUENCE "public"."nvr_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for secret_yingshi_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."secret_yingshi_id_seq";
CREATE SEQUENCE "public"."secret_yingshi_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for t_upload_comm_http_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."t_upload_comm_http_id_seq";
CREATE SEQUENCE "public"."t_upload_comm_http_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Sequence structure for vender_id_seq
-- ----------------------------
DROP SEQUENCE IF EXISTS "public"."vender_id_seq";
CREATE SEQUENCE "public"."vender_id_seq"
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- ----------------------------
-- Table structure for ax_project
-- ----------------------------
DROP TABLE IF EXISTS "public"."ax_project";
CREATE TABLE "public"."ax_project" (
"id" int4 NOT NULL,
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL
)
;
COMMENT ON TABLE "public"."ax_project" IS '安心云项目副表,主要用于和camera等进行联合查询
';
-- ----------------------------
-- Records of ax_project
-- ----------------------------
INSERT INTO "public"."ax_project" VALUES (1, '安心云项目');
-- ----------------------------
-- Table structure for camera
-- ----------------------------
DROP TABLE IF EXISTS "public"."camera";
CREATE TABLE "public"."camera" (
"id" int4 NOT NULL DEFAULT nextval('camera_id_seq'::regclass),
"type" varchar(16) COLLATE "pg_catalog"."default" NOT NULL,
"name" varchar(128) COLLATE "pg_catalog"."default",
"channel_name" varchar(64) COLLATE "pg_catalog"."default",
"external_domain" varchar(64) COLLATE "pg_catalog"."default",
"rtmp" varchar(1024) COLLATE "pg_catalog"."default",
"serial_no" varchar(128) COLLATE "pg_catalog"."default",
"cloud_control" bool,
"high_definition" bool,
"voice" bool,
"memory_card" varchar(32) COLLATE "pg_catalog"."default",
"vender_id" int4,
"cascade_type" varchar(32) COLLATE "pg_catalog"."default",
"sip" varchar(1024) COLLATE "pg_catalog"."default",
"longitude" numeric(16,12),
"latitude" numeric(16,12),
"forbidden" bool NOT NULL DEFAULT false,
"create_time" timestamptz(6) NOT NULL,
"recycle_time" timestamptz(6),
"delete" bool NOT NULL DEFAULT false,
"create_user_id" int4 NOT NULL,
"nvr_id" int4,
"model" varchar(128) COLLATE "pg_catalog"."default",
"kind_id" int4,
"yingshi_secret_id" int4,
"gb_id" int4,
"top_serial_no" varchar(128) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "public"."camera"."type" IS '设备类型:yingshi - 萤石;nvr - NVR摄像头;ipc - IPC 网络摄像头;cascade - 级联摄像头';
COMMENT ON COLUMN "public"."camera"."name" IS '设备名称/安装位置';
COMMENT ON COLUMN "public"."camera"."channel_name" IS '通道名称';
COMMENT ON COLUMN "public"."camera"."external_domain" IS '外域名称';
COMMENT ON COLUMN "public"."camera"."serial_no" IS '设备编号';
COMMENT ON COLUMN "public"."camera"."cloud_control" IS '云台控制';
COMMENT ON COLUMN "public"."camera"."high_definition" IS '高清支持';
COMMENT ON COLUMN "public"."camera"."voice" IS '语音对讲支持';
COMMENT ON COLUMN "public"."camera"."memory_card" IS '内存卡容量';
COMMENT ON COLUMN "public"."camera"."vender_id" IS '设备厂商id';
COMMENT ON COLUMN "public"."camera"."cascade_type" IS '级联方式:up - 上级联;down - 下级联';
COMMENT ON COLUMN "public"."camera"."longitude" IS '经度';
COMMENT ON COLUMN "public"."camera"."latitude" IS '维度';
COMMENT ON COLUMN "public"."camera"."forbidden" IS '是否禁用';
COMMENT ON COLUMN "public"."camera"."recycle_time" IS '放入回收站时间';
COMMENT ON COLUMN "public"."camera"."delete" IS '是否彻底删除';
COMMENT ON COLUMN "public"."camera"."model" IS '型号';
COMMENT ON COLUMN "public"."camera"."top_serial_no" IS 'gb设备 level=0 的 steamid ';
-- ----------------------------
-- Table structure for camera_ability
-- ----------------------------
DROP TABLE IF EXISTS "public"."camera_ability";
CREATE TABLE "public"."camera_ability" (
"id" int4 NOT NULL,
"ability" varchar(64) COLLATE "pg_catalog"."default" NOT NULL
)
;
COMMENT ON TABLE "public"."camera_ability" IS '摄像机能力';
-- ----------------------------
-- Records of camera_ability
-- ----------------------------
INSERT INTO "public"."camera_ability" VALUES (1, '普通摄像头');
INSERT INTO "public"."camera_ability" VALUES (2, '人流量计数');
INSERT INTO "public"."camera_ability" VALUES (3, '热成像');
INSERT INTO "public"."camera_ability" VALUES (4, 'AI摄像头');
INSERT INTO "public"."camera_ability" VALUES (1314, '其他');
-- ----------------------------
-- Table structure for camera_ability_bind
-- ----------------------------
DROP TABLE IF EXISTS "public"."camera_ability_bind";
CREATE TABLE "public"."camera_ability_bind" (
"id" int4 NOT NULL DEFAULT nextval('camera_ability_bind_id_seq'::regclass),
"camera_id" int4 NOT NULL,
"ability_id" int4 NOT NULL
)
;
-- ----------------------------
-- Table structure for camera_kind
-- ----------------------------
DROP TABLE IF EXISTS "public"."camera_kind";
CREATE TABLE "public"."camera_kind" (
"id" int4 NOT NULL,
"kind" varchar(64) COLLATE "pg_catalog"."default" NOT NULL
)
;
COMMENT ON TABLE "public"."camera_kind" IS '摄像机类型';
-- ----------------------------
-- Records of camera_kind
-- ----------------------------
INSERT INTO "public"."camera_kind" VALUES (1, '枪机');
INSERT INTO "public"."camera_kind" VALUES (2, '球机');
INSERT INTO "public"."camera_kind" VALUES (1314, '其他');
-- ----------------------------
-- Table structure for camera_remark
-- ----------------------------
DROP TABLE IF EXISTS "public"."camera_remark";
CREATE TABLE "public"."camera_remark" (
"id" int4 NOT NULL DEFAULT nextval('camera_remark_id_seq'::regclass),
"camera_id" int4 NOT NULL,
"remark" varchar(256) COLLATE "pg_catalog"."default" NOT NULL
)
;
-- ----------------------------
-- Table structure for gbCamera
-- ----------------------------
DROP TABLE IF EXISTS "public"."gbCamera";
CREATE TABLE "public"."gbCamera" (
"id" int4 NOT NULL DEFAULT nextval('gb_id_seq'::regclass),
"level" int4,
"parent" varchar(32) COLLATE "pg_catalog"."default",
"streamid" varchar(255) COLLATE "pg_catalog"."default",
"online" varchar(255) COLLATE "pg_catalog"."default",
"manufactuer" varchar(255) COLLATE "pg_catalog"."default",
"model" varchar(255) COLLATE "pg_catalog"."default",
"civilCode" varchar(255) COLLATE "pg_catalog"."default",
"adddress" varchar(255) COLLATE "pg_catalog"."default",
"name" varchar(255) COLLATE "pg_catalog"."default",
"Addr" varchar(255) COLLATE "pg_catalog"."default",
"Sipip" varchar(255) COLLATE "pg_catalog"."default",
"ipctype" varchar(255) COLLATE "pg_catalog"."default",
"registerTime" varchar(255) COLLATE "pg_catalog"."default" DEFAULT ''::character varying,
"updateTime" varchar(255) COLLATE "pg_catalog"."default",
"playUrl" jsonb
)
;
COMMENT ON COLUMN "public"."gbCamera"."playUrl" IS '播放地址集合';
-- ----------------------------
-- Table structure for nvr
-- ----------------------------
DROP TABLE IF EXISTS "public"."nvr";
CREATE TABLE "public"."nvr" (
"id" int4 NOT NULL DEFAULT nextval('nvr_id_seq'::regclass),
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"vender_id" int4,
"serial_no" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"region_code" varchar(64) COLLATE "pg_catalog"."default",
"longitude" numeric(16,12) NOT NULL,
"latitude" numeric(16,12) NOT NULL,
"create_time" timestamptz(6) NOT NULL DEFAULT now(),
"channel_count" int4,
"port" varchar(32) COLLATE "pg_catalog"."default",
"delete" bool NOT NULL DEFAULT false,
"create_user_id" int4 NOT NULL
)
;
COMMENT ON COLUMN "public"."nvr"."vender_id" IS '设备厂家id';
COMMENT ON COLUMN "public"."nvr"."serial_no" IS '设备编号';
COMMENT ON COLUMN "public"."nvr"."region_code" IS '行政区码';
COMMENT ON COLUMN "public"."nvr"."create_time" IS '创建时间';
COMMENT ON COLUMN "public"."nvr"."channel_count" IS '通道数';
COMMENT ON COLUMN "public"."nvr"."port" IS '端口';
-- ----------------------------
-- Table structure for secret_yingshi
-- ----------------------------
DROP TABLE IF EXISTS "public"."secret_yingshi";
CREATE TABLE "public"."secret_yingshi" (
"id" int4 NOT NULL DEFAULT nextval('secret_yingshi_id_seq'::regclass),
"key" varchar(512) COLLATE "pg_catalog"."default" NOT NULL,
"secret" varchar(512) COLLATE "pg_catalog"."default" NOT NULL,
"token" varchar(512) COLLATE "pg_catalog"."default",
"expire" varchar(512) COLLATE "pg_catalog"."default"
)
;
-- ----------------------------
-- Records of secret_yingshi
-- ----------------------------
INSERT INTO "public"."secret_yingshi" VALUES (2, '3ea2b502f6804d64b43e4cb3d135665c', '331c85c5b7ce76179f6eb7dccb8aeb27', 'at.culo424j9drz8atx9uikeq5e2mzkhnhx-490csubqrh-1o3hcaz-szuvfax6f', '1657681218109');
INSERT INTO "public"."secret_yingshi" VALUES (3, 'd0704fb9d5d14a6682c1c1d592c12512', '93d023269495b86be62cdfdcf34a6cd1', 'at.1y2mk5fh2myswbkp017pmvdi0v1zbdrw-5j39z78wsp-0x4vi2j-a3mxjlt32', '1657683606281');
INSERT INTO "public"."secret_yingshi" VALUES (1, '5d16a667e1c2423d9d0d634f781810b4', '0cc4e1ec4e6a53ea3dabeb09cd5f468b', 'at.9gq3xwwbazkk33y177ucqtk936bmd0sz-41x4xf24sh-1cn7x82-4lf7davve', '1657681803201');
-- ----------------------------
-- Table structure for t_upload_comm_http
-- ----------------------------
DROP TABLE IF EXISTS "public"."t_upload_comm_http";
CREATE TABLE "public"."t_upload_comm_http" (
"id" int4 NOT NULL DEFAULT nextval('t_upload_comm_http_id_seq'::regclass),
"content" json NOT NULL,
"enable" bool NOT NULL DEFAULT true,
"description" varchar(255) COLLATE "pg_catalog"."default"
)
;
-- ----------------------------
-- Table structure for vender
-- ----------------------------
DROP TABLE IF EXISTS "public"."vender";
CREATE TABLE "public"."vender" (
"id" int4 NOT NULL DEFAULT nextval('vender_id_seq'::regclass),
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL
)
;
COMMENT ON TABLE "public"."vender" IS '设备厂商';
-- ----------------------------
-- Records of vender
-- ----------------------------
INSERT INTO "public"."vender" VALUES (2, '海康威视');
INSERT INTO "public"."vender" VALUES (3, '大华');
INSERT INTO "public"."vender" VALUES (1, '飞尚科技');
INSERT INTO "public"."vender" VALUES (1314, '其他');
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
ALTER SEQUENCE "public"."camera_ability_bind_id_seq"
OWNED BY "public"."camera_ability_bind"."id";
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
ALTER SEQUENCE "public"."camera_id_seq"
OWNED BY "public"."camera"."id";
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
ALTER SEQUENCE "public"."camera_remark_id_seq"
OWNED BY "public"."camera_remark"."id";
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
SELECT setval('"public"."gbCamera_id_seq"', 2, false);
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
ALTER SEQUENCE "public"."nvr_id_seq"
OWNED BY "public"."nvr"."id";
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
ALTER SEQUENCE "public"."secret_yingshi_id_seq"
OWNED BY "public"."secret_yingshi"."id";
SELECT setval('"public"."secret_yingshi_id_seq"', 4, true);
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
SELECT setval('"public"."t_upload_comm_http_id_seq"', 2, false);
-- ----------------------------
-- Alter sequences owned by
-- ----------------------------
ALTER SEQUENCE "public"."vender_id_seq"
OWNED BY "public"."vender"."id";
SELECT setval('"public"."vender_id_seq"', 4, true);
-- ----------------------------
-- Indexes structure for table ax_project
-- ----------------------------
CREATE UNIQUE INDEX "ax_project_id_uindex" ON "public"."ax_project" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table ax_project
-- ----------------------------
ALTER TABLE "public"."ax_project" ADD CONSTRAINT "ax_project_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table camera
-- ----------------------------
CREATE UNIQUE INDEX "camera_id_uindex" ON "public"."camera" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table camera
-- ----------------------------
ALTER TABLE "public"."camera" ADD CONSTRAINT "camera_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table camera_ability
-- ----------------------------
CREATE UNIQUE INDEX "camera_ability_id_uindex" ON "public"."camera_ability" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table camera_ability
-- ----------------------------
ALTER TABLE "public"."camera_ability" ADD CONSTRAINT "camera_ability_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table camera_ability_bind
-- ----------------------------
CREATE UNIQUE INDEX "camera_ability_bind_id_uindex" ON "public"."camera_ability_bind" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table camera_ability_bind
-- ----------------------------
ALTER TABLE "public"."camera_ability_bind" ADD CONSTRAINT "camera_ability_bind_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table camera_kind
-- ----------------------------
CREATE UNIQUE INDEX "camera_kind_id_uindex" ON "public"."camera_kind" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table camera_kind
-- ----------------------------
ALTER TABLE "public"."camera_kind" ADD CONSTRAINT "camera_kind_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table camera_remark
-- ----------------------------
CREATE UNIQUE INDEX "camera_remark_id_uindex" ON "public"."camera_remark" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table camera_remark
-- ----------------------------
ALTER TABLE "public"."camera_remark" ADD CONSTRAINT "camera_remark_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Primary Key structure for table gbCamera
-- ----------------------------
ALTER TABLE "public"."gbCamera" ADD CONSTRAINT "gbCamera1_copy1_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table nvr
-- ----------------------------
CREATE UNIQUE INDEX "nvr_id_uindex" ON "public"."nvr" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table nvr
-- ----------------------------
ALTER TABLE "public"."nvr" ADD CONSTRAINT "nvr_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table secret_yingshi
-- ----------------------------
CREATE UNIQUE INDEX "secret_yingshi_id_uindex" ON "public"."secret_yingshi" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table secret_yingshi
-- ----------------------------
ALTER TABLE "public"."secret_yingshi" ADD CONSTRAINT "secret_yingshi_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Primary Key structure for table t_upload_comm_http
-- ----------------------------
ALTER TABLE "public"."t_upload_comm_http" ADD CONSTRAINT "t_upload_comm_http_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table vender
-- ----------------------------
CREATE UNIQUE INDEX "vender_id_uindex" ON "public"."vender" USING btree (
"id" "pg_catalog"."int4_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table vender
-- ----------------------------
ALTER TABLE "public"."vender" ADD CONSTRAINT "vender_pk" PRIMARY KEY ("id");
-- ----------------------------
-- Foreign Keys structure for table camera
-- ----------------------------
ALTER TABLE "public"."camera" ADD CONSTRAINT "camera_camera_kind_id_fk" FOREIGN KEY ("kind_id") REFERENCES "public"."camera_kind" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "public"."camera" ADD CONSTRAINT "camera_nvr_id_fk" FOREIGN KEY ("nvr_id") REFERENCES "public"."nvr" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "public"."camera" ADD CONSTRAINT "camera_secret_yingshi_id_fk" FOREIGN KEY ("yingshi_secret_id") REFERENCES "public"."secret_yingshi" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "public"."camera" ADD CONSTRAINT "camera_vender_id_fk" FOREIGN KEY ("vender_id") REFERENCES "public"."vender" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
-- ----------------------------
-- Foreign Keys structure for table camera_ability_bind
-- ----------------------------
ALTER TABLE "public"."camera_ability_bind" ADD CONSTRAINT "camera_ability_bind_camera_ability_id_fk" FOREIGN KEY ("ability_id") REFERENCES "public"."camera_ability" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "public"."camera_ability_bind" ADD CONSTRAINT "camera_ability_bind_camera_id_fk" FOREIGN KEY ("camera_id") REFERENCES "public"."camera" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
-- ----------------------------
-- Foreign Keys structure for table camera_remark
-- ----------------------------
ALTER TABLE "public"."camera_remark" ADD CONSTRAINT "camera_remark_camera_id_fk" FOREIGN KEY ("camera_id") REFERENCES "public"."camera" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
-- ----------------------------
-- Foreign Keys structure for table nvr
-- ----------------------------
ALTER TABLE "public"."nvr" ADD CONSTRAINT "nvr_vender_id_fk" FOREIGN KEY ("vender_id") REFERENCES "public"."vender" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;

14
code/VideoAccess-VCMP/script/1.1.0/1.camera_remark.sql

@ -0,0 +1,14 @@
create table if not exists camera_remark
(
id serial not null,
camera_id integer not null,
remark varchar(256) not null,
constraint camera_remark_pk
primary key (id),
constraint camera_remark_camera_id_fk
foreign key (camera_id) references camera
);
create unique index if not exists camera_remark_id_uindex
on camera_remark (id);

5
code/VideoAccess-VCMP/web/.vscode/extensions.json

@ -0,0 +1,5 @@
{
"recommendations": [
"formulahendry.code-runner"
]
}

20
code/VideoAccess-VCMP/web/Dockerfile

@ -1,5 +1,4 @@
FROM repository.anxinyun.cn/devops/node:12-dev as builder
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
COPY . /var/app COPY . /var/app
@ -7,6 +6,19 @@ WORKDIR /var/app
EXPOSE 8080 EXPOSE 8080
CMD ["-u", "http://localhost:8088"] RUN npm config set registry=http://10.8.30.22:7000
RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
RUN npm cache clean -f
RUN npm install --registry http://10.8.30.22:7000
RUN npm run build
RUN rm -rf client/src
RUN rm -rf node_modules
RUN npm install --production --registry http://10.8.30.22:7000
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node-16:7.22-06-20
COPY --from=builder --chown=node /var/app /home/node/app
WORKDIR /home/node/app
ENTRYPOINT [ "node", "server.js" ] CMD ["node", "server.js"]

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/loginBackground.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/logo/figure.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

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

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save