Compare commits

...

288 Commits

Author SHA1 Message Date
deartibers bac88851a7 状态码问题修改 2 years ago
wenlele 396458a380 Merge branch 'dev_trial' of https://gitea.anxinyun.cn/free-sun/FS-IOT into dev_trial 2 years ago
wenlele 3836ddde90 播放组件的修改 2 years ago
deartibers d4c9bca218 状态码释义接口联调 2 years ago
巴林闲侠 3f8c4138db camera_status sql 2 years ago
deartibers 8323f72ce0 Merge branch 'dev_trial' of https://gitea.anxinyun.cn/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 562bc0746e Merge branch 'dev_trial' of https://gitea.anxinyun.cn/free-sun/FS-IOT into dev_trial 2 years ago
巴林闲侠 1381d67ed6 camera status 2 years ago
deartibers bdb2dbe84c 状态码页面静态页面及接口联调 2 years ago
yangsen eded873264 信鸽页面未完成 2 years ago
yangsen 1bd681b64c Merge branch 'dev_trial' of https://gitea.free-sun.vip/free-sun/FS-IOT into dev_trial 2 years ago
yangsen a40ad82452 信鸽页面暂存 2 years ago
deartibers fca2333459 表格属性 2 years ago
deartibers 6915209046 状态码管理和信鸽服务主页面 2 years ago
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. 257
      code/VideoAccess-VCMP/api/app/lib/controllers/status/index.js
  9. 85
      code/VideoAccess-VCMP/api/app/lib/controllers/status/push.js
  10. 23
      code/VideoAccess-VCMP/api/app/lib/controllers/vender/index.js
  11. 111
      code/VideoAccess-VCMP/api/app/lib/index.js
  12. 2
      code/VideoAccess-VCMP/api/app/lib/middlewares/api-log.js
  13. 26
      code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js
  14. 50
      code/VideoAccess-VCMP/api/app/lib/middlewares/business-rest.js
  15. 35
      code/VideoAccess-VCMP/api/app/lib/models/ax_project.js
  16. 276
      code/VideoAccess-VCMP/api/app/lib/models/camera.js
  17. 34
      code/VideoAccess-VCMP/api/app/lib/models/camera_ability.js
  18. 52
      code/VideoAccess-VCMP/api/app/lib/models/camera_ability_bind.js
  19. 34
      code/VideoAccess-VCMP/api/app/lib/models/camera_kind.js
  20. 48
      code/VideoAccess-VCMP/api/app/lib/models/camera_remark.js
  21. 79
      code/VideoAccess-VCMP/api/app/lib/models/camera_status.js
  22. 47
      code/VideoAccess-VCMP/api/app/lib/models/camera_status_log.js
  23. 65
      code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_config.js
  24. 61
      code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_log.js
  25. 51
      code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_monitor.js
  26. 47
      code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_receiver.js
  27. 47
      code/VideoAccess-VCMP/api/app/lib/models/camera_status_resolve.js
  28. 161
      code/VideoAccess-VCMP/api/app/lib/models/gb_camera.js
  29. 128
      code/VideoAccess-VCMP/api/app/lib/models/nvr.js
  30. 63
      code/VideoAccess-VCMP/api/app/lib/models/secret_yingshi.js
  31. 36
      code/VideoAccess-VCMP/api/app/lib/models/vender.js
  32. 32
      code/VideoAccess-VCMP/api/app/lib/routes/auth/index.js
  33. 76
      code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js
  34. 18
      code/VideoAccess-VCMP/api/app/lib/routes/index.js
  35. 23
      code/VideoAccess-VCMP/api/app/lib/routes/nvr/index.js
  36. 44
      code/VideoAccess-VCMP/api/app/lib/routes/status/index.js
  37. 8
      code/VideoAccess-VCMP/api/app/lib/routes/vender/index.js
  38. 151
      code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js
  39. 33
      code/VideoAccess-VCMP/api/app/lib/schedule/index.js
  40. 40
      code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js
  41. 67
      code/VideoAccess-VCMP/api/app/lib/service/paasRequest.js
  42. 41
      code/VideoAccess-VCMP/api/app/lib/service/redis.js
  43. 33
      code/VideoAccess-VCMP/api/app/lib/service/socket.js
  44. 171
      code/VideoAccess-VCMP/api/app/lib/utils/camera.js
  45. 16
      code/VideoAccess-VCMP/api/app/lib/utils/index.js
  46. 154
      code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js
  47. 82
      code/VideoAccess-VCMP/api/app/lib/utils/xlsxDownload.js
  48. 228
      code/VideoAccess-VCMP/api/config.js
  49. 7
      code/VideoAccess-VCMP/api/package.json
  50. 66
      code/VideoAccess-VCMP/api/sequelize-automate.config.js
  51. 15
      code/VideoAccess-VCMP/api/utils/forward-api.js
  52. 3
      code/VideoAccess-VCMP/script/.vscode/settings.json
  53. 543
      code/VideoAccess-VCMP/script/0.0.1/0_init_db.sql
  54. 14
      code/VideoAccess-VCMP/script/1.1.0/1.camera_remark.sql
  55. 17
      code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/.vscode/launch.json
  56. 69
      code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/index.js
  57. 16
      code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/package.json
  58. BIN
      code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/云录制错误码.xlsx
  59. 141
      code/VideoAccess-VCMP/script/1.1.1/data/2.insert_camera_status.sql
  60. 140
      code/VideoAccess-VCMP/script/1.1.1/schema/1.create_camera_status_table.sql
  61. 5
      code/VideoAccess-VCMP/web/.vscode/extensions.json
  62. 20
      code/VideoAccess-VCMP/web/Dockerfile
  63. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/Reset.png
  64. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/backGround.png
  65. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/blue.png
  66. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/building.png
  67. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/camera.png
  68. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/cascade.png
  69. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/codeAfter.png
  70. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/codeArrow.png
  71. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/codeBefore.png
  72. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/copy1.png
  73. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/copy2.png
  74. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/formchoose.png
  75. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/green.png
  76. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/grey.png
  77. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/header.png
  78. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/ipc.png
  79. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/location.png
  80. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/loginBackground.gif
  81. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/loginbg.png
  82. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/logo.png
  83. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/notice.png
  84. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/nvr.png
  85. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/nvr_banner.png
  86. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/password.png
  87. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon0.png
  88. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon1.png
  89. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon2.png
  90. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/projectIcon3.png
  91. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/red.png
  92. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/setup.png
  93. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera1.png
  94. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/sewage_camera2.png
  95. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/store1.png
  96. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/store2.png
  97. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/straightline.png
  98. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/talk.png
  99. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/talking.png
  100. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/test.png

1
.gitignore

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

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

@ -1,41 +1,52 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动API",
"program": "${workspaceRoot}/server.js",
"env": {
"NODE_ENV": "development"
},
"args": [
"-p 14000",
"-f http://localhost:14000",
// "-g postgres://postgres:123@10.8.30.32:5432/yinjiguanli",
// "-g postgres://postgres:123456@221.230.55.27:5432/yinjiguanli",
// "-g postgres://FashionAdmin:123456@10.8.30.156:5432/SmartEmergency",
"-g postgres://postgres:Mantis1921@116.63.50.139:54327/smartYingji"
]
},
{
"type": "node",
"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"
}
}
]
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动API",
"program": "${workspaceRoot}/server.js",
"env": {
"NODE_ENV": "development"
},
"args": [
"-p 4000",
"-f http://localhost:4000",
"-g postgres://postgres:123@10.8.30.32:5432/video_access",
"--redisHost 127.0.0.1",
"--redisPort 6379",
"--axyApiUrl http://127.0.0.1:4100",
"--iotAuthApi http://127.0.0.1:4200",
"--godUrl https://restapi.amap.com/v3",
"--godKey 21c2d970e1646bb9a795900dd00093ce",
"--mqttVideoServer mqtt://10.8.30.71:30883",
"--iotVideoServerUrl http://221.230.55.27:8081",
// "--iotVideoServerUrl http://10.8.30.59:8080",
"--cameraPlayWsHost ws://221.230.55.27:8081",
"--cameraPlayHttpFlvHost http://221.230.55.27:2020",
"--cameraPlayHlsHost http://221.230.55.27:8081",
"--cameraPlayRtmpHost rtmp://221.230.55.27:1935",
"--cameraPlayRtspHost rtsp://221.230.55.27:554"
]
},
{
"type": "node",
"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/base-images/nodejs12:20.10.12.2
MAINTAINER liuxinyi "liu.xinyi@free-sun.com.cn"
FROM repository.anxinyun.cn/devops/node:12-dev as builder
COPY . /var/app
@ -9,6 +6,16 @@ WORKDIR /var/app
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;
// TODO 向视频服务发送通知
// 库记录
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,
};

257
code/VideoAccess-VCMP/api/app/lib/controllers/status/index.js

@ -0,0 +1,257 @@
'use strict';
const moment = require('moment')
async function get (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const { limit, page, orderBy, orderDirection, keyword, forbidden, paraphraseCustom } = ctx.query
const sequelize = ctx.fs.dc.ORM;
let findOption = {
attributes: {
include: [
[sequelize.fn('COUNT', sequelize.col('cameraStatusLogs.id')), 'logCount']
]
},
where: {},
order: [
[orderBy || 'id', orderDirection || 'DESC']
],
distinct: true,
subQuery: false,
group: [
'cameraStatus.id',
'cameraStatusLogs.status_id',
// 'cameraStatusResolves.id'
],
include: [
// {
// model: models.CameraStatusResolve,
// attributes: { exclude: ['statusId'] },
// required: false,
// duplicating: true
// },
{
model: models.CameraStatusLog,
attributes: [],
duplicating: false,
required: false,
}
],
}
if (orderBy) {
if (orderBy == 'logCount') {
findOption.order = sequelize.literal(`"logCount" ${orderDirection || 'DESC'}`)
}
}
if (limit) {
findOption.limit = limit
}
if (page && limit) {
findOption.offset = page * limit
}
if (keyword) {
findOption.where['$or'] = {
describe: {
$like: `%${keyword}%`
},
paraphrase: {
$like: `%${keyword}%`
},
paraphraseCustom: {
$like: `%${keyword}%`
},
}
}
if (forbidden) {
if (forbidden === 'true') {
findOption.where.forbidden = true
} else if (forbidden === 'false') {
findOption.where.forbidden = false
}
}
if (paraphraseCustom) {
if (paraphraseCustom === 'true') {
findOption.where.paraphraseCustom = null
} else if (paraphraseCustom === 'false') {
findOption.where.paraphraseCustom = {
$ne: null
}
}
}
const statusRes = await models.CameraStatus.findAll(findOption)
delete findOption.order
delete findOption.limit
delete findOption.offset
delete findOption.attributes
delete findOption.group
const count = await models.CameraStatus.count(findOption)
const statusIds = statusRes.map(r => r.id)
const statusResolveRes = await models.CameraStatusResolve.findAll({
where: {
statusId: {
$in: statusIds
}
}
})
for (let { dataValues: s } of statusRes) {
const corResolve = statusResolveRes.filter(r => r.statusId === s.id)
s.resolve = corResolve
}
ctx.status = 200;
ctx.body = {
count,
rows: statusRes,
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function getSimpleAll (ctx) {
try {
const models = ctx.fs.dc.models;
const statusRes = await models.CameraStatus.findAll({
attributes: ['id', 'platform', 'status', 'describe'],
})
ctx.status = 200;
ctx.body = statusRes
} 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.CameraStatus.update({
forbidden: data.forbidden
}, {
where: {
id: data.statusId
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function paraphraseCustom (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const data = ctx.request.body
await models.CameraStatus.update({
paraphraseCustom: data.paraphrase,
}, {
where: {
id: { $in: data.statusId }
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function resolveEdit (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const data = ctx.request.body
await models.CameraStatusResolve.destroy({
where: {
statusId: data.statusId
},
transaction
})
await models.CameraStatusResolve.bulkCreate(
data.resolve.map(r => {
return {
statusId: data.statusId,
resolve: 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 = {}
}
}
async function statusCheck (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
const { status, platform, describe } = ctx.query
if (!status || !platform) {
throw 'status and platform is required'
}
const statusRes = await models.CameraStatus.findOne({
where: {
status,
platform,
},
include: [{
model: models.CameraStatusResolve,
attributes: { exclude: ['statusId'] },
}],
})
if (!statusRes && describe) {
await models.CameraStatus.create({
status, platform, describe
})
}
ctx.status = 200;
ctx.body = statusRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
get,
getSimpleAll,
banned,
paraphraseCustom,
resolveEdit,
statusCheck,
};

85
code/VideoAccess-VCMP/api/app/lib/controllers/status/push.js

@ -0,0 +1,85 @@
'use strict';
const moment = require('moment')
async function edit (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function get (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
ctx.status = 204;
} 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.models;
const { userId, token } = ctx.fs.api
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function del (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function copy (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function detail (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, token } = ctx.fs.api
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
module.exports = {
edit, get, banned, del, copy, detail
};

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,
};

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

@ -1,36 +1,103 @@
'use strict';
const fs = require('fs');
const path = require('path');
const utils = require('./utils')
const routes = require('./routes');
const redisConnect = require('./service/redis')
const socketConect = require('./service/socket')
const mqttVideoServer = require('./service/mqttVideoServer')
const paasRequest = require('./service/paasRequest');
const authenticator = require('./middlewares/authenticator');
const schedule = require('./schedule')
// const apiLog = require('./middlewares/api-log');
const businessRest = require('./middlewares/business-rest');
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.authAttr = app.fs.api.authAttr || {};
app.fs.api.logAttr = app.fs.api.logAttr || {};
app.fs.api = app.fs.api || {};
app.fs.utils = app.fs.utils || {};
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));
// router.use(apiLog(app, opts));
// 顺序固定 ↓
redisConnect(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: {} }
require('./models/user')(dc);
require('./models/user_token')(dc);
require('./models/department')(dc);
require('./models/resource')(dc);
require('./models/user_resource')(dc);
require('./models/places')(dc);
require('./models/user_placeSecurityRecord')(dc);
require('./models/report_type')(dc);
require('./models/report_downManage')(dc);
require('./models/department')(dc);
require('./models/report_configition')(dc);
require('./models/report_collection')(dc);
require('./models/report_rectify')(dc);
// 加载定义模型 历史写法
// require('./models/nvr')(dc);
// require('./models/camera_ability')(dc);
// require('./models/camera_kind')(dc);
// require('./models/camera')(dc);
// require('./models/camera_ability_bind')(dc);
// require('./models/vender')(dc);
// require('./models/secret_yingshi')(dc);
// require('./models/gb_camera')(dc);
// require('./models/ax_project')(dc);
// require('./models/camera_remark')(dc);
// 模型关系摘出来 初始化之后再定义关系才行
fs.readdirSync(path.join(__dirname, '/models')).forEach((filename) => {
require(`./models/${filename}`)(dc)
});
const {
Nvr, Camera, CameraAbility, CameraAbilityBind, CameraKind, CameraRemark,
GbCamera, SecretYingshi, Vender, CameraStatus, CameraStatusResolve, CameraStatusLog
} = dc.models;
// Nvr.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
// User.hasMany(Nvr, { foreignKey: 'userId', sourceKey: 'id' });
Camera.belongsToMany(CameraAbility, { through: CameraAbilityBind, foreignKey: 'cameraId', otherKey: 'abilityId' });
CameraRemark.belongsTo(Camera, { foreignKey: 'cameraId', targetKey: 'id' });
Camera.hasMany(CameraRemark, { foreignKey: 'cameraId', sourceKey: 'id' });
Camera.belongsTo(CameraKind, { foreignKey: 'kindId', targetKey: 'id' });
CameraKind.hasMany(Camera, { foreignKey: 'kindId', sourceKey: 'id' });
Camera.belongsTo(Nvr, { foreignKey: 'nvrId', targetKey: 'id' });
Nvr.hasMany(Camera, { foreignKey: 'nvrId', sourceKey: 'id' });
Nvr.belongsTo(GbCamera, { foreignKey: 'serialNo', targetKey: 'streamid', as: 'gbNvr' });
GbCamera.hasMany(Nvr, { foreignKey: 'serialNo', sourceKey: 'streamid', as: 'gbNvr' });
Camera.belongsTo(GbCamera, { foreignKey: 'gbId', targetKey: 'id' });
GbCamera.hasMany(Camera, { foreignKey: 'gbId', sourceKey: 'id' });
Camera.belongsTo(SecretYingshi, { foreignKey: 'yingshiSecretId', targetKey: 'id' });
SecretYingshi.hasMany(Camera, { foreignKey: 'yingshiSecretId', sourceKey: 'id' });
Camera.belongsTo(Vender, { foreignKey: 'venderId', targetKey: 'id' });
Vender.hasMany(Camera, { foreignKey: 'venderId', sourceKey: 'id' });
Nvr.belongsTo(Vender, { foreignKey: 'venderId', targetKey: 'id' });
Vender.hasMany(Nvr, { foreignKey: 'venderId', sourceKey: 'id' });
CameraStatusResolve.belongsTo(CameraStatus, { foreignKey: 'statusId', targetKey: 'id' });
CameraStatus.hasMany(CameraStatusResolve, { foreignKey: 'statusId', sourceKey: 'id' });
CameraStatusLog.belongsTo(CameraStatus, { foreignKey: 'statusId', targetKey: 'id' });
CameraStatus.hasMany(CameraStatusLog, { foreignKey: 'statusId', sourceKey: 'id' });
};

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

@ -71,7 +71,7 @@ function factory(app, opts) {
partition: 0
}];
await sendToEsAsync(producer, payloads);
// await sendToEsAsync(producer, payloads);
} catch (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);
}
sanitizePath(path) {
sanitizePath (path) {
if (!path) return '/';
const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/');
return p;
}
reload(opts) {
reload (opts) {
// load all url
if (!this.allUrls) {
this.allUrls = opts;
@ -37,7 +37,7 @@ class ExcludesUrls {
}
}
isExcluded(path, method) {
isExcluded (path, method) {
return this.allUrls.some(function (url) {
return !url.auth
&& url.pregexp.test(path)
@ -58,9 +58,7 @@ let isPathExcluded = function (opts, path, method) {
if (!excludeAll) {
let excludeOpts = opts.exclude || [];
excludeOpts.push({ p: '/login', o: 'POST' });
excludeOpts.push({ p: '/wxLogin', o: 'POST' });
excludeOpts.push({ p: '/logout', o: 'PUT' });
excludeOpts.push({ p: '/wxLogout', o: 'PUT' });
excludes = new ExcludesUrls(excludeOpts);
}
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;
if (token && tokenFormatRegexp.test(token)) {
try {
const axyRes = await ctx.fs.dc.models.UserToken.findOne({
where: {
token: token,
expired: { $gte: moment().format('YYYY-MM-DD HH:mm:ss') }
}
});
const { userInfo, expired } = axyRes;
if (!expired || moment().valueOf() <= moment(expired).valueOf()) {
const expired = await ctx.redis.hget(token, 'expired');
if (expired && moment().valueOf() <= moment(expired).valueOf()) {
const userInfo = JSON.parse(await ctx.redis.hget(token, 'userInfo'));
rslt = {
'authorized': userInfo.authorized,
'resources': (userInfo || {}).resources || [],
@ -100,7 +94,6 @@ let isResourceAvailable = function (resources, options) {
let authCode = null;
// authorize user by authorization attribute
const { authAttr, method, path } = options;
console.log(resources, options)
for (let prop in authAttr) {
let 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);
};
function factory(app, opts) {
return async function auth(ctx, next) {
function factory (app, opts) {
return async function auth (ctx, next) {
const { path, method, header, query } = ctx;
ctx.fs.logger.log('[AUTH] start', path, method);
ctx.fs.api = ctx.fs.api || {};
ctx.fs.port = opts.port;
ctx.redis = app.redis;
ctx.redisTools = app.redisTools;
let error = null;
if (path) {
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;

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

@ -0,0 +1,35 @@
/* 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: []
});
dc.models.AxProject = AxProject;
return AxProject;
};

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

@ -0,0 +1,276 @@
/* 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;
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;
};

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

@ -0,0 +1,52 @@
/* 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;
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;
};

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

@ -0,0 +1,48 @@
/* 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;
return CameraRemark;
};

79
code/VideoAccess-VCMP/api/app/lib/models/camera_status.js

@ -0,0 +1,79 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraStatus = sequelize.define("cameraStatus", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_status_id_uindex"
},
platform: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "平台分类 yingshi gb",
primaryKey: false,
field: "platform",
autoIncrement: false
},
status: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "status",
autoIncrement: false
},
describe: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "错误描述",
primaryKey: false,
field: "describe",
autoIncrement: false
},
paraphrase: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "释义",
primaryKey: false,
field: "paraphrase",
autoIncrement: false
},
forbidden: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: "是否禁用",
primaryKey: false,
field: "forbidden",
autoIncrement: false
},
paraphraseCustom: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "自定义释义",
primaryKey: false,
field: "paraphrase_custom",
autoIncrement: false
}
}, {
tableName: "camera_status",
comment: "",
indexes: []
});
dc.models.CameraStatus = CameraStatus;
return CameraStatus;
};

47
code/VideoAccess-VCMP/api/app/lib/models/camera_status_log.js

@ -0,0 +1,47 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraStatusLog = sequelize.define("cameraStatusLog", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_status_log_id_uindex_2"
},
statusId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "status_id",
autoIncrement: false,
references: {
key: "id",
model: "cameraStatus"
}
},
time: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "time",
autoIncrement: false
}
}, {
tableName: "camera_status_log",
comment: "",
indexes: []
});
dc.models.CameraStatusLog = CameraStatusLog;
return CameraStatusLog;
};

65
code/VideoAccess-VCMP/api/app/lib/models/user.js → code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_config.js

@ -4,7 +4,7 @@
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const User = sequelize.define("user", {
const CameraStatusPushConfig = sequelize.define("cameraStatusPushConfig", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
@ -13,7 +13,7 @@ module.exports = dc => {
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "user_id_uindex"
unique: "camera_online_status_push_config_id_uindex"
},
name: {
type: DataTypes.STRING,
@ -24,85 +24,56 @@ module.exports = dc => {
field: "name",
autoIncrement: false
},
username: {
pushWay: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "用户名 账号",
comment: "推送方式 email / phone",
primaryKey: false,
field: "username",
field: "push_way",
autoIncrement: false
},
password: {
noticeWay: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
comment: "通知方式 offline / online / timing",
primaryKey: false,
field: "password",
field: "notice_way",
autoIncrement: false
},
departmentId: {
createUser: {
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",
field: "create_user",
autoIncrement: false
},
enable: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: "启用状态",
primaryKey: false,
field: "enable",
autoIncrement: false
},
delete: {
forbidden: {
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",
field: "forbidden",
autoIncrement: false
},
post: {
timing: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "职位",
comment: "定时推送时间",
primaryKey: false,
field: "post",
field: "timing",
autoIncrement: false
}
}, {
tableName: "user",
tableName: "camera_status_push_config",
comment: "",
indexes: []
});
dc.models.User = User;
return User;
dc.models.CameraStatusPushConfig = CameraStatusPushConfig;
return CameraStatusPushConfig;
};

61
code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_log.js

@ -0,0 +1,61 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraStatusPushLog = sequelize.define("cameraStatusPushLog", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_status_push_log_id_uindex"
},
pushConfigId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "push_config_id",
autoIncrement: false
},
receiver: {
type: DataTypes.JSONB,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "receiver",
autoIncrement: false
},
time: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "time",
autoIncrement: false
},
pushWay: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "push_way",
autoIncrement: false
}
}, {
tableName: "camera_status_push_log",
comment: "",
indexes: []
});
dc.models.CameraStatusPushLog = CameraStatusPushLog;
return CameraStatusPushLog;
};

51
code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_monitor.js

@ -0,0 +1,51 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraStatusPushMonitor = sequelize.define("cameraStatusPushMonitor", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_status_push_monitor_id_uindex"
},
configId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "config_id",
autoIncrement: false,
references: {
key: "id",
model: "cameraStatusPushConfig"
}
},
cameraId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "camera_id",
autoIncrement: false,
references: {
key: "id",
model: "camera"
}
}
}, {
tableName: "camera_status_push_monitor",
comment: "",
indexes: []
});
dc.models.CameraStatusPushMonitor = CameraStatusPushMonitor;
return CameraStatusPushMonitor;
};

47
code/VideoAccess-VCMP/api/app/lib/models/camera_status_push_receiver.js

@ -0,0 +1,47 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraStatusPushReceiver = sequelize.define("cameraStatusPushReceiver", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_status_push_receiver_id_uindex"
},
configId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "config_id",
autoIncrement: false,
references: {
key: "id",
model: "cameraStatusPushConfig"
}
},
receiver: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "接受者信息 邮箱或者电话号码",
primaryKey: false,
field: "receiver",
autoIncrement: false
}
}, {
tableName: "camera_status_push_receiver",
comment: "",
indexes: []
});
dc.models.CameraStatusPushReceiver = CameraStatusPushReceiver;
return CameraStatusPushReceiver;
};

47
code/VideoAccess-VCMP/api/app/lib/models/camera_status_resolve.js

@ -0,0 +1,47 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const CameraStatusResolve = sequelize.define("cameraStatusResolve", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "camera_status_resolve_id_uindex"
},
statusId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "status_id",
autoIncrement: false,
references: {
key: "id",
model: "cameraStatus"
}
},
resolve: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "resolve",
autoIncrement: false
}
}, {
tableName: "camera_status_resolve",
comment: "",
indexes: []
});
dc.models.CameraStatusResolve = CameraStatusResolve;
return CameraStatusResolve;
};

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

@ -0,0 +1,161 @@
/* 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: []
});
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;
};

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

@ -0,0 +1,63 @@
/* 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: []
});
dc.models.SecretYingshi = SecretYingshi;
return SecretYingshi;
};

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

@ -0,0 +1,36 @@
/* 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: []
});
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');
module.exports = function (app, router, opts) {
fs.readdirSync(__dirname).forEach((filename) => {
if (filename.indexOf('.') !== 0 &&fs.lstatSync(path.join(__dirname, filename)).isDirectory()) {
fs.readdirSync(path.join(__dirname, filename)).forEach((api) => {
if (api.indexOf('.') == 0 || api.indexOf('.js') == -1) return;
require(`./${filename}/${api}`)(app, router, opts);
});
}
});
fs.readdirSync(__dirname).forEach((filename) => {
if (filename.indexOf('.') !== 0 && fs.lstatSync(path.join(__dirname, filename)).isDirectory()) {
fs.readdirSync(path.join(__dirname, filename)).forEach((api) => {
if (api.indexOf('.') == 0 || api.indexOf('.js') == -1) return;
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);
};

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

@ -0,0 +1,44 @@
'use strict';
const status = require('../../controllers/status');
const push = require('../../controllers/status/push');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/status'] = { content: '获取状态码', visible: false };
router.get('/status', status.get);
app.fs.api.logAttr['GET/status/simple_all'] = { content: '获取全部状态码简略信息', visible: false };
router.get('/status/simple_all', status.getSimpleAll);
app.fs.api.logAttr['PUT/status/banned'] = { content: '禁用状态码自定义', visible: false };
router.put('/status/banned', status.banned);
app.fs.api.logAttr['POST/status/custom'] = { content: '自定义状态码释义', visible: false };
router.post('/status/custom', status.paraphraseCustom);
app.fs.api.logAttr['POST/status/resolve'] = { content: '编辑解决方案', visible: false };
router.post('/status/resolve', status.resolveEdit);
app.fs.api.logAttr['GET/status/check'] = { content: '查取指定状态码信息', visible: false };
router.get('/status/check', status.statusCheck);
// 信鸽推送
app.fs.api.logAttr['POST/status/push'] = { content: '编辑推送配置', visible: false };
router.post('/status/push', push.edit);
app.fs.api.logAttr['GET/status/push'] = { content: '获取推送配置', visible: false };
router.get('/status/push', push.get);
app.fs.api.logAttr['PUT/status/push/banned'] = { content: '禁用推送配置', visible: false };
router.put('/status/push/banned', push.banned);
app.fs.api.logAttr['DEL/status/push/:pushId'] = { content: '删除推送配置', visible: false };
router.delete('/status/push/:pushId', push.del);
app.fs.api.logAttr['GET/status/push/:pushId/copy'] = { content: '赋值推送配置', visible: false };
router.get('/status/push/:pushId/copy', push.copy);
app.fs.api.logAttr['GET/status/push/:pushId/detail'] = { content: '获取推送配置详情', visible: false };
router.get('/status/push/:pushId/detail', push.detail);
// 信鸽推送 END
};

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(['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 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;
if (!IOT_VIDEO_ACCESS_DB) {
console.log('缺少启动参数,异常退出');
args.showHelp();
process.exit(-1);
const IOTA_REDIS_SERVER_HOST = process.env.IOTA_REDIS_SERVER_HOST || flags.redisHost || "localhost";//redis IP
const IOTA_REDIS_SERVER_PORT = process.env.IOTA_REDIS_SERVER_PORT || flags.redisPort || "6379";//redis 端口
const IOTA_REDIS_SERVER_PWD = process.env.IOTA_REDIS_SERVER_PWD || flags.redisPswd || "";//redis 密码
const 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 = {
port: flags.port || 8080,
staticDirs: ['static'],
mws: [
{
entry: require('@fs/attachment').entry,
opts: {
local: {
origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`,
rootPath: 'static',
childPath: 'upload',
},
maxSize: 104857600, // 100M
}
}, {
entry: require('./app').entry,
opts: {
exclude: [], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
}
}
],
dc: {
url: IOT_VIDEO_ACCESS_DB,
opts: {
pool: {
max: 80,
min: 10,
idle: 10000
port: flags.port || 8080,
staticDirs: ['static'],
mws: [
{
entry: require('@fs/attachment').entry,
opts: {
local: {
origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`,
rootPath: 'static',
childPath: 'upload',
},
maxSize: 104857600, // 100M
}
}, {
entry: require('./app').entry,
opts: {
dev,
exclude: [
{ p: '/camera', o: 'GET' }, // 暂时滴
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
redis: {
host: IOTA_REDIS_SERVER_HOST,
port: IOTA_REDIS_SERVER_PORT,
pwd: IOTA_REDIS_SERVER_PWD
},
mqtt: {
mqttVideoServer: MQTT_VIDEO_SERVER,
},
define: {
freezeTableName: true, // 固定表名
timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt"
cameraPlayHost: {
ws: CAMERA_PLAY_WS_HOST,
httpFlv: CAMERA_PLAY_HTTP_FLV_HOST,
hls: CAMERA_PLAY_HLS_HOST,
rtmp: CAMERA_PLAY_RTMP_HOST,
rtsp: CAMERA_PLAY_RTSP_HOST,
},
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
}
pssaRequest: [
{// name 会作为一个 request 出现在 ctx.app.fs
name: 'authRequest',
root: IOT_AUTH_API
}, {
name: 'axyRequest',
root: AXY_API_URL
}, {
name: 'godRequest',
root: GOD_URL,
params: {
query: {
key: GOD_KEY
}
}
}, {
name: 'yingshiRequest',
root: YINGSHI_URL,
params: {
query: {
key: GOD_KEY
}
}
}, {
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 = {
port: product.port,
staticDirs: product.staticDirs,
mws: product.mws,
dc: product.dc,
logger: product.logger
port: product.port,
staticDirs: product.staticDirs,
mws: product.mws,
dc: product.dc,
logger: product.logger
};
if (dev) {
// mws
for (let mw of development.mws) {
// if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由
}
// logger
development.logger.filename = path.join(__dirname, 'log', 'development.log');
development.logger.level = 'debug';
development.dc.opts.logging = console.log;
// mws
for (let mw of development.mws) {
// if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由
}
// logger
development.logger.filename = path.join(__dirname, 'log', 'development.log');
development.logger.level = 'debug';
development.dc.opts.logging = console.log;
}
module.exports = dev ? development : product;

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

@ -5,7 +5,7 @@
"main": "server.js",
"scripts": {
"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",
"automate": "sequelize-automate -c sequelize-automate.config.js"
},
@ -15,13 +15,16 @@
"dependencies": {
"@fs/attachment": "^1.0.0",
"args": "^3.0.7",
"better-xlsx": "^0.7.6",
"crypto-js": "^4.0.0",
"file-saver": "^2.0.2",
"fs-web-server-scaffold": "^2.0.2",
"ioredis": "^4.19.4",
"ioredis": "^5.0.4",
"koa-convert": "^1.2.0",
"koa-proxy": "^0.9.0",
"moment": "^2.24.0",
"mqtt": "^4.3.7",
"node-schedule": "^2.1.0",
"path": "^0.12.7",
"path-to-regexp": "^3.0.0",
"pg": "^7.9.0",

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

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

3
code/VideoAccess-VCMP/script/.vscode/settings.json

@ -0,0 +1,3 @@
{
"editor.wordWrap": "on"
}

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

17
code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/.vscode/launch.json

@ -0,0 +1,17 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\index.js"
}
]
}

69
code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/index.js

@ -0,0 +1,69 @@
try {
const { Pool, Client } = require('pg')
const XLSX = require('xlsx')
const path = require('path')
// 连接数据库
const pool = new Pool({
user: 'postgres',
host: '10.8.30.32',
database: 'video_access',
password: '123',
port: 5432,
})
const fun = async () => {
// note: we don't try/catch this because if connecting throws an exception
// we don't need to dispose of the client (it will be undefined)
const client = await pool.connect()
try {
await client.query('BEGIN')
// 读取数据文件
let workbook = XLSX.readFile(path.join(__dirname, '云录制错误码.xlsx'))
let firstSheetName = workbook.SheetNames[0];
let worksheet = workbook.Sheets[firstSheetName];
let res = XLSX.utils.sheet_to_json(worksheet);
// console.log(res);
for (let d of res) {
let statusRes = await client.query(`SELECT * FROM camera_status WHERE status=$1`, [d['错误码']]);
let statusRows = statusRes.rows
if (statusRows.length) {
} else {
console.log(`增加${d['错误码']}`);
const statusInQuery = `INSERT INTO "camera_status" (platform, status, describe, paraphrase) VALUES($1, $2, $3, $4) RETURNING id;`
const statusRows = (await client.query(statusInQuery, ['yingshi', d['错误码'], d['错误描述'], d['释义']])).rows
// console.log(statusRows);
if (d['解决方案']) {
let resolveArr = d['解决方案'].split(';');
// await client.query(`DELETE FROM "camera_status_solution" WHERE status_id=$1`, [statusRows[0].id]);
for (let r of resolveArr) {
await client.query(
`INSERT INTO "camera_status_resolve" (status_id, resolve) VALUES($1, $2) RETURNING id;`,
[statusRows[0].id, r]
)
}
}
}
}
// await client.query('ROLLBACK')
await client.query('COMMIT')
console.log('执行完毕~')
} catch (e) {
await client.query('ROLLBACK')
console.log('执行错误~')
throw e
} finally {
client.release();
}
}
fun()
} catch (error) {
console.error(error)
}

16
code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/package.json

@ -0,0 +1,16 @@
{
"name": "appkey-generator",
"version": "1.0.0",
"description": "tool",
"main": "index.js",
"scripts": {
"test": "mocha",
"start": "set NODE_ENV=development&&node index"
},
"author": "liu",
"license": "ISC",
"dependencies": {
"pg": "^7.18.2",
"xlsx": "^0.17.1"
}
}

BIN
code/VideoAccess-VCMP/script/1.1.1/data/1_update_status_code_data/云录制错误码.xlsx

Binary file not shown.

141
code/VideoAccess-VCMP/script/1.1.1/data/2.insert_camera_status.sql

@ -0,0 +1,141 @@
-- ----------------------------
-- Records of camera_status
-- ----------------------------
INSERT INTO "public"."camera_status" VALUES (2, 'yingshi', '5000', '服务端内部处理异常', '服务端内部错误码', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (3, 'yingshi', '5400', '私有化协议vtm检测私有化协议中码流类型小于0或者设备序列号为空等非法参数场景返回(app不重试取流)', '客户端参数出错', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (4, 'yingshi', '5402', '回放找不到录像文件', '设备回放找不到录像文件', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (5, 'yingshi', '5403', '操作码或信令密钥与设备不匹配', '操作码或信令密钥与设备不匹配', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (6, 'yingshi', '5404', '设备不在线', '设备不在线', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (7, 'yingshi', '5405', '流媒体向设备发送或接受信令超时/cas响应超时', '设备回应信令10秒超时', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (8, 'yingshi', '5406', 'token失效', 'token失效', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (9, 'yingshi', '5407', '客户端的URL格式错误', '客户端的URL格式错误', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (10, 'yingshi', '5409', '预览开启隐私保护', '预览开启隐私保护', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (11, 'yingshi', '5411', 'token无权限', 'token无权限、用户无权限', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (12, 'yingshi', '5412', 'session不存在', 'session不存在', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (13, 'yingshi', '5413', '验证token的他异常(不具体)', 'token验证失败', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (14, 'yingshi', '5415', '设备通道错', '设备判断请求通道不存在', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (15, 'yingshi', '5416', '设备资源受限', '设备资源受限', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (16, 'yingshi', '5451', '设备不支持的码流类型', '设备不支持的码流类型', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (17, 'yingshi', '5452', '设备链接流媒体服务器失败', '设备链接流媒体服务器失败', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (18, 'yingshi', '5454', '流媒体中关于设备取流会话不存在', '流媒体中关于设备取流会话不存在', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (19, 'yingshi', '5455', '设备通道未关联', '设备通道未关联', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (20, 'yingshi', '5456', '设备通道关联设备不在线', '设备通道关联设备不在线', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (21, 'yingshi', '5457', '客户端不支持端到端加密', '客户端不支持端到端加密', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (22, 'yingshi', '5458', '设备不支持当前并发ECDH密', '设备不支持当前并发ECDH密', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (23, 'yingshi', '5459', 'VTDU 处理ECDH 加密失败', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (24, 'yingshi', '5492', '设备不支持的命令', '设备不支持的命令', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (25, 'yingshi', '5500', '服务器处理失败', '服务器处理失败', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (26, 'yingshi', '5503', 'vtm返回分配vtdu失败', 'vtm返回分配vtdu失败', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (27, 'yingshi', '5504', '流媒体vtdu达到最大负载', '流媒体vtdu达到最大负载', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (28, 'yingshi', '5544', '设备返回无视频源', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (29, 'yingshi', '5545', '视频分享时间已经结束', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (30, 'yingshi', '5546', 'vtdu返回达到取流并发路数限制', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (31, 'yingshi', '5547', 'vtdu返回开放平台用户并发限制', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (32, 'yingshi', '5556', 'ticket校验失败', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (33, 'yingshi', '5557', '回放服务器等待流头超时', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (34, 'yingshi', '5558', '查找录像开始时间错误', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (35, 'yingshi', '5560', '群组分享取流二次验证失败', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (36, 'yingshi', '5561', '分享群组用户被锁住', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (37, 'yingshi', '5562', '群组分享用户权限变更', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (38, 'yingshi', '5563', '认证服务连接失败', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (39, 'yingshi', '5564', '认证超时', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (40, 'yingshi', '5565', '缓存无效', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (41, 'yingshi', '5566', '不在分享时间内预览', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (42, 'yingshi', '5567', '分享通道被锁定', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (43, 'yingshi', '5568', '未找到认证类型', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (44, 'yingshi', '5569', '认证返回的参数异常', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (45, 'yingshi', '5600', '分享设备不在分享时间内', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (46, 'yingshi', '5601', '群组分享用户没权限', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (47, 'yingshi', '5602', '群组分享权限变更', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (48, 'yingshi', '5530', '机房故障不可用', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (49, 'yingshi', '5701', 'cas信令返回格式错误', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (50, 'yingshi', '5702', 'SPGW请求Cas、Status透传超时', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (51, 'yingshi', '5703', 'SPGW请求http不通', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (52, 'yingshi', '6001', '客户端参数出错', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (53, 'yingshi', '6099', '客户端默认错误', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (54, 'yingshi', '6101', '不支持的命令', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (55, 'yingshi', '6102', '设备流头发送失败', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (56, 'yingshi', '6103', 'cas/设备返回错误1', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (57, 'yingshi', '6104', 'cas/设备返回错误-1', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (58, 'yingshi', '6105', '设备返回错误码3', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (59, 'yingshi', '6106', '设备返回错误码4', '一般常见于多通道设 备预览 1、通道不存在 2、通道子码流不存在 3、通道不在线', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (60, 'yingshi', '6107', '设备返回错误码5', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (61, 'yingshi', '6108', 'cas信令回应重复', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (62, 'yingshi', '6109', '视频广场取消分享', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (63, 'yingshi', '6110', '设备信令默认错误', '设备错误返回的错误码,不具体', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (64, 'yingshi', '6501', '设备数据链路和实际链路不匹配', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (65, 'yingshi', '6502', '设备数据链路重复建立连接', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (66, 'yingshi', '6503', '设备数据链路端口不匹配', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (67, 'yingshi', '6504', '缓存设备数据链路失败(内存块不足)', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (68, 'yingshi', '6505', '设备发送确认头消息重复', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (69, 'yingshi', '6506', '设备数据先于确定头部到达', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (70, 'yingshi', '6508', '设备数据头部长度非法', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (71, 'yingshi', '6509', '索引找不到设备数据管理块', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (72, 'yingshi', '6510', '设备数据链路vtdu内存块协议状态不匹配', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (73, 'yingshi', '6511', '设备数据头部没有streamkey错误', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (74, 'yingshi', '6512', '设备数据头部非法(较笼统)', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (75, 'yingshi', '6513', '设备数据长度过小', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (76, 'yingshi', '6514', '设备老协议推流头部没有streamkey错误', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (77, 'yingshi', '6515', '设备老协议推流数据非法', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (78, 'yingshi', '6516', '设备老协议索引找不到内存管理块', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (79, 'yingshi', '6517', '设备老协议推流数据非法', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (80, 'yingshi', '6518', '设备数据包过大', NULL, 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (81, 'yingshi', '6519', '设备推流链路网络不稳定', '设备长时间未推流超时', 'f', NULL);
INSERT INTO "public"."camera_status" VALUES (82, 'yingshi', '6520', '设备推流链路网络不稳定(默认)', '设备网络异常', 'f', NULL);
-- ----------------------------
-- Records of camera_status_resolve
-- ----------------------------
INSERT INTO "public"."camera_status_resolve" VALUES (2, 2, '检测服务端是否正常');
INSERT INTO "public"."camera_status_resolve" VALUES (3, 3, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (4, 4, '检查是否有存储卡并且接触良好');
INSERT INTO "public"."camera_status_resolve" VALUES (5, 6, '检查设备网络');
INSERT INTO "public"."camera_status_resolve" VALUES (6, 6, '重启设备接入萤石云');
INSERT INTO "public"."camera_status_resolve" VALUES (7, 7, '检查设备网络');
INSERT INTO "public"."camera_status_resolve" VALUES (8, 7, '重启设备');
INSERT INTO "public"."camera_status_resolve" VALUES (9, 8, '刷新重试或者重启设备');
INSERT INTO "public"."camera_status_resolve" VALUES (10, 9, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (11, 13, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (12, 14, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (13, 15, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (14, 16, '刷新重试或者切换到高清模式');
INSERT INTO "public"."camera_status_resolve" VALUES (15, 17, '检查设备网络,重启设备,刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (16, 19, '检查设备通道是否关联');
INSERT INTO "public"."camera_status_resolve" VALUES (17, 20, '检查设备通道是否上线');
INSERT INTO "public"."camera_status_resolve" VALUES (18, 25, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (19, 26, 'vtdu服务异常,请请稍后重试');
INSERT INTO "public"."camera_status_resolve" VALUES (20, 27, '服务器负载达到上限,请稍后重试');
INSERT INTO "public"."camera_status_resolve" VALUES (21, 28, '设备是否接触良好');
INSERT INTO "public"."camera_status_resolve" VALUES (22, 28, '如果一直无法解决,请联系技术支持');
INSERT INTO "public"."camera_status_resolve" VALUES (23, 30, '请升级为企业版,放开并发限制');
INSERT INTO "public"."camera_status_resolve" VALUES (24, 31, '请确定开放平台用户预览是否超过用户并发数量限制');
INSERT INTO "public"."camera_status_resolve" VALUES (25, 33, '刷新重试,检测设备网络,重启设备');
INSERT INTO "public"."camera_status_resolve" VALUES (26, 48, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (27, 49, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (28, 50, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (29, 51, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (30, 52, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (31, 54, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (32, 55, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (33, 56, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (34, 57, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (35, 58, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (36, 59, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (37, 60, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (38, 61, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (39, 63, '刷新重试,或者重启设备');
INSERT INTO "public"."camera_status_resolve" VALUES (40, 64, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (41, 65, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (42, 66, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (43, 67, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (44, 68, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (45, 69, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (46, 70, '刷新重试,或者重启设备');
INSERT INTO "public"."camera_status_resolve" VALUES (47, 71, '刷新重试');
INSERT INTO "public"."camera_status_resolve" VALUES (48, 80, '刷新重试,或者重启设备');

140
code/VideoAccess-VCMP/script/1.1.1/schema/1.create_camera_status_table.sql

@ -0,0 +1,140 @@
create table if not exists camera_status
(
id serial not null,
platform varchar(32) not null,
status varchar(32) not null,
describe varchar(1024),
paraphrase varchar(1024),
forbidden boolean default false not null,
paraphrase_custom varchar(1024),
constraint camera_status_pk
primary key (id)
);
comment on column camera_status.platform is '平台分类 yingshi gb';
comment on column camera_status.describe is '错误描述';
comment on column camera_status.paraphrase is '释义';
comment on column camera_status.forbidden is '是否禁用';
comment on column camera_status.paraphrase_custom is '自定义释义';
create unique index if not exists camera_status_id_uindex
on camera_status (id);
create table if not exists camera_status_log
(
id serial not null,
status_id integer not null,
time timestamp not null,
constraint camera_status_log_pk
primary key (id),
constraint camera_status_log_camera_status_id_fk
foreign key (status_id) references camera_status
);
create unique index if not exists camera_status_log_id_uindex
on camera_status_log (id);
create unique index if not exists camera_status_log_id_uindex_2
on camera_status_log (id);
create table if not exists camera_status_push_config
(
id serial not null,
name varchar(64) not null,
push_way varchar(32) not null,
notice_way varchar(32) not null,
create_user integer not null,
forbidden boolean default false not null,
timing varchar(32),
constraint camera_online_status_push_config_pk
primary key (id)
);
comment on column camera_status_push_config.push_way is '推送方式 email / phone';
comment on column camera_status_push_config.notice_way is '通知方式 offline / online / timing';
comment on column camera_status_push_config.timing is '定时推送时间';
create unique index if not exists camera_online_status_push_config_id_uindex
on camera_status_push_config (id);
create table if not exists camera_status_push_log
(
id serial not null,
push_config_id integer,
receiver jsonb not null,
time timestamp,
push_way varchar(128) not null,
constraint camera_status_push_log_pk
primary key (id)
);
comment on table camera_status_push_log is '上下线推送日志';
create unique index if not exists camera_status_push_log_id_uindex
on camera_status_push_log (id);
create table if not exists camera_status_push_monitor
(
id serial not null,
config_id integer not null,
camera_id integer not null,
constraint camera_status_push_monitor_pk
primary key (id),
constraint camera_status_push_monitor_camera_id_fk
foreign key (camera_id) references camera,
constraint camera_status_push_monitor_camera_status_push_config_id_fk
foreign key (config_id) references camera_status_push_config
);
create unique index if not exists camera_status_push_monitor_id_uindex
on camera_status_push_monitor (id);
create table if not exists camera_status_push_receiver
(
id serial not null,
config_id integer not null,
receiver varchar(64) not null,
constraint camera_status_push_receiver_pk
primary key (id),
constraint camera_status_push_receiver_camera_status_push_config_id_fk
foreign key (config_id) references camera_status_push_config
);
comment on column camera_status_push_receiver.receiver is '接受者信息 邮箱或者电话号码';
create unique index if not exists camera_status_push_receiver_id_uindex
on camera_status_push_receiver (id);
create table if not exists camera_status_resolve
(
id serial not null,
status_id integer not null,
resolve varchar(1024) not null,
constraint camera_status_resolve_pk
primary key (id),
constraint camera_status_resolve_camera_status_id_fk
foreign key (status_id) references camera_status
);
comment on table camera_status_resolve is '错误码解决方案';
create unique index if not exists camera_status_resolve_id_uindex
on camera_status_resolve (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/base-images/nodejs12:20.10.12.2
FROM repository.anxinyun.cn/devops/node:12-dev as builder
COPY . /var/app
@ -7,6 +6,19 @@ WORKDIR /var/app
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/codeAfter.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 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

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

Loading…
Cancel
Save