| | |
| | | 12. 支持播放h265, g.711格式的流 |
| | | 13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD)) |
| | | 14. 报警信息处理,支持向前端推送报警信息 |
| | | 15. 支持订阅与通知方法 |
| | | [X] 移动位置订阅 |
| | | [X] 移动位置通知处理 |
| | | [ ] 报警事件订阅 |
| | | [X] 报警事件通知处理 |
| | | [ ] 设备目录订阅 |
| | | [X] 设备奴鲁通知处理 |
| | | 16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 |
| | | |
| | | # 待实现: |
| | | 上级级联 |
| | |
| | | </head> |
| | | <body> |
| | | <script type="text/javascript" src="./js/EasyWasmPlayer.js"></script> |
| | | <script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=rk73w8dv1rkE4UdZsataG68VarhYQzrx&s=1"></script> |
| | | <div id="app"></div> |
| | | <!-- built files will be auto injected --> |
| | | </body> |
| | |
| | | "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", |
| | | "dev": true |
| | | }, |
| | | "bmaplib.curveline": { |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmjs.org/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz", |
| | | "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q==" |
| | | }, |
| | | "bmaplib.heatmap": { |
| | | "version": "1.0.4", |
| | | "resolved": "https://registry.npmjs.org/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz", |
| | | "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q==" |
| | | }, |
| | | "bmaplib.lushu": { |
| | | "version": "1.0.7", |
| | | "resolved": "https://registry.npmjs.org/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz", |
| | | "integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w==" |
| | | }, |
| | | "bmaplib.markerclusterer": { |
| | | "version": "1.0.13", |
| | | "resolved": "https://registry.npmjs.org/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz", |
| | | "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==", |
| | | "requires": { |
| | | "bmaplib.texticonoverlay": "^1.0.2" |
| | | } |
| | | }, |
| | | "bmaplib.texticonoverlay": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmjs.org/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz", |
| | | "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg==" |
| | | }, |
| | | "bn.js": { |
| | | "version": "5.1.3", |
| | | "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.3.tgz", |
| | |
| | | "invert-kv": "^1.0.0" |
| | | } |
| | | }, |
| | | "linkify-it": { |
| | | "version": "2.2.0", |
| | | "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", |
| | | "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", |
| | | "requires": { |
| | | "uc.micro": "^1.0.1" |
| | | } |
| | | }, |
| | | "load-json-file": { |
| | | "version": "2.0.0", |
| | | "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", |
| | |
| | | "object-visit": "^1.0.0" |
| | | } |
| | | }, |
| | | "markdown-it": { |
| | | "version": "8.4.2", |
| | | "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", |
| | | "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", |
| | | "requires": { |
| | | "argparse": "^1.0.7", |
| | | "entities": "~1.1.1", |
| | | "linkify-it": "^2.0.0", |
| | | "mdurl": "^1.0.1", |
| | | "uc.micro": "^1.0.5" |
| | | }, |
| | | "dependencies": { |
| | | "entities": { |
| | | "version": "1.1.2", |
| | | "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", |
| | | "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" |
| | | } |
| | | } |
| | | }, |
| | | "math-expression-evaluator": { |
| | | "version": "1.2.22", |
| | | "resolved": "https://registry.npm.taobao.org/math-expression-evaluator/download/math-expression-evaluator-1.2.22.tgz", |
| | |
| | | "resolved": "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.4.tgz", |
| | | "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=", |
| | | "dev": true |
| | | }, |
| | | "mdurl": { |
| | | "version": "1.0.1", |
| | | "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", |
| | | "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" |
| | | }, |
| | | "media-typer": { |
| | | "version": "0.3.0", |
| | |
| | | "sprintf-js": { |
| | | "version": "1.0.3", |
| | | "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", |
| | | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", |
| | | "dev": true |
| | | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" |
| | | }, |
| | | "ssri": { |
| | | "version": "5.3.0", |
| | |
| | | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", |
| | | "dev": true |
| | | }, |
| | | "uc.micro": { |
| | | "version": "1.0.6", |
| | | "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", |
| | | "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" |
| | | }, |
| | | "uglify-js": { |
| | | "version": "3.4.10", |
| | | "resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1601823880483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz", |
| | |
| | | "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1600441238751&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz", |
| | | "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM=" |
| | | }, |
| | | "vue-baidu-map": { |
| | | "version": "0.21.22", |
| | | "resolved": "https://registry.npmjs.org/vue-baidu-map/-/vue-baidu-map-0.21.22.tgz", |
| | | "integrity": "sha512-WQMPCih4UTh0AZCKKH/OVOYnyAWjfRNeK6BIeoLmscyY5aF8zzlJhz/NOHLb3mdztIpB0Z6aohn4Jd9mfCSjQw==", |
| | | "requires": { |
| | | "bmaplib.curveline": "^1.0.0", |
| | | "bmaplib.heatmap": "^1.0.4", |
| | | "bmaplib.lushu": "^1.0.7", |
| | | "bmaplib.markerclusterer": "^1.0.13", |
| | | "markdown-it": "^8.4.0" |
| | | } |
| | | }, |
| | | "vue-clipboard2": { |
| | | "version": "0.3.1", |
| | | "resolved": "https://registry.npm.taobao.org/vue-clipboard2/download/vue-clipboard2-0.3.1.tgz", |
| | |
| | | "moment": "^2.29.1", |
| | | "postcss-pxtorem": "^5.1.1", |
| | | "vue": "^2.6.11", |
| | | "vue-baidu-map": "^0.21.22", |
| | | "vue-clipboard2": "^0.3.1", |
| | | "vue-cookies": "^1.7.4", |
| | | "vue-router": "^3.1.6" |
New file |
| | |
| | | /** |
| | | * 经纬度转换 |
| | | */ |
| | | export default { |
| | | PI: 3.1415926535897932384626, |
| | | //PI: 3.14159265358979324, |
| | | x_pi: (3.1415926535897932384626 * 3000.0) / 180.0, |
| | | delta: function (lat, lng) { |
| | | // Krasovsky 1940 |
| | | // |
| | | // a = 6378245.0, 1/f = 298.3 |
| | | // b = a * (1 - f) |
| | | // ee = (a^2 - b^2) / a^2; |
| | | var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。 |
| | | var ee = 0.00669342162296594323; // ee: 椭球的偏心率。 |
| | | var dLat = this.transformLat(lng - 105.0, lat - 35.0); |
| | | var dLng = this.transformLng(lng - 105.0, lat - 35.0); |
| | | var radLat = (lat / 180.0) * this.PI; |
| | | var magic = Math.sin(radLat); |
| | | magic = 1 - ee * magic * magic; |
| | | var sqrtMagic = Math.sqrt(magic); |
| | | dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * this.PI); |
| | | dLng = (dLng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * this.PI); |
| | | return { |
| | | lat: dLat, |
| | | lng: dLng |
| | | }; |
| | | }, |
| | | /** |
| | | * WGS-84 to GCJ-02 GPS坐标转中国坐标 |
| | | * @param {number} wgsLat GPS纬度 |
| | | * @param {number} wgsLng GPS经度 |
| | | * @return {object} 返回中国坐标经纬度对象 |
| | | */ |
| | | GPSToChina: function (wgsLat, wgsLng) { |
| | | if (this.outOfChina(wgsLat, wgsLng)) return { |
| | | lat: wgsLat, |
| | | lng: wgsLng |
| | | }; |
| | | var d = this.delta(wgsLat, wgsLng); |
| | | return { |
| | | lat: Number(wgsLat) + Number(d.lat), |
| | | lng: Number(wgsLng) + Number(d.lng) |
| | | }; |
| | | }, |
| | | /** |
| | | * GCJ-02 to WGS-84 中国标准坐标转GPS坐标 |
| | | * @param {number} gcjLat 中国标准坐标纬度 |
| | | * @param {number} gcjLng 中国标准坐标经度 |
| | | * @return {object} 返回GPS经纬度对象 |
| | | */ |
| | | chinaToGPS: function (gcjLat, gcjLng) { |
| | | if (this.outOfChina(gcjLat, gcjLng)) return { |
| | | lat: gcjLat, |
| | | lng: gcjLng |
| | | }; |
| | | var d = this.delta(gcjLat, gcjLng); |
| | | return { |
| | | lat: Number(gcjLat) - Number(d.lat), |
| | | lng: Number(gcjLng) - Number(d.lng) |
| | | }; |
| | | }, |
| | | /** |
| | | * GCJ-02 to WGS-84 exactly 中国标准坐标转GPS坐标(精确) |
| | | * @param {number} gcjLat 中国标准坐标纬度 |
| | | * @param {number} gcjLng 中国标准坐标经度 |
| | | * @return {object} 返回GPS经纬度对象(精确) |
| | | */ |
| | | chinaToGPSExact: function (gcjLat, gcjLng) { |
| | | var initDelta = 0.01; |
| | | var threshold = 0.000000001; |
| | | var dLat = initDelta, |
| | | dLng = initDelta; |
| | | var mLat = gcjLat - dLat, |
| | | mLng = gcjLng - dLng; |
| | | var pLat = gcjLat + dLat, |
| | | pLng = gcjLng + dLng; |
| | | var wgsLat, |
| | | wgsLng, |
| | | i = 0; |
| | | while (1) { |
| | | wgsLat = (mLat + pLat) / 2; |
| | | wgsLng = (mLng + pLng) / 2; |
| | | var tmp = this.gcj_encrypt(wgsLat, wgsLng); |
| | | dLat = tmp.lat - gcjLat; |
| | | dLng = tmp.lng - gcjLng; |
| | | if (Math.abs(dLat) < threshold && Math.abs(dLng) < threshold) break; |
| | | |
| | | if (dLat > 0) pLat = wgsLat; |
| | | else mLat = wgsLat; |
| | | if (dLng > 0) pLng = wgsLng; |
| | | else mLng = wgsLng; |
| | | |
| | | if (++i > 10000) break; |
| | | } |
| | | //console.log(i); |
| | | return { |
| | | lat: wgsLat, |
| | | lng: wgsLng |
| | | }; |
| | | }, |
| | | /** |
| | | * GCJ-02 to BD-09 中国标准坐标转百度坐标(精确) |
| | | * @param {number} gcjLat 中国标准坐标纬度 |
| | | * @param {number} gcjLng 中国标准坐标经度 |
| | | * @return {object} 返回百度经纬度对象 |
| | | */ |
| | | chinaToBaidu: function (gcjLat, gcjLng) { |
| | | var x = gcjLng, |
| | | y = gcjLat; |
| | | var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi); |
| | | var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi); |
| | | var bdLng = z * Math.cos(theta) + 0.0065; |
| | | var bdLat = z * Math.sin(theta) + 0.006; |
| | | return { |
| | | lat: bdLat, |
| | | lng: bdLng |
| | | }; |
| | | }, |
| | | /** |
| | | * BD-09 to GCJ-02 百度坐标转中国标准坐标 |
| | | * @param {number} bdLat 百度坐标纬度 |
| | | * @param {number} bdLng 百度坐标经度 |
| | | * @return {object} 返回中国标准经纬度对象 |
| | | */ |
| | | baiduToChina: function (bdLat, bdLng) { |
| | | var x = bdLng - 0.0065, |
| | | y = bdLat - 0.006; |
| | | var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi); |
| | | var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi); |
| | | var gcjLng = z * Math.cos(theta); |
| | | var gcjLat = z * Math.sin(theta); |
| | | return { |
| | | lat: gcjLat, |
| | | lng: gcjLng |
| | | }; |
| | | }, |
| | | /** |
| | | * BD-09 to GCJ-02 百度坐标转gps坐标 |
| | | * @param {number} bdLat 百度坐标纬度 |
| | | * @param {number} bdLng 百度坐标经度 |
| | | * @return {object} 返回gps经纬度对象 |
| | | */ |
| | | baiduToGPS: function (bdLat, bdLng) { |
| | | let china = this.baiduToChina(bdLat, bdLng); |
| | | return this.chinaToGPS(china.lat, china.lng); |
| | | }, |
| | | /** |
| | | * WGS-84 to to BD-09 GPS坐标转Baidu坐标 |
| | | * @param {number} gpsLat GPS纬度 |
| | | * @param {number} gpsLng GPS经度 |
| | | * @return {object} 返回百度经纬度对象 |
| | | */ |
| | | GPSToBaidu: function (gpsLat, gpsLng) { |
| | | var china = this.GPSToChina(gpsLat, gpsLng); |
| | | return this.chinaToBaidu(china.lat, china.lng); |
| | | }, |
| | | /** |
| | | * WGS-84 to Web mercator GPS坐标转墨卡托坐标 |
| | | * @param {number} wgsLat GPS纬度 |
| | | * @param {number} wgsLng GPS经度 |
| | | * @return {object} 返回墨卡托经纬度对象 |
| | | */ |
| | | GPSToMercator: function (wgsLat, wgsLng) { |
| | | var x = (wgsLng * 20037508.34) / 180; |
| | | var y = Math.log(Math.tan(((90 + wgsLat) * this.PI) / 360)) / (this.PI / 180); |
| | | y = (y * 20037508.34) / 180; |
| | | return { |
| | | lat: y, |
| | | lng: x |
| | | }; |
| | | /* |
| | | if ((Math.abs(wgsLng) > 180 || Math.abs(wgsLat) > 90)) |
| | | return null; |
| | | var x = 6378137.0 * wgsLng * 0.017453292519943295; |
| | | var a = wgsLat * 0.017453292519943295; |
| | | var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a))); |
| | | return {'lat' : y, 'lng' : x}; |
| | | //*/ |
| | | }, |
| | | /** |
| | | * Web mercator to WGS-84 墨卡托坐标转GPS坐标 |
| | | * @param {number} mercatorLat 墨卡托纬度 |
| | | * @param {number} mercatorLng 墨卡托经度 |
| | | * @return {object} 返回GPS经纬度对象 |
| | | */ |
| | | mercatorToGPS: function (mercatorLat, mercatorLng) { |
| | | var x = (mercatorLng / 20037508.34) * 180; |
| | | var y = (mercatorLat / 20037508.34) * 180; |
| | | y = (180 / this.PI) * (2 * Math.atan(Math.exp((y * this.PI) / 180)) - this.PI / 2); |
| | | return { |
| | | lat: y, |
| | | lng: x |
| | | }; |
| | | /* |
| | | if (Math.abs(mercatorLng) < 180 && Math.abs(mercatorLat) < 90) |
| | | return null; |
| | | if ((Math.abs(mercatorLng) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892)) |
| | | return null; |
| | | var a = mercatorLng / 6378137.0 * 57.295779513082323; |
| | | var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0); |
| | | var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323; |
| | | return {'lat' : y, 'lng' : x}; |
| | | //*/ |
| | | }, |
| | | /** |
| | | * 两点之间的距离 |
| | | * @param {number} latA 起点纬度 |
| | | * @param {number} lngA 起点经度 |
| | | * @param {number} latB 终点纬度 |
| | | * @param {number} lngB 终点经度 |
| | | * @return {number} 返回距离(米) |
| | | */ |
| | | distance: function (latA, lngA, latB, lngB) { |
| | | var earthR = 6371000; |
| | | var x = Math.cos((latA * this.PI) / 180) * Math.cos((latB * this.PI) / 180) * Math.cos(((lngA - lngB) * this.PI) / 180); |
| | | var y = Math.sin((latA * this.PI) / 180) * Math.sin((latB * this.PI) / 180); |
| | | var s = x + y; |
| | | if (s > 1) s = 1; |
| | | if (s < -1) s = -1; |
| | | var alpha = Math.acos(s); |
| | | var distance = alpha * earthR; |
| | | return distance; |
| | | }, |
| | | /** |
| | | * 是否在中国之外 |
| | | * @param {number} lat 纬度 |
| | | * @param {number} lng 经度 |
| | | * @return {boolean]} 返回结果真或假 |
| | | */ |
| | | outOfChina: function (lat, lng) { |
| | | if (lat < 72.004 || lat > 137.8347) return true; |
| | | if (lng < 0.8293 || lng > 55.8271) return true; |
| | | return false; |
| | | }, |
| | | transformLat: function (x, y) { |
| | | var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); |
| | | ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0; |
| | | ret += ((20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin((y / 3.0) * this.PI)) * 2.0) / 3.0; |
| | | ret += ((160.0 * Math.sin((y / 12.0) * this.PI) + 320 * Math.sin((y * this.PI) / 30.0)) * 2.0) / 3.0; |
| | | return ret; |
| | | }, |
| | | transformLng: function (x, y) { |
| | | var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); |
| | | ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0; |
| | | ret += ((20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin((x / 3.0) * this.PI)) * 2.0) / 3.0; |
| | | ret += ((150.0 * Math.sin((x / 12.0) * this.PI) + 300.0 * Math.sin((x / 30.0) * this.PI)) * 2.0) / 3.0; |
| | | return ret; |
| | | } |
| | | }; |
New file |
| | |
| | | <template> |
| | | <div id="devicePosition" style="height: 100%"> |
| | | <el-container style="height: 100%"> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> |
| | | <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span> |
| | | </div> |
| | | <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;"> |
| | | <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button> |
| | | <!-- <span class="demonstration">从</span> --> |
| | | <el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> |
| | | <el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> |
| | | <el-button-group> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button> |
| | | <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button> |
| | | </el-button-group> |
| | | <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag> |
| | | <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number> |
| | | <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag> |
| | | <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number> |
| | | <el-button-group> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button> |
| | | </el-button-group> |
| | | <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox> |
| | | </div> |
| | | <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);"> |
| | | <div class="baidumap" id="allmap"></div> |
| | | </div> |
| | | </el-main> |
| | | </el-container> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from "./UiHeader.vue"; |
| | | import moment from "moment"; |
| | | import geoTools from "./GeoConvertTools.js"; |
| | | export default { |
| | | name: "devicePosition", |
| | | components: { |
| | | uiHeader, |
| | | }, |
| | | data() { |
| | | return { |
| | | pickerOptions: { |
| | | shortcuts: [{ |
| | | text: '今天', |
| | | onClick(picker) { |
| | | picker.$emit('pick', new Date()); |
| | | } |
| | | }, { |
| | | text: '昨天', |
| | | onClick(picker) { |
| | | const date = new Date(); |
| | | date.setTime(date.getTime() - 3600 * 1000 * 24); |
| | | picker.$emit('pick', date); |
| | | } |
| | | }, { |
| | | text: '一周前', |
| | | onClick(picker) { |
| | | const date = new Date(); |
| | | date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit('pick', date); |
| | | } |
| | | }] |
| | | }, |
| | | deviceId: this.$route.params.deviceId, |
| | | showHistoryPosition: false, //显示历史轨迹 |
| | | startTime: null, |
| | | endTime: null, |
| | | searchFrom: null, |
| | | searchTo: null, |
| | | expired: 600, |
| | | interval: 5, |
| | | mobilePositionList: [], |
| | | mapPointList: [], |
| | | parentChannelId: this.$route.params.parentChannelId, |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | total: 0, |
| | | beforeUrl: "/videoList", |
| | | isLoging: false, |
| | | autoList: false, |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.initData(); |
| | | this.initBaiduMap(); |
| | | if (this.autoList) { |
| | | this.updateLooper = setInterval(this.initData, 5000); |
| | | } |
| | | }, |
| | | destroyed() { |
| | | // this.$destroy("videojs"); |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function () { |
| | | // if (this.parentChannelId == "" || this.parentChannelId == 0) { |
| | | // this.getDeviceChannelList(); |
| | | // } else { |
| | | // this.showSubchannels(); |
| | | // } |
| | | }, |
| | | initParam: function () { |
| | | // this.deviceId = this.$route.params.deviceId; |
| | | // this.parentChannelId = this.$route.params.parentChannelId; |
| | | // this.currentPage = parseInt(this.$route.params.page); |
| | | // this.count = parseInt(this.$route.params.count); |
| | | // if (this.parentChannelId == "" || this.parentChannelId == 0) { |
| | | // this.beforeUrl = "/videoList"; |
| | | // } |
| | | }, |
| | | initBaiduMap() { |
| | | this.map = new BMap.Map("allmap"); // 创建地图实例 |
| | | let points = []; |
| | | let point = new BMap.Point(116.231398, 39.567445); // 创建点坐标 |
| | | this.map.centerAndZoom(point, 5); // 初始化地图,设置中心点坐标和地图级别 |
| | | this.map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放 |
| | | this.map.addControl(new BMap.NavigationControl()); |
| | | this.map.addControl(new BMap.ScaleControl()); |
| | | this.map.addControl(new BMap.OverviewMapControl()); |
| | | this.map.addControl(new BMap.MapTypeControl()); |
| | | //map.setMapStyle({ style: 'midnight' }) //地图风格 |
| | | }, |
| | | currentChange: function (val) { |
| | | // var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`; |
| | | // console.log(url); |
| | | // this.$router.push(url).then(() => { |
| | | // this.initParam(); |
| | | // this.initData(); |
| | | // }); |
| | | }, |
| | | handleSizeChange: function (val) { |
| | | // var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`; |
| | | // this.$router.push(url).then(() => { |
| | | // this.initParam(); |
| | | // this.initData(); |
| | | // }); |
| | | }, |
| | | showDevice: function () { |
| | | this.$router.push(this.beforeUrl).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }); |
| | | }, |
| | | autoListChange: function () { |
| | | if (this.autoList) { |
| | | this.updateLooper = setInterval(this.initData, 1500); |
| | | } else { |
| | | window.clearInterval(this.updateLooper); |
| | | } |
| | | }, |
| | | showHistoryPath: function () { |
| | | this.map.clearOverlays(); |
| | | this.mapPointList = []; |
| | | this.mobilePositionList = []; |
| | | if (!!this.searchFrom) { |
| | | this.startTime = this.toGBString(this.searchFrom); |
| | | console.log(this.startTime); |
| | | } else{ |
| | | this.startTime = null; |
| | | } |
| | | if (!!this.searchTo) { |
| | | this.endTime = this.toGBString(this.searchTo); |
| | | console.log(this.endTime); |
| | | } else { |
| | | this.endTime = null; |
| | | } |
| | | let self = this; |
| | | this.$axios.get(`/api/positions/${this.deviceId}/history`, { |
| | | params: { |
| | | start: self.startTime, |
| | | end: self.endTime, |
| | | }, |
| | | }) |
| | | .then(function (res) { |
| | | self.total = res.data.length; |
| | | self.mobilePositionList = res.data; |
| | | console.log(self.mobilePositionList); |
| | | // 防止出现表格错位 |
| | | self.$nextTick(() => { |
| | | self.showMarkPoints(self); |
| | | }); |
| | | }) |
| | | .catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | showLatestPosition: function() { |
| | | this.map.clearOverlays(); |
| | | this.mapPointList = []; |
| | | this.mobilePositionList = []; |
| | | let self = this; |
| | | this.$axios.get(`/api/positions/${this.deviceId}/latest`) |
| | | .then(function (res) { |
| | | console.log(res.data); |
| | | self.total = res.data.length; |
| | | self.mobilePositionList.push(res.data); |
| | | console.log(self.mobilePositionList); |
| | | // 防止出现表格错位 |
| | | self.$nextTick(() => { |
| | | self.showMarkPoints(self); |
| | | }); |
| | | }) |
| | | .catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | subscribeMobilePosition: function() { |
| | | let self = this; |
| | | this.$axios.get(`/api/positions/${this.deviceId}/subscribe`, { |
| | | params: { |
| | | expires: self.expired, |
| | | interval: self.interval, |
| | | }, |
| | | }) |
| | | .then(function (res) { |
| | | console.log(res.data); |
| | | }) |
| | | .catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | unSubscribeMobilePosition: function() { |
| | | let self = this; |
| | | this.$axios.get(`/api/positions/${this.deviceId}/subscribe`, { |
| | | params: { |
| | | expires: 0, |
| | | interval: self.interval, |
| | | }, |
| | | }) |
| | | .then(function (res) { |
| | | console.log(res.data); |
| | | }) |
| | | .catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | toGBString: function (dateTime) { |
| | | return ( |
| | | dateTime.getFullYear() + |
| | | "-" + this.twoDigits(dateTime.getMonth() + 1) + |
| | | "-" + this.twoDigits(dateTime.getDate()) + |
| | | "T" + this.twoDigits(dateTime.getHours()) + |
| | | ":" + this.twoDigits(dateTime.getMinutes()) + |
| | | ":" + this.twoDigits(dateTime.getSeconds()) |
| | | ); |
| | | }, |
| | | twoDigits: function (num) { |
| | | if (num < 10) { |
| | | return "0" + num; |
| | | } else { |
| | | return "" + num; |
| | | } |
| | | }, |
| | | showMarkPoints: function(self) { |
| | | let that = self; |
| | | let npointJ = null; |
| | | let npointW = null; |
| | | let point = null; |
| | | for (let i = 0; i < self.mobilePositionList.length; i++) { |
| | | if (self.mobilePositionList[i].geodeticSystem == "BD-09") { |
| | | npointJ = self.mobilePositionList[i].cnLng; |
| | | npointW = self.mobilePositionList[i].cnLat; |
| | | point = new BMap.Point(npointJ, npointW); |
| | | } else { |
| | | npointJ = self.mobilePositionList[i].longitude; |
| | | npointW = self.mobilePositionList[i].latitude; |
| | | let bd2 = geoTools.GPSToBaidu(npointJ, npointW); |
| | | point = new BMap.Point(bd2.lat, bd2.lng); |
| | | } |
| | | self.mapPointList.push(point); |
| | | let marker = new BMap.Marker(point); // 创建标注 |
| | | self.map.addOverlay(marker); // 将标注添加到地图中 |
| | | //提示信息 可以解析 HTML标签以及CSS |
| | | let infoWindow = new BMap.InfoWindow(`<p style='text-align:left;font-weight:800'>设备: ${self.mobilePositionList[i].deviceId}</p> |
| | | <p style='text-align:left;font-weight:0'>时间: ${self.mobilePositionList[i].time}</p>`); |
| | | // 鼠标移上标注点要发生的事 |
| | | marker.addEventListener("mouseover", function () { |
| | | this.openInfoWindow(infoWindow); |
| | | }); |
| | | // 鼠标移开标注点要发生的事 |
| | | marker.addEventListener("mouseout", function () { |
| | | this.closeInfoWindow(infoWindow); |
| | | }); |
| | | // 鼠标点击标注点要发生的事情 |
| | | marker.addEventListener("click", function () { |
| | | alert("点击"); |
| | | }); |
| | | } |
| | | let view = that.map.getViewport(eval(self.mapPointList)); |
| | | that.map.centerAndZoom(view.center, view.zoom); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | |
| | | .baidumap { |
| | | width: 100%; |
| | | height: 100%; |
| | | border: none; |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | margin: auto; |
| | | } |
| | | |
| | | /* 去除百度地图版权那行字 和 百度logo */ |
| | | .baidumap > .BMap_cpyCtrl { |
| | | display: none !important; |
| | | } |
| | | .baidumap > .anchorBL { |
| | | display: none !important; |
| | | } |
| | | </style> |
| | |
| | | <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button> |
| | | </div> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer"></devicePlayer> |
| | | <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> |
| | | <!--设备列表--> |
| | | <el-table :data="deviceList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" width="180" align="center"> |
| | |
| | | </el-table-column> |
| | | <el-table-column prop="channelCount" label="通道数" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="180" align="center"> |
| | | <el-table-column label="状态" width="80" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="240" align="center" fixed="right"> |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button> |
| | | <el-button size="mini" icon="el-icon-s-open" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">查看通道</el-button> |
| | | <el-button size="mini" icon="el-icon-s-open" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">移动位置</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from './UiHeader.vue' |
| | | export default { |
| | | name: 'app', |
| | | components: { |
| | |
| | | console.log(JSON.stringify(row)) |
| | | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); |
| | | }, |
| | | |
| | | showDevicePosition: function(row) { |
| | | console.log(JSON.stringify(row)) |
| | | this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); |
| | | }, |
| | | |
| | | //gb28181平台对接 |
| | | //刷新设备信息 |
| | |
| | | }, |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function(itemData) { |
| | | let deviceId = this.currentDevice.deviceId; |
| | | let channelId = itemData.channelId; |
| | | console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/' + deviceId + '/' + channelId |
| | | }).then(function(res) { |
| | | let ssrc = res.data.ssrc; |
| | | that.$refs.devicePlayer.play(ssrc,deviceId,channelId); |
| | | }).catch(function(e) { |
| | | }); |
| | | // let deviceId = this.currentDevice.deviceId; |
| | | // let channelId = itemData.channelId; |
| | | // console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | // let that = this; |
| | | // this.$axios({ |
| | | // method: 'get', |
| | | // url: '/api/play/' + deviceId + '/' + channelId |
| | | // }).then(function(res) { |
| | | // let ssrc = res.data.ssrc; |
| | | // that.$refs.devicePlayer.play(ssrc,deviceId,channelId); |
| | | // }).catch(function(e) { |
| | | // }); |
| | | }, |
| | | transportChange: function (row) { |
| | | console.log(row); |
| | |
| | | import { Notification } from 'element-ui'; |
| | | import Fingerprint2 from 'fingerprintjs2'; |
| | | |
| | | // 生成唯一ID |
| | | // 生成唯一ID |
| | | Fingerprint2.get(function(components) { |
| | | const values = components.map(function(component,index) { |
| | | if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样 |
| | | if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样 |
| | | return component.value.replace(/\bNetType\/\w+\b/, ''); |
| | | } |
| | | return component.value; |
| | | }) |
| | | //console.log(values) //使用的浏览器信息npm |
| | | // 生成最终id |
| | | //console.log(values) //使用的浏览器信息npm |
| | | // 生成最终id |
| | | let port = window.location.port; |
| | | console.log(port); |
| | | const fingerPrint = Fingerprint2.x64hash128(values.join(port), 31) |
| | | Vue.prototype.$browserId = fingerPrint; |
| | | console.log("唯一标识码:" + fingerPrint); |
| | | console.log("唯一标识码:" + fingerPrint); |
| | | }); |
| | | |
| | | Vue.use(VueClipboard); |
| | |
| | | import control from '../components/control.vue' |
| | | import videoList from '../components/videoList.vue' |
| | | import channelList from '../components/channelList.vue' |
| | | import devicePosition from '../components/devicePosition.vue' |
| | | import login from '../components/Login.vue' |
| | | |
| | | const originalPush = VueRouter.prototype.push |
| | |
| | | name: 'channelList', |
| | | component: channelList, |
| | | }, |
| | | { |
| | | path: '/devicePosition/:deviceId/:parentChannelId/:count/:page', |
| | | name: 'devicePosition', |
| | | component: devicePosition, |
| | | }, |
| | | ] |
| | | }) |