24 files modified
7 files added
| | |
| | | *.sln |
| | | *.sw* |
| | | *.lock |
| | | vue.config.js |
| | |
| | | "actived": false |
| | | }, |
| | | { |
| | | "label": "地图模式", |
| | | "id": "SupervisoryMap", |
| | | "widgetClass": "widgets/supervisoryMap/SupervisoryMap", |
| | | "type": "sider", |
| | | "cssPath": "widgets/supervisoryMap/SupervisoryMap.css", |
| | | "actived": false |
| | | }, |
| | | { |
| | | "label": "洪水风险", |
| | | "id": "MapBrowseWidgetCopy", |
| | | "widgetClass": "widgets/mapBrowsecopy/MapBrowseWidgetCopy", |
| New file |
| | |
| | | define([ |
| | | "dojo/_base/declare", |
| | | "dojo/_base/lang", |
| | | "dojo/_base/array", |
| | | "dojo/on", |
| | | "dojo/fx", |
| | | "dojox/gfx", |
| | | "dojox/gfx/fx", |
| | | "dojox/gesture/tap", |
| | | "esri/SpatialReference", |
| | | "esri/geometry/Extent", |
| | | "esri/geometry/Multipoint", |
| | | "esri/geometry/Point", |
| | | "esri/geometry/Polygon", |
| | | "esri/geometry/ScreenPoint", |
| | | "esri/geometry/webMercatorUtils", |
| | | "esri/geometry/geometryEngine", |
| | | "esri/graphic", |
| | | "esri/Color", |
| | | "esri/renderers/ClassBreaksRenderer", |
| | | "esri/symbols/Font", |
| | | "esri/symbols/SimpleMarkerSymbol", |
| | | "esri/symbols/SimpleFillSymbol", |
| | | "esri/symbols/SimpleLineSymbol", |
| | | "esri/symbols/TextSymbol", |
| | | "esri/dijit/PopupTemplate", |
| | | "esri/layers/GraphicsLayer" |
| | | ], function ( |
| | | declare, lang, arrayUtils, on, coreFx, gfx, fx, tap, |
| | | SpatialReference, Extent, Multipoint, Point, Polygon, ScreenPoint, webMercatorUtils, geometryEngine, Graphic, |
| | | Color, ClassBreaksRenderer, Font, SimpleMarkerSymbol, SimpleFillSymbol, SimpleLineSymbol, TextSymbol, |
| | | PopupTemplate, GraphicsLayer |
| | | ) { |
| | | return declare([GraphicsLayer], { |
| | | constructor: function (options) { |
| | | /* options description: |
| | | spatialReference: default 102100. A SpatialReference object using the wkid of that data. |
| | | preClustered (boolean) : default false. Whether the data is pre-clustered or not. If true the addPreClusteredData method should be used to add data. |
| | | If false use addData method and clusters will be calculated within the layer. |
| | | clusterRatio (number): default 75. When not pre clustered this is the ratio to divide the width and height of the map by which is used to draw up a grid to represent cluster areas. Experiment based on your data. |
| | | displaySubTypeFlares (boolean): default false. Whether to dipslay flares for sub types (ie the count of a property). If this is true, then subTypeFlareProperty must also be set |
| | | subTypeFlareProperty (string): default null. If specified and displaySubTypeFlares is true, layer will display flares that contain a count of the objects that have the same value for the configured property. |
| | | flareColor (esri/Color) : default new Color([0, 0, 0, 0.5]). The color for flares. |
| | | maxFlareCount (number): default 8. The max number of flares to display. If this is too high they may overlap, depends on the size of the cluster symbols. |
| | | displaySingleFlaresAtCount (number): default 8. If a cluster contains this count or less it will display flare that represent single objects. If it contains greater than this count it will display sub type flares if they have been configured to be displayed. |
| | | singleFlareTooltipProperty (string): default null. Property name to get the values for display in a single point flares tooltips. |
| | | textSymbol (esri/symbols/TextSymbol): default set below. The text symbol to use in clusters |
| | | flareShowMode (string): default 'mouse'. Must be 'mouse' or 'tap'. On a mouse enabled device whether to show the flares on mouse enter and hide on mouse leave, or on tap / click. Devices with no mouse will behave like 'tap' anyway. |
| | | clusteringBegin (function): default null. A basic callback function that get's fired when clustering is beginning. |
| | | clusteringComplete (function): default null. A basic callback function that get's fired when clustering is complete. |
| | | clusterAreaDisplay (string): default null. Can be either 'always' or 'hover'. 'always' will constantly display the cluster area, 'hover' will only display it on hover of cluster object |
| | | The cluster area is a ploygon of the total area covered by the points in a cluster. If using preClustered data, each cluster object must contain a property called 'points' which is an array of points for every point in the cluster. example: cluster.points = [[x1, y1], [x2, y2], [x3, y3]]; |
| | | clusterAreaRenderer (Renderer): default null. This is required if clusterAreaDisplay is set. This can be set in options constructor object or by calling setRenderer as the second argument. |
| | | xPropertyName (string): default 'x'. This is the name of the field in the dataset that represents the x coordinate. |
| | | yPropertyName (string): default 'y'. This is the name of the field in the dataset that represents the y coordinate. |
| | | idPropertyName (string): default null. This is the name of the field in the dataset that represents a unique id which can be used to identify the flare. This is usefull when you may have multiple points with the same lat/long. |
| | | */ |
| | | |
| | | //set options from constructor parameter or set defaults |
| | | options = options || {}; |
| | | this.spatialRef = options.spatialReference || new SpatialReference({"wkid": 102100}); |
| | | this.preClustered = options.preClustered === true; |
| | | this.clusterRatio = options.clusterRatio || 75; |
| | | |
| | | this.displaySubTypeFlares = options.displaySubTypeFlares === true; |
| | | this.subTypeFlareProperty = options.subTypeFlareProperty || null; |
| | | |
| | | this.flareColor = options.flareColor || new Color([0, 0, 0, 0.5]); |
| | | this.maxFlareCount = options.maxFlareCount || 8; |
| | | this.displaySingleFlaresAtCount = options.displaySingleFlaresAtCount || 8; |
| | | this.singleFlareTooltipProperty = options.singleFlareTooltipProperty || null; |
| | | var defaultTextSymbol = new TextSymbol() |
| | | .setColor(new Color([255, 255, 255])) |
| | | .setAlign(Font.ALIGN_START) |
| | | .setFont(new Font("10pt").setWeight(Font.WEIGHT_BOLD).setFamily("calibri")) |
| | | .setVerticalAlignment("middle"); |
| | | defaultTextSymbol.font.size = 14; |
| | | this.textSymbol = options.textSymbol || defaultTextSymbol; |
| | | this.flareShowMode = options.flareShowMode || "mouse"; |
| | | |
| | | //a couple of callbacks - could make them into events on the layer, and/or have the clustering return deferreds. |
| | | this.clusteringBegin = options.clusteringBegin; |
| | | this.clusteringComplete = options.clusteringComplete; |
| | | |
| | | this.clusterAreaDisplay = options.clusterAreaDisplay; |
| | | this.clusterAreaRenderer = options.clusterAreaRenderer; |
| | | |
| | | this.xPropertyName = options.xPropertyName || 'x'; |
| | | this.yPropertyName = options.yPropertyName || 'y'; |
| | | this.idPropertyName = options.idPropertyName || null; |
| | | |
| | | if (this.clusterAreaDisplay && (this.clusterAreaDisplay !== 'always' && this.clusterAreaDisplay !== 'hover')) { |
| | | console.error("clusterAreaDisplay can only be 'always' or 'hover'."); |
| | | return; |
| | | } |
| | | |
| | | |
| | | if (this.flareShowMode !== "mouse" && this.flareShowMode !== "tap") { |
| | | console.error("flareShowMode option can only be 'mouse' or 'tap'"); |
| | | return; |
| | | } |
| | | |
| | | //init some stuff |
| | | this.animationMultipleType = { |
| | | combine: "combine", |
| | | chain: "chain" |
| | | }; |
| | | |
| | | this.events = []; |
| | | this.graphicEvents = []; |
| | | this.animationsRunning = []; |
| | | this.clusters = []; |
| | | this.singles = []; |
| | | |
| | | }, |
| | | |
| | | |
| | | //#region override some GraphicsLayer methods |
| | | |
| | | //add an extra argument to setRenderer. It is an optional renderer for displaying the cluster areas. The clusterAreaRenderer can also be set in constructor. |
| | | setRenderer: function (renderer, clusterAreaRenderer) { |
| | | if (clusterAreaRenderer) { |
| | | this.clusterAreaRenderer = clusterAreaRenderer; |
| | | } |
| | | |
| | | return this.inherited(arguments); |
| | | }, |
| | | |
| | | _setMap: function (map, surface) { |
| | | this.map = map; |
| | | this.surface = surface; |
| | | |
| | | this.events.push(on(this.map, "resize", lang.hitch(this, this._mapResize))); |
| | | |
| | | //add pan and zoom events to limit to recluster |
| | | this.events.push(on(this.map, "extent-change", lang.hitch(this, this._clusterData))); |
| | | |
| | | //Handle click event at the map level |
| | | this.events.push(on(this.map, "click", lang.hitch(this, this._mapClick))); |
| | | |
| | | this.events.push(on(this.map.infoWindow, "show", lang.hitch(this, this._infoWindowShow))); |
| | | this.events.push(on(this.map.infoWindow, "hide", lang.hitch(this, this._infoWindowHide))); |
| | | |
| | | this.events.push(on(this, "graphic-draw", this._graphicDraw)); |
| | | this.events.push(on(this, "graphic-node-remove", this._graphicNodeRemove)); |
| | | |
| | | this.events.push(on(this, "mouse-over", this._graphicMouseOver)); |
| | | this.events.push(on(this, "mouse-out", this._graphicMouseOut)); |
| | | |
| | | return this.inherited(arguments); |
| | | }, |
| | | |
| | | |
| | | _unsetMap: function () { |
| | | this.inherited(arguments); |
| | | //remove events |
| | | for (var i = 0, len = this.events.length; i < len; i++) { |
| | | if (this.events[i]) { |
| | | this.events[i].remove(); |
| | | } |
| | | } |
| | | |
| | | for (i = 0, len = this.graphicEvents.length; i < len; i++) { |
| | | if (this.graphicEvents[i]) { |
| | | this.graphicEvents[i].remove(); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | onClick: function (evt) { |
| | | this._restoreInfoWindowSettings(); |
| | | |
| | | if (evt.graphic.attributes.isCluster) { |
| | | evt.stopPropagation(); |
| | | //this._activateCluster(evt.graphic); |
| | | this.map.infoWindow.hide(); |
| | | } else if (evt.graphic.attributes.isFlare) { |
| | | evt.stopPropagation(); |
| | | |
| | | var flareObject = this._getFlareFromGraphic(evt.graphic); |
| | | if (!flareObject) { |
| | | this._hideFlareDetail(); |
| | | this.map.infoWindow.hide(); |
| | | return; |
| | | } |
| | | |
| | | if (flareObject.isSummaryFlare || !flareObject.singleData) { |
| | | this._showFlareDetail(evt.graphic); |
| | | this.map.infoWindow.hide(); |
| | | return; |
| | | } |
| | | |
| | | //if we're clicking on a single data flare then show an info window |
| | | var graphic = evt.graphic; |
| | | |
| | | this.originalInfoWindow = { |
| | | highlight: lang.clone(this.map.infoWindow.get("highlight")), |
| | | anchor: lang.clone(this.map.infoWindow.anchor) |
| | | }; |
| | | |
| | | this.map.infoWindow.hide(); |
| | | this.map.infoWindow.clearFeatures(); |
| | | this.map.infoWindow.set("highlight", false); |
| | | this.map.infoWindow.setFeatures([graphic]); |
| | | |
| | | //when getting screen point make sure we use the location of the flare on screen, by converting the map point on the object. |
| | | var sp = this.map.toScreen({x: flareObject.mapPoint.x, y: flareObject.mapPoint.y}); |
| | | |
| | | //Could do something with the anchor of the info window here if wanted. The offsets can be a bit wacky as well. |
| | | //var anchor = this._getInfoWindowAnchor(flareObject.degree); |
| | | //this.map.infoWindow.anchor = anchor; |
| | | |
| | | this.map.infoWindow.cluster = this.activeCluster; |
| | | |
| | | //reset the geometry of the flare feature in the info window to be the actual location of the flared object, not the location of the flare graphic. |
| | | var p = webMercatorUtils.geographicToWebMercator(new Point(flareObject.singleData[this.xPropertyName], flareObject.singleData[this.yPropertyName], this.spatialRef)); |
| | | this.map.infoWindow.features[0].geometry = p; |
| | | this.map.infoWindow.show(sp); |
| | | |
| | | } |
| | | }, |
| | | |
| | | //Add a data point to be clustered. |
| | | //Each object passed in must contain an x and y property. |
| | | //Data should also contain whatever property is set in singleFlareTooltipProperty, so the flare tooltip has something to display for summary flares if needed |
| | | add: function (p) { |
| | | |
| | | |
| | | // if passed a graphic, just use the base GraphicsLayer's add method |
| | | if (p.declaredClass) { |
| | | this.inherited(arguments); |
| | | return; |
| | | } |
| | | |
| | | //if we got here, then we're adding a single object |
| | | //NOTE: Use this sparingly - better to use addData (or even better addPreClusteredData). |
| | | //If using add() to add a large amount of objects (eg: in a long loop), clusters and their elements will be removed and recreated when changes are applied to them,this can be expensive |
| | | //If you use addData and pass in an array clusters will only be created in the DOM once they have been fully calculated |
| | | |
| | | //can't add client side if preClustered is being used |
| | | if (this.preClustered) { |
| | | return; |
| | | } |
| | | |
| | | //get an extent that is in web mercator to make sure it's flat for extent checking |
| | | var webExtent = webMercatorUtils.project(map.extent, new SpatialReference({"wkid": 102100})); |
| | | if (!this.gridClusters || this.gridClusters.length === 0) { |
| | | this._createClusterGrid(); |
| | | } |
| | | |
| | | var obj = p; |
| | | if (!this.allData) { |
| | | this.allData = []; |
| | | } |
| | | |
| | | this.allData.push(obj); |
| | | |
| | | var xVal = obj[this.xPropertyName]; |
| | | var yVal = obj[this.yPropertyName]; |
| | | |
| | | //get a web merc lng/lat for extent checking. Use web merc as it's flat to cater for longitude pole |
| | | if (this.spatialRef.isWebMercator()) { |
| | | web = [xVal, yVal]; |
| | | } else { |
| | | web = webMercatorUtils.lngLatToXY(xVal, yVal); |
| | | } |
| | | |
| | | //filter by visible extent first |
| | | if (web[0] < webExtent.xmin || web[0] > webExtent.xmax || web[1] < webExtent.ymin || web[1] > webExtent.ymax) { |
| | | return; //not in the visible extent |
| | | } |
| | | |
| | | //loop cluster grid to see if it should be added to one |
| | | for (var j = 0, jLen = this.gridClusters.length; j < jLen; j++) { |
| | | var cl = this.gridClusters[j]; |
| | | |
| | | if (web[0] < cl.extent.xmin || web[0] > cl.extent.xmax || web[1] < cl.extent.ymin || web[1] > cl.extent.ymax) { |
| | | continue; //not here so carry on |
| | | } |
| | | |
| | | //recalc the x and y of the cluster by averaging the points again |
| | | cl.x = cl.clusterCount > 0 ? (xVal + (cl.x * cl.clusterCount)) / (cl.clusterCount + 1) : xVal; |
| | | cl.y = cl.clusterCount > 0 ? (yVal + (cl.y * cl.clusterCount)) / (cl.clusterCount + 1) : yVal; |
| | | |
| | | //push every point into the cluster so we have it for area display if required. This could be omitted if never checking areas, or on demand at least |
| | | if (this.clusterAreaDisplay) { |
| | | cl.points.push([xVal, yVal]); |
| | | } |
| | | |
| | | cl.clusterCount++; |
| | | |
| | | var subTypeExists = false; |
| | | for (var s = 0, sLen = cl.subTypeCounts.length; s < sLen; s++) { |
| | | if (cl.subTypeCounts[s].name === obj[this.subTypeFlareProperty]) { |
| | | cl.subTypeCounts[s].count++; |
| | | subTypeExists = true; |
| | | break; |
| | | } |
| | | } |
| | | if (!subTypeExists) { |
| | | cl.subTypeCounts.push({name: obj[this.subTypeFlareProperty], count: 1}); |
| | | } |
| | | |
| | | cl.singles.push(obj); |
| | | |
| | | if (cl.clusterCount === 1) { |
| | | //this was the only point in this cluster area so add a single |
| | | this._createSingle(obj); |
| | | } else { |
| | | if (cl.clusterCount === 2) { |
| | | //if it was previously a single remove the single. |
| | | var index = this.singles.indexOf(cl.singles[0]); |
| | | this.remove(cl.singles[0].graphic); |
| | | this.singles.splice(index, 1); |
| | | delete cl.singles[0].graphic; |
| | | } else { |
| | | //only remove if the count is > 2. Would have been a single previously. |
| | | this._removeCluster(cl); |
| | | } |
| | | this._createCluster(cl); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | clear: function () { |
| | | // Summary: Remove all clusters and data points. |
| | | |
| | | this.inherited(arguments); |
| | | |
| | | this.activeCluster = null; |
| | | this.activeFlareObject = null; |
| | | |
| | | //stop any animations that may still be running while clearing graphics |
| | | this._stopAnimations(); |
| | | |
| | | //remove all created cluster group elements |
| | | var node = this.getNode(); |
| | | dojo.query("g.cluster-group", node).forEach(dojo.destroy); |
| | | |
| | | //clear any graphic events |
| | | for (var i = 0, len = this.graphicEvents.length; i < len; i++) { |
| | | if (this.graphicEvents[i]) { |
| | | this.graphicEvents[i].remove(); |
| | | } |
| | | } |
| | | |
| | | // this.map.infoWindow.hide(); |
| | | // this.map.infoWindow.clearFeatures(); |
| | | |
| | | this.gridClusters = []; |
| | | this.clusters = []; |
| | | this.singles = []; |
| | | }, |
| | | |
| | | //#endregion |
| | | |
| | | //#region other event handlers |
| | | |
| | | _mapResize: function () { |
| | | //destroy any orphaned cluster group nodes |
| | | dojo.query("g.cluster-group:empty", this.getNode()).forEach(dojo.destroy); |
| | | }, |
| | | |
| | | _mapClick: function (e) { |
| | | if (!e.target) { |
| | | return; |
| | | } |
| | | |
| | | var targetClass = e.target.getAttribute("class"); |
| | | if (!targetClass || targetClass.indexOf("cluster-object") === -1) { |
| | | //if this was not a cluster object at all then clear any active one and return |
| | | this._clearActiveCluster(); |
| | | } else if (targetClass.indexOf("cluster-object") !== -1) { |
| | | //if click reached map click event and it is a cluster object, make sure an info window doesn't display for the cluster graphic |
| | | if (this.map.infoWindow.cluster) { |
| | | this._restoreInfoWindowSettings(); |
| | | } |
| | | this.map.infoWindow.hide(); |
| | | } |
| | | }, |
| | | |
| | | _graphicDraw: function (e) { |
| | | var g = e.graphic; |
| | | if (g.attributes.isCluster) { |
| | | //create the cluster graphics if this is a cluster being drawn |
| | | var cl = this._getClusterFromGraphic(g); |
| | | this._createClusterGraphic(cl); |
| | | if (this.activeCluster === cl) { |
| | | this._clearActiveCluster(); |
| | | } |
| | | } else if (g.attributes.isClusterArea) { |
| | | var sh = g.getShape(); |
| | | sh.moveToBack(); |
| | | } |
| | | |
| | | |
| | | return this.inherited(arguments); |
| | | }, |
| | | |
| | | _graphicNodeRemove: function (e) { |
| | | var g = e.graphic; |
| | | if (g.attributes.isCluster) { |
| | | //remove any group graphics related to this cluster as they'll be recreated when the node is redrawn. |
| | | var cl = this._getClusterFromGraphic(g); |
| | | if (cl) { |
| | | dojo.destroy(cl.groupShape.rawNode); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _graphicMouseOver: function (e) { |
| | | if (this.flareShowMode === "mouse") { |
| | | if (e.graphic.attributes.isCluster) { |
| | | //this._activateCluster(e.graphic); |
| | | } else if (e.graphic.attributes.isFlare) { |
| | | this._showFlareDetail(e.graphic); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _graphicMouseOut: function (e) { |
| | | if (e.graphic.attributes.isFlare) { |
| | | this._hideFlareDetail(); |
| | | } |
| | | }, |
| | | |
| | | |
| | | _infoWindowShow: function (e) { |
| | | if (typeof (this.map.infoWindow.features !== 'undefined') && this.map.infoWindow.features !== null) { |
| | | for (var i = 0; i < this.map.infoWindow.features.length; i++) { |
| | | if (typeof (this.map.infoWindow.features[i].attributes) !== 'undefined' && (this.map.infoWindow.features[i].attributes.isCluster || this.map.infoWindow.features[i].attributes.isClusterArea)) { |
| | | this.map.infoWindow.hide(); //if a cluster never show an info window |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _infoWindowHide: function (e) { |
| | | this.map.infoWindow.cluster = null; |
| | | }, |
| | | |
| | | |
| | | //#endregion |
| | | |
| | | |
| | | //#region extra public methods |
| | | |
| | | addPreClusteredData: function (data) { |
| | | /* |
| | | Add data that is preclustered - (ie clustered server side). |
| | | Data is an array, clusters must contain an x and y property as well as a clusterCount property. subTypeCounts is optional. |
| | | Clusters that have a count less than the this.displaySingleFlaresAtCount option must all contain the data for the single points in an array called singles |
| | | Singles should also be in the array, they only need to contain an x and y property. Singles should also contain whatever property is set in singleFlareTooltipProperty, so the flare tooltip has something to display for summary flares if needed |
| | | */ |
| | | |
| | | if (this.clusteringBegin) { |
| | | this.clusteringBegin(); |
| | | } |
| | | |
| | | this.allData = []; |
| | | this.preClustered = true; //if we're adding preclustered data, force this flag to true |
| | | for (var i = 0, len = data.length; i < len; i++) { |
| | | if (data[i].clusterCount) { |
| | | //this is a cluster as it contains clusterCount |
| | | var cl = data[i]; |
| | | this._createCluster(cl); |
| | | } else { |
| | | this._createSingle(data[i]); |
| | | } |
| | | } |
| | | |
| | | if (this.clusteringComplete) { |
| | | this.clusteringComplete(); |
| | | } |
| | | }, |
| | | |
| | | |
| | | addData: function (data) { |
| | | /* |
| | | Add data to be clustered. |
| | | Data is an array of objects. Each object passed in must contain an x and y property. |
| | | Data should also contain whatever property is set in singleFlareTooltipProperty if one is set, so the flare tooltip has something to display for summary flares if needed |
| | | This will also clear all data first. add() can be used to add single objects at any time. |
| | | */ |
| | | this.allData = data; |
| | | this._clusterData(); |
| | | }, |
| | | |
| | | |
| | | //#endregion |
| | | |
| | | |
| | | //#region internal stuff |
| | | |
| | | _restoreInfoWindowSettings: function () { |
| | | if (this.originalInfoWindow) { |
| | | this.map.infoWindow.set("highlight", this.originalInfoWindow.highlight); |
| | | this.map.infoWindow.anchor = this.originalInfoWindow.anchor; |
| | | } |
| | | }, |
| | | |
| | | _clusterData: function () { |
| | | |
| | | //this function currently only applies if not using preclustered data |
| | | if (this.preClustered) { |
| | | return; |
| | | } |
| | | |
| | | if (this.clusteringBegin) { |
| | | this.clusteringBegin(); |
| | | } |
| | | |
| | | this.clear(); |
| | | |
| | | //get an extent that is in web mercator to make sure it's flat for extent checking |
| | | //The webextent will need to be normalized since panning over the international dateline will cause |
| | | //cause the extent to shift outside the -180 to 180 degree window. If we don't normalize then the |
| | | //clusters will not be drawn if the map pans over the international dateline. |
| | | var webExtent = !this.map.extent.spatialReference.isWebMercator() ? webMercatorUtils.project(this.map.extent, new SpatialReference({"wkid": 102100})) : this.map.extent; |
| | | var normalizedWebExtent = webExtent.normalize(); |
| | | webExtent = normalizedWebExtent[0]; |
| | | |
| | | if (normalizedWebExtent.length > 1) { |
| | | webExtent = webExtent.union(normalizedWebExtent[1]); |
| | | this.extentIsUnioned = true; |
| | | } else { |
| | | this.extentIsUnioned = true; |
| | | } |
| | | |
| | | this._createClusterGrid(webExtent); |
| | | |
| | | var dataLength = this.allData.length; |
| | | var web, obj, xVal, yVal; |
| | | for (var i = 0; i < dataLength; i++) { |
| | | obj = this.allData[i]; |
| | | xVal = obj[this.xPropertyName]; |
| | | yVal = obj[this.yPropertyName]; |
| | | |
| | | //get a web merc lng/lat for extent checking. Use web merc as it's flat to cater for longitude pole |
| | | if (this.spatialRef.isWebMercator()) { |
| | | web = [xVal, yVal]; |
| | | } else { |
| | | web = webMercatorUtils.lngLatToXY(xVal, yVal); |
| | | } |
| | | |
| | | //filter by visible extent first |
| | | if (web[0] < webExtent.xmin || web[0] > webExtent.xmax || web[1] < webExtent.ymin || web[1] > webExtent.ymax) { |
| | | continue; |
| | | } |
| | | |
| | | //loop cluster grid to see if it should be added to one |
| | | for (var j = 0, jLen = this.gridClusters.length; j < jLen; j++) { |
| | | var cl = this.gridClusters[j]; |
| | | |
| | | if (web[0] < cl.extent.xmin || web[0] > cl.extent.xmax || web[1] < cl.extent.ymin || web[1] > cl.extent.ymax) { |
| | | continue; //not here so carry on |
| | | } |
| | | |
| | | //recalc the x and y of the cluster by averaging the points again |
| | | cl.x = cl.clusterCount > 0 ? (xVal + (cl.x * cl.clusterCount)) / (cl.clusterCount + 1) : xVal; |
| | | cl.y = cl.clusterCount > 0 ? (yVal + (cl.y * cl.clusterCount)) / (cl.clusterCount + 1) : yVal; |
| | | |
| | | //push every point into the cluster so we have it for area display if required. This could be omitted if never checking areas, or on demand at least |
| | | if (this.clusterAreaDisplay) { |
| | | cl.points.push([xVal, yVal]); |
| | | } |
| | | |
| | | cl.clusterCount++; |
| | | |
| | | var subTypeExists = false; |
| | | for (var s = 0, sLen = cl.subTypeCounts.length; s < sLen; s++) { |
| | | if (cl.subTypeCounts[s].name === obj[this.subTypeFlareProperty]) { |
| | | cl.subTypeCounts[s].count++; |
| | | subTypeExists = true; |
| | | break; |
| | | } |
| | | } |
| | | if (!subTypeExists) { |
| | | cl.subTypeCounts.push({name: obj[this.subTypeFlareProperty], count: 1}); |
| | | } |
| | | |
| | | cl.singles.push(obj); |
| | | } |
| | | } |
| | | |
| | | for (i = 0, len = this.gridClusters.length; i < len; i++) { |
| | | if (this.gridClusters[i].clusterCount === 1) { |
| | | this._createSingle(this.gridClusters[i].singles[0]); |
| | | } else if (this.gridClusters[i].clusterCount > 0) { |
| | | this._createCluster(this.gridClusters[i]); |
| | | } |
| | | } |
| | | |
| | | }, |
| | | |
| | | _createClusterGrid: function (webExtent) { |
| | | |
| | | //get the total amount of grid spaces based on the height and width of the map (divide it by clusterRatio) - then get the degrees for x and y |
| | | var xCount = Math.round(this.map.width / this.clusterRatio); |
| | | var yCount = Math.round(this.map.height / this.clusterRatio); |
| | | |
| | | //if the extent has been unioned due to normalization, double the count of x in the cluster grid as the unioning will halve it. |
| | | if (this.extentIsUnioned) { |
| | | xCount *= 2; |
| | | } |
| | | |
| | | var xw = (webExtent.xmax - webExtent.xmin) / xCount; |
| | | var yh = (webExtent.ymax - webExtent.ymin) / yCount; |
| | | |
| | | var gsxmin, gsxmax, gsymin, gsymax; |
| | | |
| | | //create an array of clusters that is a grid over the visible extent. Each cluster contains the extent (in web merc) that bounds the grid space for it. |
| | | this.gridClusters = []; |
| | | for (var i = 0; i < xCount; i++) { |
| | | gsxmin = webExtent.xmin + (xw * i); |
| | | gsxmax = gsxmin + xw; |
| | | for (var j = 0; j < yCount; j++) { |
| | | gsymin = webExtent.ymin + (yh * j); |
| | | gsymax = gsymin + yh; |
| | | var ext = new Extent({xmin: gsxmin, xmax: gsxmax, ymin: gsymin, ymax: gsymax}); |
| | | ext.setSpatialReference(new SpatialReference({"wkid": 102100})); |
| | | this.gridClusters.push({ |
| | | extent: ext, |
| | | clusterCount: 0, |
| | | subTypeCounts: [], |
| | | singles: [], |
| | | points: [] |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _createSingle: function (single) { |
| | | this.singles.push(single); |
| | | delete single.graphic; |
| | | var point = new Point(single[this.xPropertyName], single[this.yPropertyName], this.spatialRef); |
| | | var attributes = lang.clone(single); |
| | | var graphic = new Graphic(point, null, attributes, null); |
| | | single.graphic = graphic; |
| | | this.add(graphic); |
| | | }, |
| | | |
| | | _createCluster: function (cluster) { |
| | | |
| | | this.clusters.push(cluster); |
| | | |
| | | //add the graphic using the Graphics Layer add |
| | | var point = new Point(cluster.x, cluster.y, this.spatialRef); |
| | | |
| | | //clear some props as we may be recreating the cluster |
| | | delete cluster.graphic; |
| | | delete cluster.graphicShape; |
| | | delete cluster.groupShape; |
| | | |
| | | var attributes = { |
| | | x: cluster.x, |
| | | y: cluster.y, |
| | | clusterCount: cluster.clusterCount |
| | | } |
| | | |
| | | var areaGraphic; |
| | | if (this.clusterAreaDisplay && cluster.points && cluster.points.length > 0) { |
| | | if (!this.clusterAreaRenderer) { |
| | | console.error("_createCluster: clusterAreaRenderer must be set if clusterAreaDisplay is set."); |
| | | return; |
| | | } |
| | | |
| | | var mp = new Multipoint(this.spatialRef); |
| | | mp.points = cluster.points; |
| | | var area = geometryEngine.convexHull(mp, true); //use convex hull on the points to get the boundary |
| | | var areaAttr = lang.clone(attributes); |
| | | areaAttr.isClusterArea = true; |
| | | areaGraphic = new Graphic(area, null, areaAttr, null); |
| | | areaGraphic.setSymbol(this.clusterAreaRenderer.getSymbol(areaGraphic)); |
| | | this.add(areaGraphic); |
| | | areaGraphic.hide(); |
| | | } |
| | | |
| | | attributes.isCluster = true; |
| | | var graphic = new Graphic(point, null, attributes, null); |
| | | cluster.graphic = graphic; |
| | | cluster.areaGraphic = areaGraphic; |
| | | this.add(graphic); |
| | | |
| | | }, |
| | | |
| | | _createClusterGraphic: function (cluster) { |
| | | |
| | | if (cluster.groupShape) { |
| | | dojo.destroy(cluster.groupShape.rawNode); |
| | | } |
| | | |
| | | //create a group element to hold the cluster and text and other things |
| | | var groupShape = this.surface.createGroup(); |
| | | |
| | | //Note: dojo.addClass() doesn't seem to work on svg elements, that's why all the setAttributes for each shape. |
| | | groupShape.rawNode.setAttribute("class", "cluster-group cluster-object"); |
| | | cluster.groupShape = groupShape; |
| | | |
| | | //append the group to this layer's node |
| | | var layerNode = this.getNode(); |
| | | layerNode.appendChild(groupShape.rawNode); |
| | | |
| | | var gShape = cluster.graphic.getShape(); |
| | | if (!gShape) { |
| | | return; //couldn't get the graphic shape that was just added, it's probably not visible on the map |
| | | } |
| | | |
| | | //add an area graphic first if one has been set |
| | | var areaShape; |
| | | if (cluster.areaGraphic) { |
| | | if (this.clusterAreaDisplay === 'always') { |
| | | cluster.areaGraphic.show(); |
| | | } |
| | | areaShape = cluster.areaGraphic.getShape(); |
| | | if (areaShape) { |
| | | areaShape.rawNode.setAttribute("pointer-events", "none"); |
| | | } |
| | | } |
| | | |
| | | cluster.graphicShape = gShape; |
| | | cluster.graphicShape.rawNode.setAttribute("class", "cluster-object"); |
| | | groupShape.add(cluster.graphicShape); |
| | | |
| | | //add a text element for the label to display the count and add to the group |
| | | var shapeCenter = this._getShapeCenter(cluster.graphicShape); |
| | | var textShape = groupShape.createText({ |
| | | x: shapeCenter.x, |
| | | y: shapeCenter.y + (this.textSymbol.font.size / 2 - 2), |
| | | text: cluster.clusterCount, |
| | | align: 'middle' |
| | | }) |
| | | .setFont({ |
| | | size: this.textSymbol.font.size, |
| | | family: this.textSymbol.font.family, |
| | | weight: this.textSymbol.font.weight |
| | | }) |
| | | .setFill(this.textSymbol.color); |
| | | textShape.rawNode.setAttribute("class", "cluster-text-counts"); |
| | | textShape.rawNode.setAttribute("pointer-events", "none"); //remove pointer events from text |
| | | groupShape.add(textShape); |
| | | cluster.textShape = textShape; |
| | | |
| | | var anims = []; |
| | | //animate drawing of the cluster. |
| | | var create = fx.animateTransform({ |
| | | duration: 200, |
| | | shape: groupShape, |
| | | transform: [ |
| | | { |
| | | name: "scaleAt", |
| | | start: [0, 0, shapeCenter.x, shapeCenter.y], |
| | | end: [1, 1, shapeCenter.x, shapeCenter.y] |
| | | } |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | anims.push(create); |
| | | |
| | | //animate area drawing if it is visible now |
| | | if (this.clusterAreaDisplay === 'always' && areaShape) { |
| | | var areaCenter = this._getShapeCenter(areaShape); |
| | | var areaCreate = fx.animateTransform({ |
| | | duration: 200, |
| | | shape: areaShape, |
| | | transform: [ |
| | | { |
| | | name: "scaleAt", |
| | | start: [0, 0, areaCenter.x, areaCenter.y], |
| | | end: [1, 1, areaCenter.x, areaCenter.y] |
| | | } |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | anims.push(areaCreate); |
| | | } |
| | | |
| | | this._playAnimations(anims, this.animationMultipleType.combine); |
| | | |
| | | //add events |
| | | if (this.flareShowMode === "mouse") { |
| | | this.graphicEvents.push(on(groupShape, "mouseleave", lang.hitch(this, this._clearActiveCluster))); |
| | | } |
| | | }, |
| | | |
| | | _activateCluster: function (graphic) { |
| | | |
| | | var cluster = this._getClusterFromGraphic(graphic); |
| | | if (!cluster) { |
| | | return; |
| | | } |
| | | |
| | | if (this.activeCluster) { |
| | | this._clearActiveCluster(); |
| | | } |
| | | |
| | | this.activeCluster = cluster; |
| | | |
| | | var groupShape = cluster.groupShape; |
| | | var graphicShape = cluster.graphicShape; |
| | | groupShape.moveToFront(); |
| | | var center = this._getShapeCenter(graphicShape); |
| | | |
| | | var scaleAnims = []; |
| | | if (this.clusterAreaDisplay === 'hover') { |
| | | cluster.areaGraphic.show(); |
| | | var areaDisplay = fx.animateTransform({ |
| | | duration: 300, |
| | | shape: cluster.areaGraphic.getShape(), |
| | | transform: [ |
| | | {name: "scaleAt", start: [0, 0, center.x, center.y], end: [1, 1, center.x, center.y]} |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | scaleAnims.push(areaDisplay); |
| | | } |
| | | |
| | | var scaleUp = fx.animateTransform({ |
| | | duration: 400, |
| | | shape: groupShape, |
| | | transform: [ |
| | | {name: "scaleAt", start: [1, 1, center.x, center.y], end: [1.3, 1.3, center.x, center.y]} |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | |
| | | scaleAnims.push(scaleUp); |
| | | |
| | | this._playAnimations(scaleAnims, this.animationMultipleType.combine); |
| | | |
| | | //Add applicable flare graphics |
| | | |
| | | //array to hold the flare object data |
| | | this.flareObjects = []; |
| | | |
| | | //check if we need to create flares for the cluster |
| | | var singleFlares = (cluster.singles && cluster.singles.length > 0) && (cluster.clusterCount <= this.displaySingleFlaresAtCount); |
| | | var subTypeFlares = !singleFlares && (this.displaySubTypeFlares && this.subTypeFlareProperty && (cluster.subTypeCounts && cluster.subTypeCounts.length > 0)); |
| | | |
| | | if (!singleFlares && !subTypeFlares) { |
| | | return; |
| | | } |
| | | |
| | | //create and add a graphic to represent the flare circle |
| | | var bbox = graphicShape.getBoundingBox(); |
| | | var radius = 8; |
| | | var buffer = 4; |
| | | |
| | | var flareSymbol = new SimpleMarkerSymbol() |
| | | .setStyle(SimpleMarkerSymbol.STYLE_CIRCLE) |
| | | .setSize(radius * 2); |
| | | |
| | | //create a transparent circle that contains the boundary of the flares, this is to make sure the mouse events don't fire moving in between flares |
| | | var conCircleRadius = (center.x - (bbox.x - radius - buffer)) + radius; //get the radius of the circle to contain everything |
| | | var containerCircle = groupShape.createCircle({cx: center.x, cy: center.y, r: conCircleRadius}) |
| | | //.setStroke({ width: 1, color: "000" }) |
| | | .setFill(new Color([0, 0, 0, 0])); |
| | | containerCircle.rawNode.setAttribute("class", "flare-object cluster-object"); |
| | | |
| | | //array to hold the animations for displaying flares |
| | | var stAnims = []; |
| | | |
| | | if (singleFlares) { |
| | | for (var i = 0, len = cluster.singles.length; i < len; i++) { |
| | | delete cluster.singles[i].graphic; |
| | | this.flareObjects.push({ |
| | | tooltipText: cluster.singles[i][this.singleFlareTooltipProperty], |
| | | flareText: "", |
| | | color: this.flareColor, |
| | | singleData: cluster.singles[i], |
| | | strokeWidth: 2 |
| | | }); |
| | | } |
| | | } else if (subTypeFlares) { |
| | | |
| | | //sort sub types by highest count first |
| | | var subTypes = cluster.subTypeCounts.sort(function (a, b) { |
| | | return b.count - a.count; |
| | | }); |
| | | |
| | | for (i = 0, len = subTypes.length; i < len; i++) { |
| | | this.flareObjects.push({ |
| | | tooltipText: subTypes[i].count + " - " + subTypes[i].name, |
| | | flareText: subTypes[i].count, |
| | | color: this.flareColor, |
| | | strokeWidth: 1 |
| | | }); |
| | | } |
| | | } |
| | | |
| | | //if there are more flare objects to create that the maxFlareCount and this is a one of those - create a summary flare that contains '...' as the text and make this one part of it |
| | | var willContainSummaryFlare = this.flareObjects.length > this.maxFlareCount; |
| | | var flareCount = willContainSummaryFlare ? this.maxFlareCount : this.flareObjects.length; |
| | | |
| | | //get the surface translate values if any |
| | | var surfaceTranslate = this._getSurfaceTranslate(); |
| | | |
| | | //if there's an even amount of flares, position the first flare to the left, minus 180 from degree to do this. |
| | | //for an add amount position the first flare on top, -90 to do this. Looks more symmetrical this way. |
| | | var degreeVariance = (flareCount % 2 === 0) ? -180 : -90; |
| | | for (i = 0, len = flareCount; i < len; i++) { |
| | | |
| | | //exit if we've hit the maxFlareCount - a summary would have been created on the last one |
| | | if (i >= this.maxFlareCount) { |
| | | break; |
| | | } |
| | | |
| | | var fo = this.flareObjects[i]; |
| | | |
| | | //Do a couple of things differently if this is a summary flare or not |
| | | var tooltipText = ""; |
| | | var isSummaryFlare = willContainSummaryFlare && i >= this.maxFlareCount - 1; |
| | | if (isSummaryFlare) { |
| | | fo.color = this.flareColor; |
| | | fo.isSummaryFlare = true; |
| | | |
| | | //multiline tooltip for summary flares, ie: greater than this.maxFlareCount flares per cluster |
| | | for (var j = this.maxFlareCount - 1, jlen = this.flareObjects.length; j < jlen; j++) { |
| | | tooltipText += j > (this.maxFlareCount - 1) ? "\n" : ""; |
| | | tooltipText += this.flareObjects[j].tooltipText; |
| | | } |
| | | } else { |
| | | tooltipText = fo.tooltipText; |
| | | } |
| | | |
| | | //get the position of the flare to be placed around the container circle. |
| | | var degree = parseInt(((360 / len) * i).toFixed()); |
| | | degree = degree + degreeVariance; |
| | | |
| | | var radian = degree * (Math.PI / 180); |
| | | fo.degree = degree; |
| | | fo.radius = radius; |
| | | fo.center = { |
| | | x: center.x + (conCircleRadius - radius) * Math.cos(radian), |
| | | y: center.y + (conCircleRadius - radius) * Math.sin(radian) |
| | | }; |
| | | |
| | | //create a group to hold the flare objects |
| | | var flareGroup = groupShape.createGroup(); |
| | | |
| | | //add a graphic for the flare |
| | | var sym = lang.clone(flareSymbol); |
| | | sym.setColor(fo.color).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, this.textSymbol.color, fo.strokeWidth)); |
| | | |
| | | //get the map point from the flare group center |
| | | var matrix = flareGroup.rawNode.getScreenCTM(); |
| | | var pt = this.surface.rawNode.createSVGPoint(); |
| | | pt.x = fo.center.x; |
| | | pt.y = fo.center.y; |
| | | var screenPoint = pt.matrixTransform(matrix); |
| | | |
| | | //ScreenPoint needs to be relative to the top-left corner of the map control. |
| | | //The matrixTransform on pt gives us a point based on the screen coordinate system. |
| | | //Therefore if the map has a top offset applied to it the fo object will appear in |
| | | //an incorrect spot on the map. We must apply the offset to both the x and y points |
| | | //to ensure the point is relative to the map control. |
| | | //As of v3.18 also apply need to apply the surface translate values that may have been created by the api during panning. |
| | | var offsets = this.surface.rawNode.getBoundingClientRect(); |
| | | var sp = new ScreenPoint(screenPoint.x - offsets.left + surfaceTranslate.x, screenPoint.y - offsets.top + surfaceTranslate.y); |
| | | fo.mapPoint = this.map.toMap(sp); |
| | | |
| | | var attributes = fo.singleData ? lang.clone(fo.singleData) : {}; |
| | | attributes.isFlare = true; |
| | | var flareGraphic = new Graphic(fo.mapPoint, sym, attributes, null); |
| | | this.add(flareGraphic); |
| | | var flareCircle = flareGraphic.getShape(); |
| | | if (!flareCircle) { |
| | | return; |
| | | } |
| | | flareGroup.rawNode.appendChild(flareCircle.rawNode); |
| | | |
| | | if (fo.flareText) { |
| | | //if displaying text in the flare, |
| | | flareGroup.flareText = { |
| | | location: {x: fo.center.x, y: fo.center.y + (radius / 2 - 1)}, |
| | | text: !isSummaryFlare ? fo.flareText : "...", |
| | | textSize: !isSummaryFlare ? 7 : 10 |
| | | }; |
| | | } |
| | | |
| | | flareGroup.setTransform({xx: 0, yy: 0});//scale to 0 to start with |
| | | flareGroup.rawNode.setAttribute("class", "flare-object cluster-object"); |
| | | flareCircle.rawNode.setAttribute("class", "flare-graphic cluster-object"); |
| | | flareGroup.rawNode.setAttribute("data-tooltip", tooltipText); |
| | | |
| | | //add an animation to display the flare |
| | | var anim = fx.animateTransform({ |
| | | duration: 50, |
| | | shape: flareGroup, |
| | | transform: [ |
| | | { |
| | | name: "scaleAt", |
| | | start: [0, 0, fo.center.x, fo.center.y], |
| | | end: [1, 1, fo.center.x, fo.center.y] |
| | | } |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | |
| | | stAnims.push(anim); |
| | | |
| | | flareGroup.rawNode.setAttribute("data-center-x", fo.center.x); |
| | | flareGroup.rawNode.setAttribute("data-center-y", fo.center.y); |
| | | fo.flareGroupShape = flareGroup; |
| | | } |
| | | |
| | | this._playAnimations(stAnims, this.animationMultipleType.chain); |
| | | |
| | | }, |
| | | |
| | | _showFlareDetail: function (graphic) { |
| | | var flareObject = this._getFlareFromGraphic(graphic); |
| | | |
| | | if (this.activeFlareObject && flareObject !== this.activeFlareObject) { |
| | | this._hideFlareDetail(); |
| | | } |
| | | |
| | | this.activeFlareObject = flareObject; |
| | | this._createTooltip(flareObject.flareGroupShape); |
| | | |
| | | }, |
| | | |
| | | _getInfoWindowAnchor: function (degree) { |
| | | //set the anchor based on the degree, so the cluster is not covered by the info window |
| | | if (degree === -180) { |
| | | return "left"; |
| | | } else if (degree > -10 && degree < 10) { |
| | | return "right"; |
| | | } else if (degree > -260 && degree < -170) { |
| | | return "left"; |
| | | } else if (degree <= -90) { |
| | | return "top-left"; |
| | | } else if (degree > -90 && degree <= 0) { |
| | | return "top-right"; |
| | | } else if (degree > 0 && degree <= 90) { |
| | | return "bottom-right"; |
| | | } else { |
| | | return "bottom-left"; |
| | | } |
| | | }, |
| | | |
| | | _hideFlareDetail: function () { |
| | | |
| | | if (!this.activeFlareObject) { |
| | | return; |
| | | } |
| | | |
| | | var flareObject = this.activeFlareObject; |
| | | this._destroyTooltip(flareObject.flareGroupShape); |
| | | this.activeFlareObject = null; |
| | | |
| | | }, |
| | | |
| | | _clearActiveCluster: function (e) { |
| | | |
| | | if (!this.activeCluster) { |
| | | return; |
| | | } |
| | | if (e) { |
| | | var currentElement = e.toElement || e.relatedTarget; |
| | | if (currentElement && (currentElement.parentElement === this.map.infoWindow.domNode || (currentElement.parentElement && currentElement.parentElement.parentElement === this.map.infoWindow.domNode))) { |
| | | return; |
| | | } |
| | | } |
| | | |
| | | if (this.map.infoWindow.cluster) { |
| | | this.map.infoWindow.hide(); |
| | | } |
| | | |
| | | var cluster = this.activeCluster; |
| | | this._hideFlareDetail(); |
| | | |
| | | var groupShape = cluster.groupShape; |
| | | var graphicShape = cluster.graphicShape; |
| | | |
| | | var center = this._getShapeCenter(graphicShape); |
| | | |
| | | var scaleAnims = []; |
| | | if (this.clusterAreaDisplay === 'hover') { |
| | | var areaHide = fx.animateTransform({ |
| | | duration: 600, |
| | | shape: cluster.areaGraphic.getShape(), |
| | | transform: [ |
| | | {name: "scaleAt", start: [1, 1, center.x, center.y], end: [0, 0, center.x, center.y]} |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | |
| | | scaleAnims.push(areaHide); |
| | | } |
| | | |
| | | var scaleDown = fx.animateTransform({ |
| | | duration: 400, |
| | | shape: groupShape, |
| | | transform: [ |
| | | {name: "scaleAt", start: [1.3, 1.3, center.x, center.y], end: [1, 1, center.x, center.y]} |
| | | ], |
| | | onEnd: dojo.partial(this._animationEnd, this) |
| | | }); |
| | | |
| | | scaleAnims.push(scaleDown); |
| | | |
| | | this._playAnimations(scaleAnims, this.animationMultipleType.combine); |
| | | |
| | | //destroy any flares |
| | | for (var i = 0, len = this.graphics.length; i < len; i++) { |
| | | if (this.graphics[i].attributes.isFlare) { |
| | | this.remove(this.graphics[i]); |
| | | len--; |
| | | i--; |
| | | } |
| | | } |
| | | dojo.query(".flare-object", groupShape.rawNode).forEach(dojo.destroy); |
| | | this.activeCluster = null; |
| | | }, |
| | | |
| | | _createTooltip: function (shape) { |
| | | |
| | | var tooltipLength = dojo.query(".tooltip-text", shape.rawNode).length; |
| | | if (tooltipLength > 0) { |
| | | return; |
| | | } |
| | | |
| | | //get the text from the data-tooltip attribute of the shape object |
| | | var text = shape.rawNode.getAttribute("data-tooltip"); |
| | | if (!text) { |
| | | console.log("no data-tooltip attribute on element"); |
| | | return; |
| | | } |
| | | |
| | | //split on /n character that should be in tooltip to signify multiple lines |
| | | var lines = text.split("\n"); |
| | | |
| | | //read the center positions from the shape, attributes must be set on whatever node is being passed in. Calculating from getboundingBox wasn't working for some reason |
| | | var xPos = parseInt(shape.rawNode.getAttribute("data-center-x")); |
| | | var yPos = parseInt(shape.rawNode.getAttribute("data-center-y")) + 18; //align underneath, could be changed to be wherever |
| | | |
| | | //create a group to hold the tooltip elements |
| | | var tooltipGroup = shape.createGroup({x: xPos, y: yPos}); |
| | | tooltipGroup.rawNode.setAttribute("class", "tooltip-text"); |
| | | |
| | | var textShapes = []; |
| | | for (var i = 0, len = lines.length; i < len; i++) { |
| | | var textShape = tooltipGroup.createText({x: xPos, y: yPos + (i * 10), text: lines[i], align: 'middle'}) |
| | | .setFill("#000") |
| | | .setFont({size: 8, family: this.textSymbol.font.family, weight: this.textSymbol.font.weight}); |
| | | textShapes.push(textShape); |
| | | textShape.rawNode.setAttribute("pointer-events", "none"); |
| | | } |
| | | |
| | | var rectPadding = 2; |
| | | var textBox = tooltipGroup.getBoundingBox(); |
| | | var rectShape = tooltipGroup.createRect({ |
| | | x: textBox.x - rectPadding, |
| | | y: textBox.y - rectPadding, |
| | | width: textBox.width + (rectPadding * 2), |
| | | height: textBox.height + (rectPadding * 2), |
| | | r: 0 |
| | | }) |
| | | .setFill(new Color([255, 255, 255, 0.9])) |
| | | .setStroke({color: "#000", width: 0.5}); |
| | | rectShape.rawNode.setAttribute("pointer-events", "none"); |
| | | |
| | | shape.moveToFront(); |
| | | for (i = 0, len = textShapes.length; i < len; i++) { |
| | | textShapes[i].moveToFront(); |
| | | } |
| | | |
| | | }, |
| | | |
| | | _destroyTooltip: function (shape) { |
| | | dojo.query(".tooltip-text", shape.rawNode).forEach(dojo.destroy); |
| | | }, |
| | | |
| | | _removeCluster: function (cluster) { |
| | | //remove the cluster completely |
| | | for (var i = 0, len = this.clusters.length; i < len; i++) { |
| | | if (this.clusters[i] === cluster) { |
| | | this.clusters.splice(i, 1); |
| | | i--; |
| | | len--; |
| | | } |
| | | } |
| | | this.remove(cluster.graphic); |
| | | dojo.destroy(cluster.groupShape.rawNode); |
| | | }, |
| | | |
| | | //#endregion |
| | | |
| | | //#region helper methods |
| | | |
| | | _getGraphicFromObject: function (obj) { |
| | | //return the graphic from the obj which could be a single or cluster object |
| | | for (var i = 0, len = this.graphics.length; i < len; i++) { |
| | | var g = this.graphics[i]; |
| | | if (g.attributes[this.xPropertyName] === obj[this.xPropertyName] && g.attributes[this.yPropertyName] === obj[this.yPropertyName]) { |
| | | return g; |
| | | } |
| | | } |
| | | return null; |
| | | }, |
| | | |
| | | _getClusterFromGraphic: function (graphic) { |
| | | //return the obj which could be a single or cluster object, based on the graphic |
| | | for (var i = 0, len = this.clusters.length; i < len; i++) { |
| | | var cl = this.clusters[i]; |
| | | if (cl.graphic === graphic || (graphic.attributes.x === cl.x && graphic.attributes.y === cl.y)) { |
| | | cl.graphic = graphic; |
| | | return cl; |
| | | } |
| | | } |
| | | return null; |
| | | }, |
| | | |
| | | _getClusterFromGroupNode: function (groupNode) { |
| | | for (var i = 0, len = this.clusters.length; i < len; i++) { |
| | | if (this.clusters[i].groupShape.rawNode === groupNode) { |
| | | return this.clusters[i]; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | _getFlareFromGraphic: function (graphic) { |
| | | //return the obj which could be a single or cluster object, based on the graphic |
| | | for (var i = 0, len = this.flareObjects.length; i < len; i++) { |
| | | var fl = this.flareObjects[i]; |
| | | if (fl.singleData && (fl.singleData[this.xPropertyName] === graphic.attributes[this.xPropertyName] && fl.singleData[this.yPropertyName] === graphic.attributes[this.yPropertyName]) && |
| | | (this.idPropertyName === null || fl.singleData[this.idPropertyName] === graphic.attributes[this.idPropertyName])) { |
| | | return fl; |
| | | } |
| | | |
| | | if (graphic.geometry.x === fl.mapPoint.x && graphic.geometry.y === fl.mapPoint.y) { |
| | | return fl; |
| | | } |
| | | } |
| | | return null; |
| | | }, |
| | | |
| | | _getShapeCenter: function (shape) { |
| | | var bbox = shape.getBoundingBox(); |
| | | x = bbox.x + bbox.width / 2; |
| | | y = bbox.y + bbox.height / 2 |
| | | return {x: x, y: y}; |
| | | }, |
| | | |
| | | _getSurfaceTranslate: function () { |
| | | var translate = { |
| | | x: 0, |
| | | y: 0 |
| | | }; |
| | | |
| | | //check if we could find a translate style property on the surface. |
| | | if (!this.surface || !this.surface.rawNode || !this.surface.rawNode.style.transform || this.surface.rawNode.style.transform.indexOf("translate") === -1) return translate; |
| | | |
| | | //parse the values from the translate string. Using some basic string manipulation, some regex guru could tidy this up I would think. |
| | | var transform = this.surface.rawNode.style.transform; |
| | | transform = transform.replace("translate(", "").replace(")", ""); |
| | | var vals = transform.split(","); |
| | | if (vals.length !== 2) return translate; |
| | | vals[0] = parseInt(vals[0].replace("px", "")); |
| | | vals[1] = parseInt(vals[1].replace("px", "")); |
| | | translate.x = vals[0]; |
| | | translate.y = vals[1]; |
| | | return translate; |
| | | }, |
| | | |
| | | _animationEnd: function (layer) { |
| | | //scope: 'this' is the animation that triggered the event, 'layer' is the flare cluster layer object instance |
| | | |
| | | //IE10 and below Fix - have to manually set transform back to 1 on elements. They don't seem to appear all of the time again after beign animated back to |
| | | //a scale of 1. IE sucks. |
| | | dojo.query("> *", this.shape.rawNode).forEach(function (elem) { |
| | | if (!elem.__gfxObject__) return; |
| | | //put this in a slight timeout, otherwise the display can get a tiny bit jittery. |
| | | setTimeout(function () { |
| | | if (elem.__gfxObject__) { |
| | | elem.__gfxObject__.setTransform({xx: 1, yy: 1}); |
| | | } |
| | | }, 50); |
| | | }); |
| | | |
| | | //Here's a hack for Edge. Good to see there's no need to do special hacks for MS browsers anymore. WTF. |
| | | //Have to add the flare text after the flare group animation otherwise Edge just reloads the page and dies for some reason? |
| | | if (this.shape.flareText) { |
| | | var flareText = this.shape.createText({ |
| | | x: this.shape.flareText.location.x, |
| | | y: this.shape.flareText.location.y, |
| | | text: this.shape.flareText.text, |
| | | align: 'middle' |
| | | }) |
| | | .setFill(layer.textSymbol.color) |
| | | .setFont({ |
| | | size: this.shape.flareText.textSize, |
| | | family: layer.textSymbol.font.family, |
| | | weight: layer.textSymbol.font.weight |
| | | }); |
| | | |
| | | flareText.rawNode.setAttribute("class", "flare-text-counts"); |
| | | flareText.rawNode.setAttribute("pointer-events", "none"); //remove pointer events from text |
| | | flareText.moveToFront(); |
| | | } |
| | | |
| | | for (var i = 0, len = layer.animationsRunning.length; i < len; i++) { |
| | | if (layer.animationsRunning[i] === this) { |
| | | layer.animationsRunning.splice(i, 1); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | }, |
| | | |
| | | _playAnimations: function (animations, type) { |
| | | if (type === this.animationMultipleType.combine) { |
| | | coreFx.combine(animations).play(); |
| | | } else if (type === this.animationMultipleType.chain) { |
| | | coreFx.chain(animations).play(); |
| | | } else { |
| | | for (var i = 0, len = animations.length; i < len; i++) { |
| | | animations[i].play(); |
| | | } |
| | | } |
| | | |
| | | this.animationsRunning = this.animationsRunning.concat(animations); |
| | | }, |
| | | |
| | | _stopAnimations: function () { |
| | | for (var i = 0, len = this.animationsRunning.length; i < len; i++) { |
| | | this.animationsRunning[i].stop(); |
| | | } |
| | | this.animationsRunning = []; |
| | | }, |
| | | |
| | | //#endregion |
| | | }); |
| | | }); |
| New file |
| | |
| | | /* |
| | | * @Description: |
| | | * @Version: 1.0 |
| | | * @Author: yangsx |
| | | * @Date: 2019-12-09 19:01:40 |
| | | * @LastEditors: yangsx |
| | | * @LastEditTime: 2019-12-14 14:44:57 |
| | | */ |
| | | define([ |
| | | "dojo", |
| | | "dojo/_base/declare", |
| | | "dojo/_base/lang", |
| | | "base/BaseWidget", |
| | | "dojo/text!widgets/supervisoryMap/template.html", |
| | | "base/AppEvent", |
| | | "base/ConfigData", |
| | | "widgets/supervisoryMap/config", |
| | | "dojo/dom", |
| | | "dojo/dom-construct", |
| | | "dojo/dom-attr", |
| | | "dojo/dom-style", |
| | | "dojo/on", |
| | | "esri/layers/ArcGISDynamicMapServiceLayer", |
| | | "esri/layers/ArcGISTiledMapServiceLayer", |
| | | "esri/layers/FeatureLayer", |
| | | "controls/tab/TabControl", |
| | | "esri/dijit/SymbolStyler", |
| | | "esri/styles/basic", |
| | | "dojo/_base/array", |
| | | "esri/InfoTemplate", |
| | | "esri/tasks/query", |
| | | "esri/tasks/QueryTask", |
| | | "esri/Color", |
| | | "esri/toolbars/edit", |
| | | "esri/graphic", |
| | | "esri/geometry/Point", |
| | | "esri/geometry/Polyline", |
| | | "esri/geometry/Polygon", |
| | | "esri/geometry/Extent", |
| | | "esri/tasks/FeatureSet", |
| | | "esri/renderers/HeatmapRenderer", |
| | | "esri/symbols/SimpleLineSymbol", |
| | | "esri/symbols/SimpleFillSymbol", |
| | | "esri/symbols/PictureMarkerSymbol", |
| | | "esri/symbols/SimpleMarkerSymbol", |
| | | "esri/SpatialReference", |
| | | "esri/tasks/GeometryService", |
| | | "esri/tasks/ProjectParameters", |
| | | "esri/layers/GraphicsLayer", |
| | | "esri/layers/LabelLayer", |
| | | "esri/symbols/TextSymbol", |
| | | "esri/renderers/SimpleRenderer", |
| | | "esri/renderers/ClassBreaksRenderer", |
| | | "esri/tasks/Geoprocessor", |
| | | "esri/tasks/DataFile", |
| | | "esri/geometry/webMercatorUtils", |
| | | "esri/symbols/Font", |
| | | "esri/geometry/ScreenPoint", |
| | | "esri/layers/ImageParameters", |
| | | "esri/geometry/geometryEngine", |
| | | "esri/dijit/PopupTemplate", |
| | | "widgets/clientManagement/FlareClusterLayer_v3", |
| | | "dojo/domReady!" |
| | | ], function ( |
| | | dojo, |
| | | declare, |
| | | lang, |
| | | BaseWidget, |
| | | template, |
| | | AppEvent, |
| | | ConfigData, |
| | | config, |
| | | dom, |
| | | domConstruct, |
| | | domAttr, |
| | | domStyle, |
| | | on, |
| | | ArcGISDynamicMapServiceLayer, |
| | | ArcGISTiledMapServiceLayer, |
| | | FeatureLayer, |
| | | TabControl, |
| | | SymbolStyler, |
| | | basic, |
| | | arrayUtils, |
| | | InfoTemplate, |
| | | Query, |
| | | QueryTask, |
| | | Color, |
| | | Edit, |
| | | Graphic, |
| | | Point, |
| | | Polyline, |
| | | Polygon, |
| | | Extent, |
| | | FeatureSet, |
| | | HeatmapRenderer, |
| | | SimpleLineSymbol, |
| | | SimpleFillSymbol, |
| | | PictureMarkerSymbol, |
| | | SimpleMarkerSymbol, |
| | | SpatialReference, |
| | | GeometryService, |
| | | ProjectParameters, |
| | | GraphicsLayer, |
| | | LabelLayer, |
| | | TextSymbol, |
| | | SimpleRenderer, |
| | | ClassBreaksRenderer, |
| | | Geoprocessor, |
| | | DataFile, |
| | | webMercatorUtils, |
| | | Font, |
| | | ScreenPoint, |
| | | ImageParameters, |
| | | geometryEngine, |
| | | PopupTemplate, |
| | | FlareClusterLayer |
| | | ) { |
| | | var Widget = declare([BaseWidget], { |
| | | widgetName: "AlertSecurity", |
| | | label: "地图模式", |
| | | templateString: template, |
| | | _map: null, |
| | | objThis: null, |
| | | _siteLayer: new GraphicsLayer(), |
| | | layuiLayer: null, |
| | | layuiLadate: null, |
| | | tabIndex: 0, |
| | | |
| | | // 保留添加实体图层的变量 |
| | | addEntitys: null, |
| | | entitysData: [], |
| | | |
| | | // 巡逻区域或者巡逻路线的描述 |
| | | routeOrRegionDescribe: null, |
| | | |
| | | // 用来记录巡逻区域或者巡逻路线的下标的 |
| | | patrolIndex: 0, |
| | | |
| | | // 拖拽 |
| | | isDown: false, |
| | | x: 0, |
| | | y: 0, |
| | | offset: null, |
| | | moveThis: null, |
| | | // 电子围栏需要新增的Id |
| | | newElectronicFenceId: null, |
| | | |
| | | // 新增路线时,派发人员,人员名称,以及人员id |
| | | peopleRealName: null, |
| | | pepleRealId: null, |
| | | |
| | | //存放聚合实体 |
| | | clusterLayer: null, |
| | | constructor: function (options, srcRefNode) { |
| | | this._map = options.map; |
| | | objThis = this; |
| | | |
| | | this.addEntitys = new GraphicsLayer({ |
| | | id: 'addEntitys' |
| | | }); |
| | | |
| | | // 添加点面线的图层 |
| | | this.addPolygonEntitys = new GraphicsLayer({ |
| | | id: 'addPolygonEntitys' |
| | | }); |
| | | // 添加所有图层的地方 |
| | | this.entityPolygonAll = new GraphicsLayer({ |
| | | id: 'entityPolygonAll' |
| | | }); |
| | | |
| | | |
| | | this._map.addLayer(this.addEntitys); |
| | | |
| | | |
| | | this._map.addLayer(this.addPolygonEntitys); |
| | | this._map.addLayer(this.entityPolygonAll); |
| | | |
| | | }, |
| | | |
| | | startup: function () { |
| | | |
| | | objThis._map.addLayer(objThis._siteLayer); |
| | | |
| | | |
| | | |
| | | |
| | | }, |
| | | |
| | | getQueryStringByKey: function (key) { |
| | | return (document.location.search.match(new RegExp("(?:^\\?|&)" + key + "=(.*?)(?=&|$)")) || ['', null])[1]; |
| | | }, |
| | | |
| | | open: function () { |
| | | var that = this; |
| | | $.ajax({ |
| | | url: "https://web.byisf.com/api/blade-jfpts/equipment/equipment/listAll", |
| | | type: 'get', |
| | | dataType: 'JSON', |
| | | success: function (res) { |
| | | |
| | | var datas = res.data; |
| | | for (var i = 0; i < datas.length; i++) { |
| | | datas[i].x = Number(datas[i].jd); |
| | | datas[i].y = Number(datas[i].wd); |
| | | } |
| | | that.flareClusterLayer(datas); |
| | | |
| | | } |
| | | }) |
| | | |
| | | }, |
| | | close: function () { |
| | | |
| | | }, |
| | | // 获取当前时间,以及昨天现在的时间 |
| | | getTime: function getTime() { |
| | | var timestamp = Date.parse(new Date()); |
| | | |
| | | // 当前时间 |
| | | var currentTime = new Date(timestamp); |
| | | // 年 |
| | | var currentY = currentTime.getFullYear(); |
| | | // 月 |
| | | var currentM = currentTime.getMonth() + 1 < 10 ? '0' + (currentTime.getMonth() + 1) : currentTime.getMonth() + 1; |
| | | // 日 |
| | | var currentD = currentTime.getDate() < 10 ? '0' + currentTime.getDate() : currentTime.getDate(); |
| | | // 时 |
| | | var currentH = currentTime.getHours() < 10 ? '0' + currentTime.getHours() : currentTime.getHours(); |
| | | // 分 |
| | | var currentDd = currentTime.getMinutes() < 10 ? '0' + currentTime.getMinutes() : currentTime.getMinutes(); |
| | | // 明天 |
| | | var tomorrowTime = new Date(timestamp - 60 * 60 * 24 * 1000); |
| | | // 年 |
| | | var tomorrowY = tomorrowTime.getFullYear(); |
| | | // 月 |
| | | var tomorrowM = tomorrowTime.getMonth() + 1 < 10 ? '0' + (tomorrowTime.getMonth() + 1) : tomorrowTime.getMonth() + 1; |
| | | // 日 |
| | | var tomorrowD = tomorrowTime.getDate() < 10 ? '0' + tomorrowTime.getDate() : tomorrowTime.getDate(); |
| | | // 时 |
| | | var tomorrowH = tomorrowTime.getHours() < 10 ? '0' + tomorrowTime.getHours() : tomorrowTime.getHours(); |
| | | // 分 |
| | | var tomorrowDd = tomorrowTime.getMinutes() < 10 ? '0' + tomorrowTime.getMinutes() : tomorrowTime.getMinutes(); |
| | | return { |
| | | current: currentY + '-' + currentM + '-' + currentD + ' ' + currentH + ':' + currentDd, |
| | | tomorrow: tomorrowY + '-' + tomorrowM + '-' + tomorrowD + ' ' + tomorrowH + ':' + tomorrowDd, |
| | | month: currentM + currentD |
| | | }; |
| | | }, |
| | | |
| | | // 创建实体图层 |
| | | createEntitys: function (entitys, entityContent, name, item, lgtd, lttd, outlineColors) { |
| | | |
| | | var symbol = new esri.symbol.PictureMarkerSymbol(outlineColors, 33, 48); |
| | | symbol.name = name; |
| | | var pt = new Point(lgtd, lttd, new esri.SpatialReference({ |
| | | wkid: 4326 |
| | | })); |
| | | pt.entityData = item; |
| | | var graphic = new esri.Graphic(pt, symbol); |
| | | entitys.add(graphic); |
| | | |
| | | |
| | | entityContent.push(item); |
| | | }, |
| | | |
| | | addPoint: function (entitys, lgtd, lttd, img) { |
| | | var symbol = new esri.symbol.PictureMarkerSymbol(img, 33, 48); |
| | | var pt = new Point(lgtd, lttd, new SpatialReference({ |
| | | wkid: 4326 |
| | | })); |
| | | var graphic = new esri.Graphic(pt, symbol); |
| | | entitys.add(graphic); |
| | | }, |
| | | |
| | | addPoints: function (entitys, lgtd, lttd, img) { |
| | | var symbol = new esri.symbol.PictureMarkerSymbol(img, 33, 48); |
| | | var pt = new Point(lgtd, lttd, new SpatialReference({ |
| | | wkid: 4326 |
| | | })); |
| | | var graphic = new esri.Graphic(pt, symbol); |
| | | entitys.add(graphic); |
| | | }, |
| | | |
| | | //聚合图层事件 |
| | | flareClusterLayer: function (datas) { |
| | | |
| | | console.log(1); |
| | | |
| | | var that = this; |
| | | |
| | | var preClustered = false; |
| | | var displaySingleFlaresAtCount = 10; |
| | | var areaDisplayMode = ""; |
| | | // var allData = JSON.parse(DATA); |
| | | // DataManager.setData(allData); |
| | | |
| | | //init the layer, more options are available and explained in the cluster layer constructor |
| | | that.clusterLayer = new FlareClusterLayer({ |
| | | id: "flare-cluster-layer", |
| | | spatialReference: new esri.SpatialReference({ |
| | | "wkid": 4326 |
| | | }), |
| | | subTypeFlareProperty: "facilityType", |
| | | singleFlareTooltipProperty: "name", |
| | | displaySubTypeFlares: true, |
| | | displaySingleFlaresAtCount: displaySingleFlaresAtCount, |
| | | flareShowMode: "mouse", |
| | | preClustered: preClustered, |
| | | clusterRatio: 75, |
| | | clusterAreaDisplay: areaDisplayMode, |
| | | clusteringBegin: function (e) { |
| | | console.log(e, "clustering begin"); |
| | | }, |
| | | clusteringComplete: function () { |
| | | console.log("clustering complete"); |
| | | } |
| | | }); |
| | | |
| | | //set up a class breaks renderer to render different symbols based on the cluster count. Use the required clusterCount property to break on. |
| | | var defaultSym = new PictureMarkerSymbol("./images/jingbaored.png", 33, 48).setOffset(0, 15); |
| | | var renderer = new ClassBreaksRenderer(defaultSym, "clusterCount"); |
| | | var xlSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 32, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new dojo.Color([200, 52, 59, 0.8]), 1), new dojo.Color([250, 65, 74, 0.8])); |
| | | var lgSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 28, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new dojo.Color([41, 163, 41, 0.8]), 1), new dojo.Color([51, 204, 51, 0.8])); |
| | | var mdSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 24, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new dojo.Color([82, 163, 204, 0.8]), 1), new dojo.Color([102, 204, 255, 0.8])); |
| | | var smSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 22, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new dojo.Color([230, 184, 92, 0.8]), 1), new dojo.Color([255, 204, 102, 0.8])); |
| | | renderer.addBreak(0, 19, smSymbol); |
| | | renderer.addBreak(20, 150, mdSymbol); |
| | | renderer.addBreak(151, 1000, lgSymbol); |
| | | renderer.addBreak(1001, Infinity, xlSymbol); |
| | | |
| | | that.clusterLayer.setRenderer(renderer); //use standard setRenderer. |
| | | |
| | | //set up a popup template |
| | | var template = new PopupTemplate({ |
| | | title: "{name}", |
| | | fieldInfos: [{ |
| | | fieldName: "facilityType", |
| | | label: "Facility Type", |
| | | visible: true |
| | | }, |
| | | { |
| | | fieldName: "postcode", |
| | | label: "Post Code", |
| | | visible: true |
| | | }, |
| | | { |
| | | fieldName: "isOpen", |
| | | label: "Opening Hours", |
| | | visible: true |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | //clusterLayer.infoTemplate = template; |
| | | that._map.infoWindow.titleInBody = false; |
| | | |
| | | that._map.addLayer(that.clusterLayer); |
| | | |
| | | //var data = DataManager.getData(); |
| | | that.clusterLayer.addData(datas); |
| | | |
| | | }, |
| | | clearLayer: function () { |
| | | var that = this; |
| | | that._map.removeLayer(that.clusterLayer); |
| | | that.clusterLayer = null; |
| | | } |
| | | }); |
| | | return Widget; |
| | | }); |
| New file |
| | |
| | | /* |
| | | * @Description: |
| | | * @Version: 1.0 |
| | | * @Author: yangsx |
| | | * @Date: 2019-12-09 19:01:40 |
| | | * @LastEditors: yangsx |
| | | * @LastEditTime: 2019-12-14 10:00:41 |
| | | */ |
| | | define([], function() { |
| | | var config = {}; |
| | | |
| | | return config; |
| | | }); |
| | |
| | | ...params, |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export const selectAlertScount = (params) => { |
| | | return request({ |
| | | url: '/api/blade-jfpts/alarm/alarm/selectAlertScount', |
| | | method: 'get', |
| | | params: { |
| | | ...params, |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export const selAlarmDayAveragePro = (params) => { |
| | | return request({ |
| | | url: '/api/blade-jfpts/alarm/alarm/selAlarmDayAveragePro', |
| | | method: 'get', |
| | | params: { |
| | | ...params, |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export const selConfirmTimePro = (params) => { |
| | | return request({ |
| | | url: '/api/blade-jfpts/alarm/alarm/selConfirmTimePro', |
| | | method: 'get', |
| | | params: { |
| | | ...params, |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export const selAlarmTimeDis = (params) => { |
| | | return request({ |
| | | url: '/api/blade-jfpts/alarm/alarm/selAlarmTimeDis', |
| | | method: 'get', |
| | | params: { |
| | | ...params, |
| | | } |
| | | }) |
| | | } |
| New file |
| | |
| | | import request from '@/router/axios'; |
| | | |
| | | export const getList = () => { |
| | | return request({ |
| | | url: '/api/blade-jfpts/equipment/equipment/listAll', |
| | | method: 'get', |
| | | params: {} |
| | | }) |
| | | } |
| | |
| | | params: {} |
| | | }) |
| | | } |
| | | |
| | | export const getEquipment = () => { |
| | | return request({ |
| | | url: '/api/blade-jfpts/equipment/equipment/SeleC', |
| | | method: 'post', |
| | | params: {} |
| | | }) |
| | | } |
| | |
| | | .then((result) => { |
| | | axios({ |
| | | method: "post", |
| | | url: `/api/blade-jfpts/rvideo/rVoid`, |
| | | timeout: 600000, |
| | | url: `/api/blade-jfpts/rvideo/rVoids`, |
| | | params: { |
| | | sourcePath: result.data.data.flv, |
| | | jid: that.form.id, |
| | | url: result.data.data.flv, |
| | | }, |
| | | }).then((resdata) => {}); |
| | | }); |
| | |
| | | this.videoConversationReal = false; |
| | | this.oldVideoSatart = false; |
| | | }, |
| | | |
| | | getDate() { |
| | | // 当前时间 |
| | | var timestamp = Date.parse(new Date()); |
| | |
| | | ) |
| | | .then(function () { |
| | | that.dialogTableVisible = false; |
| | | |
| | | axios({ |
| | | method: "post", |
| | | url: `/api/blade-jfpts/rvideo/stop`, |
| | | params: { |
| | | jid: row.id, |
| | | }, |
| | | }).then((resdata) => {}); |
| | | |
| | | that.$router.push({ |
| | | path: "/policeTracking/track", |
| | |
| | | |
| | | //启动websocket |
| | | websocketStart() { |
| | | |
| | | var that = this; |
| | | |
| | | if (!window.WebSocket) { |
| | |
| | | |
| | | window.socket.onopen = function (event) {}; |
| | | |
| | | window.socket.onclose = function (event) { |
| | | |
| | | }; |
| | | window.socket.onclose = function (event) {}; |
| | | window.socket.error = function (event) { |
| | | //执行重连 |
| | | that.websocketStart(); |
| | | }; |
| | | |
| | | } else { |
| | | console.log("WebSocket连接没有建立成功!!"); |
| | | } |
| | |
| | | |
| | | //开启心跳传送 |
| | | window.websockPing = setInterval(function () { |
| | | |
| | | if (window.socket.readyState == WebSocket.OPEN) { |
| | | window.socket.send("ping"); |
| | | }else{ |
| | | console.log("心跳停止,断开重连") |
| | | } else { |
| | | console.log("心跳停止,断开重连"); |
| | | //断开连接,重连 |
| | | window.clearTimeout(window.websockPing); |
| | | //执行重连 |
| | | that.websocketStart(); |
| | | } |
| | | |
| | | |
| | | }, 10000); |
| | | } else { |
| | | console.log("WebSocket连接没有建立成功!!"); |
| | |
| | | <template> |
| | | <div class="avue-top"> |
| | | <div class="top-bar__left"> |
| | | <div class="avue-breadcrumb" |
| | | :class="[{ 'avue-breadcrumb--active': isCollapse }]" |
| | | v-if="showCollapse"> |
| | | <i class="icon-navicon" |
| | | @click="setCollapse"></i> |
| | | <div |
| | | class="avue-breadcrumb" |
| | | :class="[{ 'avue-breadcrumb--active': isCollapse }]" |
| | | v-if="showCollapse" |
| | | > |
| | | <i class="icon-navicon" @click="setCollapse"></i> |
| | | </div> |
| | | </div> |
| | | <div class="top-bar__title"> |
| | | <div class="top-bar__item top-bar__item--show" |
| | | v-if="showMenu"> |
| | | <div class="top-bar__item top-bar__item--show" v-if="showMenu"> |
| | | <top-menu ref="topMenu"></top-menu> |
| | | </div> |
| | | <!--去除顶部搜索栏--> |
| | | <!-- <span class="top-bar__item"--> |
| | | <!-- v-if="showSearch">--> |
| | | <!-- <top-search></top-search>--> |
| | | <!-- </span>--> |
| | | <!-- <span class="top-bar__item"--> |
| | | <!-- v-if="showSearch">--> |
| | | <!-- <top-search></top-search>--> |
| | | <!-- </span>--> |
| | | </div> |
| | | <div class="top-bar__right"> |
| | | |
| | | <img src="/img/ydlg.png" style="height: 44px; vertical-align: middle;" alt=""> |
| | | <el-tooltip v-if="showColor" |
| | | effect="dark" |
| | | :content="$t('navbar.color')" |
| | | placement="bottom"> |
| | | <img |
| | | src="/img/ydlg.png" |
| | | style="height: 44px; vertical-align: middle" |
| | | alt="" |
| | | /> |
| | | <el-tooltip |
| | | v-if="showColor" |
| | | effect="dark" |
| | | :content="$t('navbar.color')" |
| | | placement="bottom" |
| | | > |
| | | <div class="top-bar__item"> |
| | | <top-color></top-color> |
| | | </div> |
| | | </el-tooltip> |
| | | <el-tooltip v-if="showDebug" |
| | | effect="dark" |
| | | :content="logsFlag?$t('navbar.bug'):logsLen+$t('navbar.bugs')" |
| | | placement="bottom"> |
| | | <el-tooltip |
| | | v-if="showDebug" |
| | | effect="dark" |
| | | :content="logsFlag ? $t('navbar.bug') : logsLen + $t('navbar.bugs')" |
| | | placement="bottom" |
| | | > |
| | | <div class="top-bar__item"> |
| | | <top-logs></top-logs> |
| | | </div> |
| | | </el-tooltip> |
| | | <el-tooltip v-if="showLock" |
| | | effect="dark" |
| | | :content="$t('navbar.lock')" |
| | | placement="bottom"> |
| | | <el-tooltip |
| | | v-if="showLock" |
| | | effect="dark" |
| | | :content="$t('navbar.lock')" |
| | | placement="bottom" |
| | | > |
| | | <div class="top-bar__item"> |
| | | <top-lock></top-lock> |
| | | </div> |
| | | </el-tooltip> |
| | | <el-tooltip v-if="showTheme" |
| | | effect="dark" |
| | | :content="$t('navbar.theme')" |
| | | placement="bottom"> |
| | | <el-tooltip |
| | | v-if="showTheme" |
| | | effect="dark" |
| | | :content="$t('navbar.theme')" |
| | | placement="bottom" |
| | | > |
| | | <div class="top-bar__item top-bar__item--show"> |
| | | <top-theme></top-theme> |
| | | </div> |
| | | </el-tooltip> |
| | | <!-- <el-tooltip effect="dark"--> |
| | | <!-- :content="$t('navbar.notice')"--> |
| | | <!-- placement="bottom">--> |
| | | <!-- <div class="top-bar__item top-bar__item--show">--> |
| | | <!-- <top-notice></top-notice>--> |
| | | <!-- </div>--> |
| | | <!-- </el-tooltip>--> |
| | | <el-tooltip effect="dark" |
| | | :content="$t('navbar.language')" |
| | | placement="bottom"> |
| | | <!-- <el-tooltip effect="dark"--> |
| | | <!-- :content="$t('navbar.notice')"--> |
| | | <!-- placement="bottom">--> |
| | | <!-- <div class="top-bar__item top-bar__item--show">--> |
| | | <!-- <top-notice></top-notice>--> |
| | | <!-- </div>--> |
| | | <!-- </el-tooltip>--> |
| | | <el-tooltip |
| | | effect="dark" |
| | | :content="$t('navbar.language')" |
| | | placement="bottom" |
| | | > |
| | | <div class="top-bar__item top-bar__item--show"> |
| | | <top-lang></top-lang> |
| | | </div> |
| | | </el-tooltip> |
| | | <el-tooltip v-if="showFullScren" |
| | | effect="dark" |
| | | :content="isFullScren?$t('navbar.screenfullF'):$t('navbar.screenfull')" |
| | | placement="bottom"> |
| | | <el-tooltip |
| | | v-if="showFullScren" |
| | | effect="dark" |
| | | :content=" |
| | | isFullScren ? $t('navbar.screenfullF') : $t('navbar.screenfull') |
| | | " |
| | | placement="bottom" |
| | | > |
| | | <div class="top-bar__item"> |
| | | <i :class="isFullScren?'icon-tuichuquanping':'icon-quanping'" |
| | | @click="handleScreen"></i> |
| | | <i |
| | | :class="isFullScren ? 'icon-tuichuquanping' : 'icon-quanping'" |
| | | @click="handleScreen" |
| | | ></i> |
| | | </div> |
| | | </el-tooltip> |
| | | <img class="top-bar__img" |
| | | :src="userInfo.avatar"> |
| | | <img class="top-bar__img" :src="userInfo.avatar" /> |
| | | <el-dropdown> |
| | | <span class="el-dropdown-link"> |
| | | {{userInfo.userName}} |
| | | {{ userInfo.userName }} |
| | | <i class="el-icon-arrow-down el-icon--right"></i> |
| | | </span> |
| | | <el-dropdown-menu slot="dropdown"> |
| | | <el-dropdown-item> |
| | | <router-link to="/">{{$t('navbar.dashboard')}}</router-link> |
| | | <router-link to="/">{{ $t("navbar.dashboard") }}</router-link> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item> |
| | | <router-link to="/info/index">{{$t('navbar.userinfo')}}</router-link> |
| | | <router-link to="/info/index">{{ |
| | | $t("navbar.userinfo") |
| | | }}</router-link> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item @click.native="logout" |
| | | divided>{{$t('navbar.logOut')}} |
| | | <el-dropdown-item @click.native="logout" divided |
| | | >{{ $t("navbar.logOut") }} |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </el-dropdown> |
| | |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import {resetRouter} from '@/router/router' |
| | | import {mapGetters, mapState} from "vuex"; |
| | | import {fullscreenToggel, listenfullscreen} from "@/util/util"; |
| | | import topLock from "./top-lock"; |
| | | import topMenu from "./top-menu"; |
| | | import topSearch from "./top-search"; |
| | | import topTheme from "./top-theme"; |
| | | import topLogs from "./top-logs"; |
| | | import topColor from "./top-color"; |
| | | import topNotice from './top-notice' |
| | | import topLang from "./top-lang"; |
| | | import { resetRouter } from "@/router/router"; |
| | | import { mapGetters, mapState } from "vuex"; |
| | | import { fullscreenToggel, listenfullscreen } from "@/util/util"; |
| | | import topLock from "./top-lock"; |
| | | import topMenu from "./top-menu"; |
| | | import topSearch from "./top-search"; |
| | | import topTheme from "./top-theme"; |
| | | import topLogs from "./top-logs"; |
| | | import topColor from "./top-color"; |
| | | import topNotice from "./top-notice"; |
| | | import topLang from "./top-lang"; |
| | | |
| | | export default { |
| | | components: { |
| | | topLock, |
| | | topMenu, |
| | | topSearch, |
| | | topTheme, |
| | | topLogs, |
| | | topColor, |
| | | topNotice, |
| | | topLang |
| | | export default { |
| | | components: { |
| | | topLock, |
| | | topMenu, |
| | | topSearch, |
| | | topTheme, |
| | | topLogs, |
| | | topColor, |
| | | topNotice, |
| | | topLang, |
| | | }, |
| | | name: "top", |
| | | data() { |
| | | return {}; |
| | | }, |
| | | filters: {}, |
| | | created() {}, |
| | | mounted() { |
| | | listenfullscreen(this.setScreen); |
| | | }, |
| | | computed: { |
| | | ...mapState({ |
| | | showDebug: (state) => state.common.showDebug, |
| | | showTheme: (state) => state.common.showTheme, |
| | | showLock: (state) => state.common.showLock, |
| | | showFullScren: (state) => state.common.showFullScren, |
| | | showCollapse: (state) => state.common.showCollapse, |
| | | showSearch: (state) => state.common.showSearch, |
| | | showMenu: (state) => state.common.showMenu, |
| | | showColor: (state) => state.common.showColor, |
| | | }), |
| | | ...mapGetters([ |
| | | "userInfo", |
| | | "isFullScren", |
| | | "tagWel", |
| | | "tagList", |
| | | "isCollapse", |
| | | "tag", |
| | | "logsLen", |
| | | "logsFlag", |
| | | ]), |
| | | }, |
| | | methods: { |
| | | handleScreen() { |
| | | fullscreenToggel(); |
| | | }, |
| | | name: "top", |
| | | data() { |
| | | return {}; |
| | | setCollapse() { |
| | | this.$store.commit("SET_COLLAPSE"); |
| | | }, |
| | | filters: {}, |
| | | created() { |
| | | setScreen() { |
| | | this.$store.commit("SET_FULLSCREN"); |
| | | }, |
| | | mounted() { |
| | | listenfullscreen(this.setScreen); |
| | | }, |
| | | computed: { |
| | | ...mapState({ |
| | | showDebug: state => state.common.showDebug, |
| | | showTheme: state => state.common.showTheme, |
| | | showLock: state => state.common.showLock, |
| | | showFullScren: state => state.common.showFullScren, |
| | | showCollapse: state => state.common.showCollapse, |
| | | showSearch: state => state.common.showSearch, |
| | | showMenu: state => state.common.showMenu, |
| | | showColor: state => state.common.showColor |
| | | }), |
| | | ...mapGetters([ |
| | | "userInfo", |
| | | "isFullScren", |
| | | "tagWel", |
| | | "tagList", |
| | | "isCollapse", |
| | | "tag", |
| | | "logsLen", |
| | | "logsFlag" |
| | | ]) |
| | | }, |
| | | methods: { |
| | | handleScreen() { |
| | | fullscreenToggel(); |
| | | }, |
| | | setCollapse() { |
| | | this.$store.commit("SET_COLLAPSE"); |
| | | }, |
| | | setScreen() { |
| | | this.$store.commit("SET_FULLSCREN"); |
| | | }, |
| | | logout() { |
| | | this.$confirm(this.$t("logoutTip"), this.$t("tip"), { |
| | | confirmButtonText: this.$t("submitText"), |
| | | cancelButtonText: this.$t("cancelText"), |
| | | type: "warning" |
| | | }).then(() => { |
| | | logout() { |
| | | this.$confirm(this.$t("logoutTip"), this.$t("tip"), { |
| | | confirmButtonText: this.$t("submitText"), |
| | | cancelButtonText: this.$t("cancelText"), |
| | | type: "warning", |
| | | }).then(() => { |
| | | //关闭webSocket |
| | | window.socket.close(); |
| | | //关闭报警循环 |
| | | window.clearTimeout(window.realTimeQuery); |
| | | //关闭心跳循环 |
| | | window.clearTimeout(window.websockPing); |
| | | |
| | | //关闭webSocket |
| | | window.socket.close(); |
| | | //关闭报警循环 |
| | | window.clearTimeout(window.realTimeQuery); |
| | | //关闭心跳循环 |
| | | window.clearTimeout(window.websockPing); |
| | | |
| | | this.$store.dispatch("LogOut").then(() => { |
| | | resetRouter(); |
| | | this.$router.push({path: "/login"}); |
| | | }); |
| | | this.$store.dispatch("LogOut").then(() => { |
| | | resetRouter(); |
| | | this.$router.push({ path: "/login" }); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | <template> |
| | | <div class="top-menu"> |
| | | <el-menu :default-active="activeIndex" |
| | | mode="horizontal" |
| | | text-color="#333"> |
| | | <el-menu-item index="0" @click.native="openHome(itemHome)" key="0"> |
| | | <el-menu :default-active="activeIndex" mode="horizontal" text-color="#333"> |
| | | <el-menu-item index="0" @click.native="openHome(dataItem)" key="0"> |
| | | <template slot="title"> |
| | | <i :class="itemHome.source"></i> |
| | | <span>{{generateTitle(itemHome)}}</span> |
| | | <i :class="dataItem.source" :title="dataItem.name"></i> |
| | | </template> |
| | | </el-menu-item> |
| | | <!-- <el-menu-item index="0" @click.native="openHomes(ZHAJ)" key="0">--> |
| | | <!-- <template slot="title">--> |
| | | <!-- <i :class="ZHAJ.source"></i>--> |
| | | <!-- <span>{{generateTitle(ZHAJ)}}</span>--> |
| | | <!-- </template>--> |
| | | <!-- </el-menu-item>--> |
| | | <template v-for="(item,index) in items"> |
| | | <el-menu-item :index="item.id+''" @click.native="openMenu(item)" :key="index"> |
| | | <el-menu-item index="1" @click.native="openHome(mapItem)" key="0"> |
| | | <template slot="title"> |
| | | <i :class="mapItem.source" :title="mapItem.name"></i> |
| | | </template> |
| | | </el-menu-item> |
| | | <el-menu-item index="2" @click.native="openHome(cardItem)" key="0"> |
| | | <template slot="title"> |
| | | <i :class="cardItem.source" :title="cardItem.name"></i> |
| | | </template> |
| | | </el-menu-item> |
| | | <!-- <el-menu-item index="0" @click.native="openHomes(ZHAJ)" key="0">--> |
| | | <!-- <template slot="title">--> |
| | | <!-- <i :class="ZHAJ.source"></i>--> |
| | | <!-- <span>{{generateTitle(ZHAJ)}}</span>--> |
| | | <!-- </template>--> |
| | | <!-- </el-menu-item>--> |
| | | <template v-for="(item, index) in items"> |
| | | <el-menu-item |
| | | :index="item.id + ''" |
| | | @click.native="openMenu(item)" |
| | | :key="index" |
| | | > |
| | | <template slot="title"> |
| | | <i :class="item.source" style="padding-right: 5px;"></i> |
| | | <span>{{generateTitle(item)}}</span> |
| | | <i :class="item.source" style="padding-right: 5px"></i> |
| | | <span>{{ generateTitle(item) }}</span> |
| | | </template> |
| | | </el-menu-item> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import {mapGetters} from "vuex"; |
| | | import { mapGetters } from "vuex"; |
| | | |
| | | export default { |
| | | name: "top-menu", |
| | | data() { |
| | | return { |
| | | itemHome: { |
| | | name: '数据模式', |
| | | source: 'el-icon-menu', |
| | | }, |
| | | ZHAJ: { |
| | | name: '智慧安检', |
| | | source: 'icon-anbao', |
| | | }, |
| | | activeIndex: "0", |
| | | items: [], |
| | | }; |
| | | export default { |
| | | name: "top-menu", |
| | | data() { |
| | | return { |
| | | dataItem: { |
| | | name: "数据模式", |
| | | source: "el-icon-s-data", |
| | | path: "/wel/index", |
| | | }, |
| | | mapItem: { |
| | | name: "地图模式", |
| | | source: "el-icon-location", |
| | | path: "/welcomeData/map", |
| | | }, |
| | | cardItem: { |
| | | name: "卡片模式", |
| | | source: "el-icon-menu", |
| | | path: "/welcomeData/card", |
| | | }, |
| | | ZHAJ: { |
| | | name: "智慧安检", |
| | | source: "icon-anbao", |
| | | }, |
| | | activeIndex: "0", |
| | | items: [], |
| | | }; |
| | | }, |
| | | inject: ["index"], |
| | | created() { |
| | | this.getMenu(); |
| | | }, |
| | | computed: { |
| | | ...mapGetters(["tagCurrent", "menu"]), |
| | | }, |
| | | methods: { |
| | | openHome(itemHome) { |
| | | this.index.openMenu(itemHome); |
| | | this.$router.push({ |
| | | path: itemHome.path, |
| | | }); |
| | | }, |
| | | inject: ["index"], |
| | | created() { |
| | | this.getMenu(); |
| | | openHomes(itemHome) { |
| | | this.index.openMenu(itemHome); |
| | | this.$router.push({ |
| | | path: this.$router.$avueRouter.getPath( |
| | | { |
| | | name: itemHome.name, |
| | | src: |
| | | "https://cas.sf-express.com/cas/login?service=http://fengkong.sf-express.com/backstageprd/#/homeInfo/infoOverview", |
| | | }, |
| | | {} |
| | | ), |
| | | }); |
| | | }, |
| | | computed: { |
| | | ...mapGetters(["tagCurrent", "menu"]) |
| | | openMenu(item) { |
| | | this.index.openMenu(item); |
| | | }, |
| | | methods: { |
| | | openHome(itemHome) { |
| | | this.index.openMenu(itemHome); |
| | | this.$router.push({ |
| | | path: this.$router.$avueRouter.getPath({name: itemHome.name, src: ''}, {}) |
| | | }); |
| | | }, |
| | | openHomes(itemHome) { |
| | | this.index.openMenu(itemHome); |
| | | this.$router.push({ |
| | | path: this.$router.$avueRouter.getPath({name: itemHome.name, src: 'https://cas.sf-express.com/cas/login?service=http://fengkong.sf-express.com/backstageprd/#/homeInfo/infoOverview'}, {}) |
| | | }); |
| | | }, |
| | | openMenu(item) { |
| | | this.index.openMenu(item) |
| | | }, |
| | | getMenu() { |
| | | this.$store.dispatch("GetTopMenu").then(res => { |
| | | this.items = res; |
| | | }); |
| | | }, |
| | | generateTitle(item) { |
| | | return this.$router.$avueRouter.generateTitle( |
| | | item.name, |
| | | (item.meta || {}).i18n |
| | | ); |
| | | }, |
| | | } |
| | | }; |
| | | getMenu() { |
| | | this.$store.dispatch("GetTopMenu").then((res) => { |
| | | this.items = res; |
| | | }); |
| | | }, |
| | | generateTitle(item) { |
| | | return this.$router.$avueRouter.generateTitle( |
| | | item.name, |
| | | (item.meta || {}).i18n |
| | | ); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | |
| | | isShade: false, |
| | | screen: -1, |
| | | isLock: getStore({name: 'isLock'}) || false, |
| | | showTag: true, |
| | | showTag: false, |
| | | showDebug: true, |
| | | showCollapse: true, |
| | | showSearch: true, |
| | |
| | | height: 450px; |
| | | position: relative; |
| | | left: 0.8%; |
| | | top: 12%; |
| | | top: 10%; |
| | | } |
| | | |
| | | #confirmTimeProEcharts { |
| | |
| | | width: 35%; |
| | | height: 450px; |
| | | position: relative; |
| | | top: -41%; |
| | | top: -43%; |
| | | left: 64.4%; |
| | | } |
| | | |
| | |
| | | height: 450px; |
| | | position: relative; |
| | | left: 0.8%; |
| | | top: -38.6%; |
| | | top: -40.6%; |
| | | } |
| | | |
| | | #alarmTimeDisEchars { |
| | |
| | | position: relative; |
| | | left: 0.8%; |
| | | top: -38%; |
| | | } |
| | | } |
| | | |
| | | .el-button .btn-color { |
| | | color: rgb(255, 255, 255); |
| | | background-color: #29C093; |
| | | border-color: #29C093; |
| | | } |
| | | |
| | | // .el-icon-bell:before { |
| | | // width: 10px; |
| | | // height: 10px; |
| | | // border-radius: 50%; |
| | | // //background-color: #F34A4A; |
| | | // display: inline-block; |
| | | // content: ''; |
| | | // } |
| | |
| | | position: absolute; |
| | | left: 240px; |
| | | padding: 0; |
| | | padding-bottom: 20px; |
| | | width: calc(100% - 240px); |
| | | height: calc(100% - 64px); |
| | | box-sizing: border-box; |
| | |
| | | <template> |
| | | <iframe v-show="iframeState" id="show-iframe" frameborder=0 name="showHere" scrolling=auto |
| | | v-bind:src="reportUrl"></iframe> |
| | | <iframe |
| | | v-show="iframeState" |
| | | id="show-iframe" |
| | | frameborder="0" |
| | | name="showHere" |
| | | scrolling="auto" |
| | | v-bind:src="reportUrl" |
| | | ></iframe> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "tcgl.vue", |
| | | created() { |
| | | this.getData(); |
| | | export default { |
| | | name: "tcgl.vue", |
| | | created() { |
| | | this.getData(); |
| | | }, |
| | | data() { |
| | | return { |
| | | reportUrl: "", |
| | | channelNumber: null, |
| | | serialNumber: null, |
| | | }; |
| | | }, |
| | | methods: { |
| | | getData() { |
| | | this.reportUrl = |
| | | "./realVideo/realtime-view-videos.html?channelNumber=" + |
| | | this.$route.query.channelNumber + |
| | | "&serialNumber=" + |
| | | this.$route.query.serialNumber; |
| | | }, |
| | | data() { |
| | | return { |
| | | reportUrl: '', |
| | | channelNumber: null, |
| | | serialNumber: null |
| | | } |
| | | }, |
| | | methods: { |
| | | getData() { |
| | | this.reportUrl = "./realVideo/realtime-view-videos.html?channelNumber=" |
| | | + this.$route.query.channelNumber |
| | | + "&serialNumber=" + this.$route.query.serialNumber; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | #show-iframe { |
| | | display: block !important; |
| | | height: 95%; |
| | | } |
| | | |
| | | #show-iframe { |
| | | display: block !important; |
| | | height: 95%; |
| | | |
| | | } |
| | | |
| | | .avue-main .avue-view { |
| | | height: 100%; |
| | | padding: 0px 5px !important; |
| | | } |
| | | .avue-main .avue-view { |
| | | height: 100%; |
| | | padding: 5px 5px !important; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="big"> |
| | | <!-- 标题 --> |
| | | <div class="alarm_title"><span>预警分析</span></div> |
| | | <!-- 时间按钮 --> |
| | | <div class="timeSearchBtn"> |
| | | <el-button-group class="timeBtn"> |
| | | <el-button |
| | | v-bind:class="activeClass == 1 ? 'btn-color' : ''" |
| | | size="mini" |
| | | @click="getData(1)"> |
| | | 本周 |
| | | </el-button> |
| | | |
| | | <el-button |
| | | v-bind:class="activeClass == 2 ? 'btn-color' : ''" |
| | | size="mini" |
| | | @click="getData(2)"> |
| | | 月初至今 |
| | | </el-button> |
| | | |
| | | <el-button |
| | | v-bind:class="activeClass == 3 ? 'btn-color' : ''" |
| | | size="mini" |
| | | @click="getData(3)"> |
| | | 季度至今 |
| | | </el-button> |
| | | </el-button-group> |
| | | <el-date-picker class="timeSearch" size="mini" v-model="dateTime" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> |
| | | </el-date-picker> |
| | | </div> |
| | | <!-- 监测点 --> |
| | | <div class="statisTotal"> |
| | | <avue-data-box :option="statisToTalData" class="statisTotalAvueDataBox"></avue-data-box> |
| | | </div> |
| | | <!-- 预警数量分布 --> |
| | | <div class="alarmStatis"> |
| | | <div id="alarmNumberStatis"> |
| | | </div> |
| | | <div class="alarmClassifyStatis"> |
| | | <avue-data-cardtext :option="alarmClassifyStatis"></avue-data-cardtext> |
| | | </div> |
| | | </div> |
| | | <!-- 预警类型占比 --> |
| | | <div class="alarmTypePro"> |
| | | <div id="alarmTypeProEcharts"></div> |
| | | <div class="alarmTypeProStatis"> |
| | | <avue-data-cardtext :option="alarmTypeProStatis"></avue-data-cardtext> |
| | | </div> |
| | | </div> |
| | | <!-- 预警设备类型占比 --> |
| | | <div class="alarmEquipmentPro"> |
| | | <div id="alarmEquipmentProEcharts"></div> |
| | | <div class="alarmEquipmentProStatis"> |
| | | <avue-crud :data="alarmEquipmentProStatisData" :option="alarmEquipmentProStatisOption"></avue-crud> |
| | | </div> |
| | | </div> |
| | | <!-- 确认时间占比 --> |
| | | <div class="confirmTimePro"> |
| | | <div id="confirmTimeProEcharts"></div> |
| | | <div class="confirmTimeProStatis"> |
| | | <avue-data-cardtext :option="confirmTimeProStatis"></avue-data-cardtext> |
| | | </div> |
| | | </div> |
| | | <!-- 预警平均确认速度排行 --> |
| | | <div class="confirmAverageSpeed"> |
| | | <avue-crud :data="confirmAverageSpeedData" :option="confirmAverageSpeedOption"></avue-crud> |
| | | </div> |
| | | <!-- 预警时间分布 --> |
| | | <div class="alarmTimeDis"> |
| | | <div id="alarmTimeDisEchars"></div> |
| | | </div> |
| | | |
| | | <!-- 底部 --> |
| | | <div class="low"></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import echarts from 'echarts' |
| | | import {selectIndexCount} from "@/api/statis/statis"; |
| | | |
| | | export default { |
| | | data(){ |
| | | return { |
| | | activeClass:2, |
| | | statisToTalData: { |
| | | span:6, |
| | | data: [] |
| | | }, |
| | | dateTime: '', |
| | | alarmClassifyStatis:{ |
| | | span:6, |
| | | data: [] |
| | | }, |
| | | alarmTypeProStatis:{ |
| | | span:10, |
| | | height:100, |
| | | data: [] |
| | | }, |
| | | alarmEquipmentProStatisData:[], |
| | | alarmEquipmentProStatisOption:{}, |
| | | confirmTimeProStatis:{ |
| | | span:10, |
| | | height:100, |
| | | data: [] |
| | | }, |
| | | confirmAverageSpeedData:[], |
| | | confirmAverageSpeedOption:{} |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | //统计预警总数 |
| | | this.getStatisTotalData(); |
| | | //预警数量统计 |
| | | this.getAlarmNumberStatis(); |
| | | //预警分类统计 |
| | | this.getAlarmClassifyStatis(); |
| | | //预警类型占比统计 |
| | | this.getAlarmTypeProEcharts(); |
| | | this.getAlarmTypeProStatis(); |
| | | //预警设备类型占比统计 |
| | | this.getAlarmEquipmentProEcharts(); |
| | | this.getAlarmEquipmentProStatis(); |
| | | //确认时间占比统计 |
| | | this.getConfirmTimeProEcharts(); |
| | | this.getConfirmTimeProStatis(); |
| | | this.confirmAverageSpeedStatis(); |
| | | //预警时间分布统计 |
| | | this.getAlarmTimeDisEchars(); |
| | | }, |
| | | |
| | | methods: { |
| | | //警情统计总数 |
| | | getStatisTotalData(data){ |
| | | selectIndexCount(data).then(res => { |
| | | console.log(res.data); |
| | | this.form = res.data.data; |
| | | }); |
| | | var that = this; |
| | | that.statisToTalData.data = [ |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title: '警情总数', |
| | | count: 12332, |
| | | icon: 'el-icon-warning', |
| | | color: '#F34A4A' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title: '违禁包裹数', |
| | | count: 33, |
| | | icon: 'el-icon-warning', |
| | | color: '#FF9836' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title: '违禁物品数', |
| | | count: 2223, |
| | | icon: 'el-icon-setting', |
| | | color: '#8058A5' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title: '在线设备数', |
| | | count: 2223, |
| | | icon: 'el-icon-setting', |
| | | color: '#29C093' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title: '客户数量', |
| | | count: 2223, |
| | | icon: 'el-icon-setting', |
| | | color: '#3AA7F0' |
| | | } |
| | | ]; |
| | | }, |
| | | |
| | | //预警数量分布 |
| | | getAlarmNumberStatis(){ |
| | | let echarts = require('echarts'); |
| | | let myChart = echarts.init(document.getElementById('alarmNumberStatis')); |
| | | let option = { |
| | | title: { |
| | | textStyle: { |
| | | fontWeight: 'normal', |
| | | fontSize: 16, |
| | | color: '#000' |
| | | }, |
| | | left: '1%', |
| | | top: 25, |
| | | textAlign:'left', |
| | | text: '预警时间分布' |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '7%', |
| | | bottom: '10%', |
| | | top:'20%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | splitLine: { |
| | | show: true, |
| | | lineStyle:{ |
| | | type:'dashed' |
| | | } |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '邮件营销', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [120, 132, 101, 134, 90, 230, 210] |
| | | }, |
| | | { |
| | | name: '联盟广告', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [220, 182, 191, 234, 290, 330, 310] |
| | | }, |
| | | { |
| | | name: '视频广告', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [150, 232, 201, 154, 190, 330, 410] |
| | | }, |
| | | { |
| | | name: '直接访问', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [320, 332, 301, 334, 390, 330, 320] |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | myChart.setOption(option); |
| | | |
| | | //建议加上以下这一行代码,不加的效果图如下(当浏览器窗口缩小的时候)。超过了div的界限(红色边框) |
| | | window.addEventListener('resize',function() {myChart.resize()}); |
| | | }, |
| | | |
| | | //警情类别统计总数 |
| | | getAlarmClassifyStatis(){ |
| | | var that = this; |
| | | that.alarmClassifyStatis.data = [ |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'一键求助', |
| | | color:'yellow', |
| | | target:'_blank', |
| | | name:'日平均一键求助数', |
| | | date:'1.00' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'违禁品', |
| | | color:'green', |
| | | name:'日平均违禁品数', |
| | | date:'3.00' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'红色健康码', |
| | | color:'#3fa1ff', |
| | | name:'日平均红色健康码数', |
| | | date:'1.00' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'体温异常', |
| | | color:'red', |
| | | name:'日平均体温异常数', |
| | | date:'10.00' |
| | | } |
| | | ]; |
| | | }, |
| | | |
| | | |
| | | //预警类型占比统计 |
| | | getAlarmTypeProEcharts(){ |
| | | let echarts = require('echarts'); |
| | | let myChart = echarts.init(document.getElementById('alarmTypeProEcharts')); |
| | | let option = { |
| | | title: { |
| | | textStyle: { |
| | | fontWeight: 'normal', |
| | | fontSize: 16, |
| | | color: '#000' |
| | | }, |
| | | left: '1%', |
| | | top: 25, |
| | | textAlign:'left', |
| | | text: '预警类型占比' |
| | | }, |
| | | tooltip: { |
| | | trigger: 'item' |
| | | }, |
| | | grid: { |
| | | left: '1%', |
| | | right: '10%', |
| | | bottom: '5%', |
| | | top:'25%', |
| | | containLabel: true |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '访问来源', |
| | | type: 'pie', |
| | | radius: ['43%','60%'], |
| | | center: ['45%','53%'], |
| | | avoidLabelOverlap: false, |
| | | label: { |
| | | show: false, |
| | | position: 'center' |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: '40', |
| | | fontWeight: 'bold' |
| | | } |
| | | }, |
| | | labelLine: { |
| | | show: false |
| | | }, |
| | | data: [ |
| | | {value: 1048, name: '搜索引擎'}, |
| | | {value: 735, name: '直接访问'}, |
| | | {value: 580, name: '邮件营销'}, |
| | | {value: 484, name: '联盟广告'}, |
| | | {value: 300, name: '视频广告'} |
| | | ] |
| | | } |
| | | ] |
| | | }; |
| | | myChart.setOption(option); |
| | | |
| | | //建议加上以下这一行代码,不加的效果图如下(当浏览器窗口缩小的时候)。超过了div的界限(红色边框) |
| | | window.addEventListener('resize',function() {myChart.resize()}); |
| | | }, |
| | | |
| | | |
| | | //警情类别统计总数(分类占比) |
| | | getAlarmTypeProStatis(){ |
| | | var that = this; |
| | | that.alarmTypeProStatis.data = [ |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'一键求助', |
| | | color:'yellow', |
| | | target:'_blank', |
| | | name:'0', |
| | | date:'0.00%' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'违禁品', |
| | | color:'green', |
| | | name:'0', |
| | | date:'0.00%' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'红色健康码', |
| | | color:'#3fa1ff', |
| | | name:'0', |
| | | date:'0.00%' |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'体温异常', |
| | | color:'red', |
| | | name:'0', |
| | | date:'0.00%' |
| | | } |
| | | ]; |
| | | }, |
| | | |
| | | |
| | | |
| | | //预警设备类型占比统计 |
| | | getAlarmEquipmentProEcharts(){ |
| | | let echarts = require('echarts'); |
| | | let myChart = echarts.init(document.getElementById('alarmEquipmentProEcharts')); |
| | | let option = { |
| | | title: { |
| | | textStyle: { |
| | | fontWeight: 'normal', |
| | | fontSize: 16, |
| | | color: '#000' |
| | | }, |
| | | left: '1%', |
| | | top: 25, |
| | | textAlign:'left', |
| | | text: '预警设备类型占比' |
| | | }, |
| | | tooltip: { |
| | | trigger: 'item' |
| | | }, |
| | | grid: { |
| | | left: '1%', |
| | | right: '10%', |
| | | bottom: '5%', |
| | | top:'25%', |
| | | containLabel: true |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '访问来源', |
| | | type: 'pie', |
| | | radius: ['43%','60%'], |
| | | cneter: ['45%','53%'], |
| | | avoidLabelOverlap: false, |
| | | label: { |
| | | show: false, |
| | | position: 'center' |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: '40', |
| | | fontWeight: 'bold' |
| | | } |
| | | }, |
| | | labelLine: { |
| | | show: false |
| | | }, |
| | | data: [ |
| | | {value: 1048, name: '搜索引擎'}, |
| | | {value: 735, name: '直接访问'}, |
| | | {value: 580, name: '邮件营销'}, |
| | | {value: 484, name: '联盟广告'}, |
| | | {value: 300, name: '视频广告'} |
| | | ] |
| | | } |
| | | ] |
| | | }; |
| | | myChart.setOption(option); |
| | | |
| | | //建议加上以下这一行代码,不加的效果图如下(当浏览器窗口缩小的时候)。超过了div的界限(红色边框) |
| | | window.addEventListener('resize',function() {myChart.resize()}); |
| | | }, |
| | | |
| | | //预警设备类型占比统计(分类表格) |
| | | getAlarmEquipmentProStatis(){ |
| | | var that = this; |
| | | that.alarmEquipmentProStatisData=[ |
| | | { |
| | | name:'一键求助', |
| | | sex:'1', |
| | | date:'100%' |
| | | } |
| | | ]; |
| | | that.alarmEquipmentProStatisOption={ |
| | | menu:false, |
| | | menuBtn:false, |
| | | page:false, |
| | | align:'center', |
| | | menuAlign:'center', |
| | | column:[ |
| | | { |
| | | label:'预警设备类型', |
| | | prop:'name' |
| | | }, |
| | | { |
| | | label:'预警次数', |
| | | prop:'sex' |
| | | },{ |
| | | label: "占比", |
| | | prop: "date" |
| | | } |
| | | ] |
| | | } |
| | | |
| | | |
| | | }, |
| | | |
| | | |
| | | //确认时间占比统计 |
| | | getConfirmTimeProEcharts(){ |
| | | let echarts = require('echarts'); |
| | | let myChart = echarts.init(document.getElementById('confirmTimeProEcharts')); |
| | | let option = { |
| | | title: { |
| | | textStyle: { |
| | | fontWeight: 'normal', |
| | | fontSize: 16, |
| | | color: '#000' |
| | | }, |
| | | left: '1%', |
| | | top: 25, |
| | | textAlign:'left', |
| | | text: '确认时间占比' |
| | | }, |
| | | tooltip: { |
| | | trigger: 'item' |
| | | }, |
| | | grid: { |
| | | left: '1%', |
| | | right: '10%', |
| | | bottom: '5%', |
| | | top:'25%', |
| | | containLabel: true |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '访问来源', |
| | | type: 'pie', |
| | | radius: ['43%', '60%'], |
| | | center: ['45%','53%'], |
| | | avoidLabelOverlap: false, |
| | | label: { |
| | | show: false, |
| | | position: 'center' |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: '40', |
| | | fontWeight: 'bold' |
| | | } |
| | | }, |
| | | labelLine: { |
| | | show: false |
| | | }, |
| | | data: [ |
| | | {value: 1048, name: '搜索引擎'}, |
| | | {value: 735, name: '直接访问'}, |
| | | {value: 580, name: '邮件营销'}, |
| | | {value: 484, name: '联盟广告'}, |
| | | {value: 300, name: '视频广告'} |
| | | ] |
| | | } |
| | | ] |
| | | }; |
| | | myChart.setOption(option); |
| | | |
| | | //建议加上以下这一行代码,不加的效果图如下(当浏览器窗口缩小的时候)。超过了div的界限(红色边框) |
| | | window.addEventListener('resize',function() {myChart.resize()}); |
| | | }, |
| | | |
| | | //确认时间占比(分类) |
| | | getConfirmTimeProStatis(){ |
| | | var that = this; |
| | | that.confirmTimeProStatis.data = [ |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'小于5分钟', |
| | | color:'yellow', |
| | | target:'_blank', |
| | | name:'0', |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'5-10分钟', |
| | | color:'green', |
| | | name:'0', |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'10-30分钟', |
| | | color:'#3fa1ff', |
| | | name:'0', |
| | | }, |
| | | { |
| | | click: function (item) { |
| | | }, |
| | | title:'30分钟以上', |
| | | color:'red', |
| | | name:'0', |
| | | } |
| | | ]; |
| | | }, |
| | | |
| | | //预警平均速度排行(table) |
| | | confirmAverageSpeedStatis(){ |
| | | var that = this; |
| | | that.confirmAverageSpeedData=[ |
| | | { |
| | | name:'mis_zhang', |
| | | sex:'1', |
| | | } |
| | | ]; |
| | | that.confirmAverageSpeedOption={ |
| | | title:'表格的标题', |
| | | titleSize:'h3', |
| | | titleStyle:{ |
| | | color:'red' |
| | | }, |
| | | menu:false, |
| | | page:false, |
| | | align:'center', |
| | | menuAlign:'center', |
| | | column:[ |
| | | { |
| | | label:'巡检人', |
| | | prop:'name' |
| | | }, |
| | | { |
| | | label:'平均确认速度', |
| | | prop:'sex' |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | |
| | | //预警时间分布 |
| | | getAlarmTimeDisEchars(){ |
| | | let echarts = require('echarts'); |
| | | let myChart = echarts.init(document.getElementById('alarmTimeDisEchars')); |
| | | let option = { |
| | | title: { |
| | | textStyle: { |
| | | fontWeight: 'normal', |
| | | fontSize: 16, |
| | | color: '#000' |
| | | }, |
| | | left: '3%', |
| | | top: 25, |
| | | textAlign:'center', |
| | | text: '预警时间分布' |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | legend: { |
| | | data: ['一键求助', '违禁品', '红色健康码', '体温异常'], |
| | | top:'10%', |
| | | right:'6%' |
| | | }, |
| | | grid: { |
| | | left: '1%', |
| | | right: '7%', |
| | | bottom: '10%', |
| | | top:'25%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | splitLine: { |
| | | show: true, |
| | | lineStyle:{ |
| | | type:'dashed' |
| | | } |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '一键求助', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [120, 132, 101, 134, 90, 230, 210] |
| | | }, |
| | | { |
| | | name: '违禁品', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [220, 182, 191, 234, 290, 330, 310] |
| | | }, |
| | | { |
| | | name: '红色健康码', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [150, 232, 201, 154, 190, 330, 410] |
| | | }, |
| | | { |
| | | name: '体温异常', |
| | | type: 'line', |
| | | stack: '总量', |
| | | data: [320, 332, 301, 334, 390, 330, 320] |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | myChart.setOption(option); |
| | | |
| | | //建议加上以下这一行代码,不加的效果图如下(当浏览器窗口缩小的时候)。超过了div的界限(红色边框) |
| | | window.addEventListener('resize',function() {myChart.resize()}); |
| | | }, |
| | | |
| | | //点击按钮获取不同时间段的数据 |
| | | getData(data){ |
| | | var that = this; |
| | | var today = new Date(); |
| | | var startTime =''; |
| | | var endTime = ''; |
| | | //本周的时间 |
| | | if(data==1){ |
| | | startTime = this.showWeekFirstDay(today); |
| | | endTime = this.showToDay(today); |
| | | that.dateTime = [startTime,endTime]; |
| | | } |
| | | //月初至今的时间 |
| | | if(data==2){ |
| | | startTime = this.showMonthFirstDay(today); |
| | | endTime = this.showToDay(today); |
| | | that.dateTime = [startTime,endTime]; |
| | | } |
| | | //本季度初至今的时间 |
| | | if(data==3){ |
| | | startTime = this.getQuarterStartDate(today); |
| | | endTime = this.showToDay(today); |
| | | that.dateTime = [startTime,endTime]; |
| | | } |
| | | //封装数据 |
| | | var data = {}; |
| | | data ={ |
| | | startTime:this.dateTime[0], |
| | | endTime:this.dateTime[1] |
| | | } |
| | | console.log(data,111); |
| | | //调用方法 |
| | | }, |
| | | |
| | | //本日 |
| | | showToDay(Nowdate){ |
| | | var M=Number(Nowdate.getMonth())+1; |
| | | console.log(Nowdate.getFullYear,111); |
| | | return Nowdate.getFullYear()+"-"+M+"-"+Nowdate.getDate(); |
| | | }, |
| | | |
| | | //本周第一天 |
| | | showWeekFirstDay(Nowdate){ |
| | | var WeekFirstDay=new Date(Nowdate-(Nowdate.getDay()-1)*86400000); |
| | | var M=Number(WeekFirstDay.getMonth())+1; |
| | | return WeekFirstDay.getFullYear()+"-"+M+"-"+WeekFirstDay.getDate(); |
| | | }, |
| | | |
| | | //本月第一天 |
| | | showMonthFirstDay(Nowdate){ |
| | | var MonthFirstDay=new Date(Nowdate.getFullYear(),Nowdate.getMonth(),1); |
| | | var M=Number(MonthFirstDay.getMonth())+1 |
| | | return MonthFirstDay.getFullYear()+"-"+M+"-"+MonthFirstDay.getDate(); |
| | | }, |
| | | |
| | | //本季度的第一天 |
| | | getQuarterStartDate(Nowdate){ |
| | | var quarterStartDate = this.getQuarterStartMonth(Nowdate); |
| | | return Nowdate.getFullYear()+"-"+quarterStartDate+"-"+"01"; |
| | | }, |
| | | |
| | | |
| | | //本季度的第一个月份 |
| | | getQuarterStartMonth(Nowdate){ |
| | | var nowMonth = Nowdate.getMonth()+1; |
| | | console.log(nowMonth,555); |
| | | var quarterStartMonth = 0; |
| | | if(nowMonth<4){ |
| | | quarterStartMonth = "0"+1; |
| | | } |
| | | if(3<nowMonth && nowMonth<7){ |
| | | quarterStartMonth = "0"+4; |
| | | } |
| | | if(6<nowMonth && nowMonth<10){ |
| | | quarterStartMonth = "0"+7; |
| | | } |
| | | if(nowMonth>9){ |
| | | quarterStartMonth = 10; |
| | | } |
| | | return quarterStartMonth; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | }, |
| | | |
| | | } |
| | | |
| | | |
| | | </script> |
| | | <style lang="scss"> |
| | | .el-button.btn-color { |
| | | color: rgb(255, 255, 255); |
| | | background-color: #29C093; |
| | | border-color: #29C093; |
| | | } |
| | | @import '@/styles/alarmAnalysis/alarmAnalysis.scss' |
| | | |
| | | </style> |
| | |
| | | menu:false, |
| | | height:'auto', |
| | | calcHeight: 30, |
| | | border: false, |
| | | stripe:true, |
| | | tip: false, |
| | | searchShow: true, |
| | | searchMenuSpan: 6, |
| | | activeClass: 0, |
| | | border: true, |
| | | index: true, |
| | | viewBtn: true, |
| | | selection: true, |
| | |
| | | } |
| | | ], |
| | | } |
| | | |
| | | |
| | | ] |
| | | }, |
| | | data: [] |
| | |
| | | return ids.join(","); |
| | | } |
| | | }, |
| | | |
| | | |
| | | methods: { |
| | | beforeOpen(done, type) { |
| | | }, |
| | |
| | | </div> |
| | | </div> |
| | | <div class="r-b-map"> |
| | | <iframe |
| | | id="mapDiv" |
| | | ref="mapDiv" |
| | | <el-row> |
| | | <iframe |
| | | id="supervisoryMap" |
| | | ref="supervisoryMap" |
| | | :src="baseUrl" |
| | | frameborder="0" |
| | | width="100%" |
| | | height="100%" |
| | | ></iframe> |
| | | ></iframe> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | import echarts from 'echarts' |
| | | const cityOptions = ['未确认', '真实火警', '非真实火警', '测试/巡检', '安全隐患']; |
| | | export default { |
| | | created() { |
| | | this.baseUrl = `/map/index.html?openid=SupervisoryMap`; |
| | | }, |
| | | data(){ |
| | | return{ |
| | | name: '婴滋诚红谷滩凤凰花园东区', |
| | |
| | | >本月 |
| | | </el-button> |
| | | </template> |
| | | |
| | | |
| | | </avue-crud> |
| | | </basic-container> |
| | | </template> |
| | |
| | | menu:false, |
| | | height:'auto', |
| | | calcHeight: 30, |
| | | border: false, |
| | | stripe:true, |
| | | tip: false, |
| | | searchShow: true, |
| | | searchMenuSpan: 6, |
| | | activeClass: 0, |
| | | border: true, |
| | | index: true, |
| | | viewBtn: true, |
| | | selection: true, |
| | |
| | | status:this.$route.query.status, |
| | | type:this.$route.query.type |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | if (dateTime) { |
| | |
| | | background-color: rgb(64, 158, 255); |
| | | border-color: rgb(64, 158, 255); |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | * @LastEditTime: 2021-03-18 10:37:42 |
| | | --> |
| | | <template> |
| | | <iframe v-show="iframeState" id="show-iframe" frameborder=0 name="showHere" scrolling=auto |
| | | src="https://web.byisf.com/bigScreen/view/1349193280059879426"></iframe> |
| | | <iframe |
| | | v-show="iframeState" |
| | | id="show-iframe" |
| | | frameborder="0" |
| | | name="showHere" |
| | | scrolling="auto" |
| | | src="https://web.byisf.com/bigScreen/view/1349193280059879426" |
| | | ></iframe> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "tcgl.vue", |
| | | created() { |
| | | //this.getData(); |
| | | export default { |
| | | name: "tcgl.vue", |
| | | created() { |
| | | //this.getData(); |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogTableVisible: false, |
| | | form: {}, |
| | | }; |
| | | }, |
| | | mounted() { |
| | | window.handleStartAnimalHeat = this.handleStartAnimalHeat; |
| | | window.handleStartHealthcode = this.handleStartHealthcode; |
| | | window.handleStartAlarm = this.handleStartAlarm; |
| | | window.handleStartEquipment = this.handleStartEquipment; |
| | | window.handleStartSuser = this.handleStartSuser; |
| | | window.handleStartParcel = this.handleStartParcel; |
| | | window.handleStartParcelKind = this.handleStartParcelKind; |
| | | }, |
| | | methods: { |
| | | //体温监测分页数据 |
| | | handleStartAnimalHeat(data) { |
| | | this.$router.push({ |
| | | path: `/animalHeat/animalHeatPage`, |
| | | query: data[0], |
| | | }); |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogTableVisible:false, |
| | | form: {}, |
| | | } |
| | | //健康码分页数据 |
| | | handleStartHealthcode(data) { |
| | | this.$router.push({ |
| | | path: `/healthcode/healthcodePage`, |
| | | query: data[0], |
| | | }); |
| | | }, |
| | | mounted() { |
| | | window.handleStartAnimalHeat = this.handleStartAnimalHeat; |
| | | window.handleStartHealthcode = this.handleStartHealthcode; |
| | | window.handleStartAlarm = this.handleStartAlarm; |
| | | window.handleStartEquipment = this.handleStartEquipment; |
| | | window.handleStartSuser=this.handleStartSuser; |
| | | window.handleStartParcel=this.handleStartParcel; |
| | | window.handleStartParcelKind=this.handleStartParcelKind; |
| | | //主动报警(一键求助,电话报警)分页数据 |
| | | handleStartAlarm(data) { |
| | | this.$router.push({ |
| | | path: `/realTimePolice/index`, |
| | | query: data[0], |
| | | }); |
| | | }, |
| | | methods: { |
| | | //体温监测分页数据 |
| | | handleStartAnimalHeat(data) { |
| | | this.$router.push({ |
| | | path: `/animalHeat/animalHeatPage`, |
| | | query: data[0] |
| | | }); |
| | | }, |
| | | //健康码分页数据 |
| | | handleStartHealthcode(data){ |
| | | this.$router.push({ |
| | | path: `/healthcode/healthcodePage`, |
| | | query: data[0] |
| | | }); |
| | | }, |
| | | //主动报警(一键求助,电话报警)分页数据 |
| | | handleStartAlarm(data){ |
| | | this.$router.push({ |
| | | path: `/realTimePolice/index`, |
| | | query: data[0] |
| | | }); |
| | | }, |
| | | //在线设备分页数据 |
| | | handleStartEquipment(data){ |
| | | this.$router.push({ |
| | | path: `/clientManagement/index`, |
| | | query: data[0] |
| | | }); |
| | | }, |
| | | //客户管理分页数据 |
| | | handleStartSuser(){ |
| | | this.$router.push({ |
| | | path: `/suser/index` |
| | | }); |
| | | }, |
| | | //包裹分页数据 |
| | | handleStartParcel(data){ |
| | | debugger; |
| | | this.$router.push({ |
| | | path: `/parcel/index`, |
| | | query: data[0] |
| | | }); |
| | | }, |
| | | //违禁品分页数据 |
| | | handleStartParcelKind(data){ |
| | | this.$router.push({ |
| | | path: `/parcelKind/index`, |
| | | query: data[0] |
| | | }); |
| | | } |
| | | //在线设备分页数据 |
| | | handleStartEquipment(data) { |
| | | this.$router.push({ |
| | | path: `/clientManagement/index`, |
| | | query: data[0], |
| | | }); |
| | | }, |
| | | //客户管理分页数据 |
| | | handleStartSuser() { |
| | | this.$router.push({ |
| | | path: `/suser/index`, |
| | | }); |
| | | }, |
| | | //包裹分页数据 |
| | | handleStartParcel(data) { |
| | | debugger; |
| | | this.$router.push({ |
| | | path: `/parcel/index`, |
| | | query: data[0], |
| | | }); |
| | | }, |
| | | //违禁品分页数据 |
| | | handleStartParcelKind(data) { |
| | | this.$router.push({ |
| | | path: `/parcelKind/index`, |
| | | query: data[0], |
| | | }); |
| | | }, |
| | | |
| | | // getData() { |
| | | // var that = this; |
| | | // |
| | | // window.clearTimeout(window.realTimeQuery); |
| | | // |
| | | // window.realTimeQuery = setInterval(function () { |
| | | // //that.dialogTableVisible = true; |
| | | // }, 3000); |
| | | // } |
| | | } |
| | | } |
| | | // getData() { |
| | | // var that = this; |
| | | // |
| | | // window.clearTimeout(window.realTimeQuery); |
| | | // |
| | | // window.realTimeQuery = setInterval(function () { |
| | | // //that.dialogTableVisible = true; |
| | | // }, 3000); |
| | | // } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | #show-iframe { |
| | | display: block !important; |
| | | height: 95%; |
| | | } |
| | | |
| | | #show-iframe { |
| | | display: block !important; |
| | | height: 95%; |
| | | |
| | | } |
| | | |
| | | .avue-main .avue-view { |
| | | height: 100%; |
| | | padding: 0px 5px !important; |
| | | } |
| | | |
| | | .avue-main .avue-view { |
| | | height: 100%; |
| | | padding: 5px 5px !important; |
| | | } |
| | | </style> |
| | |
| | | @size-change="sizeChange" |
| | | @refresh-change="refreshChange" |
| | | @on-load="onLoad"> |
| | | |
| | | |
| | | <!-- <template slot-scope="{ type, size, row }" slot="menu"> |
| | | |
| | | <el-button |
| | |
| | | >查看包裹图片 |
| | | </el-button> |
| | | </template> --> |
| | | |
| | | |
| | | </avue-crud> |
| | | <template> |
| | | <div> |
| | | <el-image-viewer |
| | | <el-image-viewer |
| | | class="img" |
| | | v-if="showViewer" |
| | | :on-close="closeViewer" |
| | | v-if="showViewer" |
| | | :on-close="closeViewer" |
| | | :url-list="['data:image/png;base64,'+imgUrl]" /> |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | </basic-container> |
| | | </template> |
| | | |
| | |
| | | searchShow: true, |
| | | searchMenuSpan: 6, |
| | | activeClass: 3, |
| | | border: true, |
| | | border: false, |
| | | stripe:true, |
| | | index: true, |
| | | viewBtn: true, |
| | | selection: true, |
| | |
| | | </avue-crud> |
| | | <template> |
| | | <div> |
| | | <el-image-viewer |
| | | <el-image-viewer |
| | | class="img" |
| | | v-if="showViewer" |
| | | :on-close="closeViewer" |
| | | v-if="showViewer" |
| | | :on-close="closeViewer" |
| | | :url-list="['data:image/png;base64,'+imgUrl]" /> |
| | | </div> |
| | | </template> |
| | |
| | | searchShow: true, |
| | | searchMenuSpan: 4, |
| | | menuWidth:150, |
| | | border: true, |
| | | border: false, |
| | | stripe:true, |
| | | index: true, |
| | | viewBtn: true, |
| | | selection: true, |
| | |
| | | }, |
| | | methods: { |
| | | beforeOpen(done, type) { |
| | | |
| | | |
| | | done(); |
| | | }, |
| | | searchReset() { |
| | |
| | | color: white; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | * @Author: Morpheus |
| | | * @Date: 2021-03-17 15:21:33 |
| | | * @Last Modified by: Morpheus |
| | | * @Last Modified time: 2021-03-29 14:12:05 |
| | | * @Last Modified time: 2021-04-07 17:36:33 |
| | | */ |
| | | <template> |
| | | <basic-container> |
| | |
| | | labelWidth: "100", |
| | | size: "mini", |
| | | border: false, |
| | | stripe:true, |
| | | stripe: true, |
| | | menuWidth: 240, |
| | | dialogWidth: 950, |
| | | tip: false, |
| | | searchShow: true, |
| | | searchMenuSpan: 3, |
| | | align:"center", |
| | | align: "center", |
| | | index: true, |
| | | viewBtn: true, |
| | | selection: true, |
| | |
| | | { |
| | | label: "报警人", |
| | | prop: "galarmPeople", |
| | | width: 90 |
| | | width: 90, |
| | | }, |
| | | { |
| | | label: "报警人电话", |
| | |
| | | { |
| | | label: "接警人", |
| | | prop: "alarmPeople", |
| | | width: 90 |
| | | width: 90, |
| | | }, |
| | | { |
| | | label: "接警时间", |
| | |
| | | return a.jtype - b.jtype; |
| | | }); |
| | | |
| | | |
| | | |
| | | this.data = data.records; |
| | | |
| | | this.loading = false; |
| | |
| | | ) |
| | | .then(function () { |
| | | that.dialogTableVisible = false; |
| | | |
| | | axios({ |
| | | method: "post", |
| | | url: `/api/blade-jfpts/rvideo/stop`, |
| | | params: { |
| | | jid: row.id, |
| | | }, |
| | | }).then((resdata) => {}); |
| | | |
| | | that.onLoad(that.page, that.query); |
| | | that.$router.push({ |
| | | path: "/policeTracking/track", |
| | |
| | | }); |
| | | |
| | | that.hls.on(Hls.Events.ERROR, function (event, data) { |
| | | |
| | | console.log(data, 4566824159, "视频播放有问题!!!") |
| | | console.log(data, 4566824159, "视频播放有问题!!!"); |
| | | if (data.fatal) { |
| | | switch (data.type) { |
| | | case Hls.ErrorTypes.NETWORK_ERROR: |
| | |
| | | border-color: rgb(64, 158, 255); |
| | | } |
| | | |
| | | .tabFontSize{ |
| | | .tabFontSize { |
| | | font-size: 15px; |
| | | } |
| | | |
| | | </style> |
| | |
| | | @row-save="rowSave" |
| | | :before-open="beforeOpen" |
| | | :row-style="rowStyle" |
| | | row-class-name="tabFontSize" |
| | | @search-change="searchChange" |
| | | @search-reset="searchReset" |
| | | @selection-change="selectionChange" |
| | |
| | | calcHeight: 30, |
| | | menuWidth: 240, |
| | | size: "mini", |
| | | border: false, |
| | | stripe:true, |
| | | labelWidth: "100", |
| | | dialogWidth: 950, |
| | | tip: false, |
| | | searchShow: true, |
| | | searchMenuSpan: 3, |
| | | border: true, |
| | | index: true, |
| | | viewBtn: true, |
| | | selection: true, |
| | |
| | | { |
| | | label: "报警时间", |
| | | type: "datetime", |
| | | width: 130, |
| | | width: 160, |
| | | format: "yyyy-MM-dd HH:mm:ss", |
| | | valueFormat: "yyyy-MM-dd HH:mm:ss", |
| | | prop: "alarmTime", |
| | |
| | | dicUrl: "/api/blade-system/region/select", |
| | | span: 6, |
| | | className: "cityClass1", |
| | | hide: true, |
| | | addDisplay: true, |
| | | editDisplay: true, |
| | | viewDisplay: true, |
| | | }, |
| | | { |
| | | label: "地市", |
| | |
| | | span: 3, |
| | | labelWidth: "0", |
| | | className: "cityClass2", |
| | | hide: true, |
| | | addDisplay: true, |
| | | editDisplay: true, |
| | | viewDisplay: true, |
| | | }, |
| | | { |
| | | label: "区县", |
| | |
| | | span: 3, |
| | | labelWidth: "0", |
| | | className: "cityClass3", |
| | | hide: true, |
| | | addDisplay: true, |
| | | editDisplay: true, |
| | | viewDisplay: true, |
| | | }, |
| | | { |
| | | label: "警情状态", |
| | |
| | | type: "datetime", |
| | | format: "yyyy-MM-dd HH:mm:ss", |
| | | valueFormat: "yyyy-MM-dd HH:mm:ss", |
| | | width: 130, |
| | | width: 160, |
| | | prop: "jjTime", |
| | | }, |
| | | ], |
| | |
| | | height: calc(100% - 44px); |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .tabFontSize{ |
| | | font-size: 15px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | |
| | | <el-row> |
| | | <el-col |
| | | class="card-container" |
| | | :span="1" |
| | | v-for="(item, index) in option" |
| | | :key="index" |
| | | > |
| | | <a href=""> |
| | | <el-card |
| | | :style=" |
| | | item.state == '' |
| | | ? item.onlineStatus == 1 |
| | | ? 'background: #1DBB99e6' |
| | | : 'background: #C9C9C9e6' |
| | | : 'background: #F48F57e6' |
| | | " |
| | | @click="alert(1)" |
| | | > |
| | | <div>{{ item.deviceName }}</div> |
| | | <div>{{ item.street }}</div> |
| | | |
| | | <div class="cet"> |
| | | {{ |
| | | item.state == "" |
| | | ? item.onlineStatus == 1 |
| | | ? "设备在线" |
| | | : "设备掉线" |
| | | : "设备故障" |
| | | }} |
| | | </div> |
| | | |
| | | <img src="/img/alarm.png" alt="" /> |
| | | |
| | | <div class="bot"> |
| | | <span> |
| | | {{ item.deviceNumber }} |
| | | </span> |
| | | <span> |
| | | {{ item.stime }} |
| | | </span> |
| | | </div> |
| | | </el-card> |
| | | </a> |
| | | </el-col> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getList } from "@/api/supervisory/card"; |
| | | export default { |
| | | data() { |
| | | return { |
| | | option: [], |
| | | }; |
| | | }, |
| | | created() { |
| | | getList().then((res) => { |
| | | var a = [], |
| | | b = [], |
| | | c = []; |
| | | |
| | | } |
| | | res.data.data.forEach((item) => { |
| | | if (item.state != "") a.push(item); |
| | | if (item.state == "" && item.onlineStatus != 1) b.push(item); |
| | | if (item.state == "" && item.onlineStatus == 1) c.push(item); |
| | | }); |
| | | |
| | | this.option = a.concat(c.concat(b)); |
| | | }); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | <style lang="scss"> |
| | | .card-container { |
| | | padding: 0 10px; |
| | | height: 172px !important; |
| | | box-sizing: border-box; |
| | | margin-bottom: 20px !important; |
| | | min-width: 368px; |
| | | max-width: 370px; |
| | | a { |
| | | width: 100%; |
| | | height: 100%; |
| | | cursor: pointer; |
| | | .el-card { |
| | | height: 100%; |
| | | color: #180808; |
| | | &:hover { |
| | | transform: scale(1.04); |
| | | } |
| | | .el-card__body { |
| | | position: relative; |
| | | height: 100%; |
| | | box-sizing: border-box; |
| | | .bot { |
| | | position: absolute; |
| | | left: 16px; |
| | | bottom: 16px; |
| | | width: calc(100% - 32px); |
| | | span:nth-child(1) { |
| | | float: left; |
| | | } |
| | | span:nth-child(2) { |
| | | float: right; |
| | | } |
| | | } |
| | | .cet { |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 16px; |
| | | } |
| | | div { |
| | | line-height: 24px; |
| | | font-size: 14px; |
| | | } |
| | | img { |
| | | position: absolute; |
| | | right: 16px; |
| | | top: 40%; |
| | | width: 40px; |
| | | } |
| | | } |
| | | } |
| | | &:hover { |
| | | color: #180808; |
| | | text-decoration: none; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div class="info-active-top"> |
| | | <div class="active-list"> |
| | | <div> |
| | | <span |
| | | ng-click="menuToDetail(0)" |
| | | class="dashboard_alarm ng-binding" |
| | | >预警</span |
| | | > |
| | | <span class="dashboard_alarm ng-binding">预警</span> |
| | | </div> |
| | | <div><span class="ng-binding">3</span></div> |
| | | <div class="ng-binding">占比 1.8%</div> |
| | | <div> |
| | | <span class="ng-binding">{{ yj }}</span> |
| | | </div> |
| | | <div class="ng-binding">占比 {{ yjper }}</div> |
| | | </div> |
| | | <div class="active-list"> |
| | | <div> |
| | | <span |
| | | ng-click="menuToDetail(4)" |
| | | class="dashboard_malfunction ng-binding" |
| | | >故障</span |
| | | > |
| | | <span class="dashboard_malfunction ng-binding">故障</span> |
| | | </div> |
| | | <div><span class="ng-binding">25</span></div> |
| | | <div class="ng-binding">占比 15%</div> |
| | | <div> |
| | | <span class="ng-binding">{{ gz }}</span> |
| | | </div> |
| | | <div class="ng-binding">占比 {{ gzper }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="info-active-bottom"> |
| | | <div class="active-list"> |
| | | <div> |
| | | <span |
| | | ng-click="menuToDetail(1)" |
| | | class="dashboard_normal ng-binding" |
| | | >正常</span |
| | | > |
| | | <span class="dashboard_normal ng-binding">正常</span> |
| | | </div> |
| | | <div><span class="ng-binding">125</span></div> |
| | | <div class="ng-binding">占比 75%</div> |
| | | <div> |
| | | <span class="ng-binding">{{ zx }}</span> |
| | | </div> |
| | | <div class="ng-binding">占比 {{ zxper }}</div> |
| | | </div> |
| | | <div class="active-list"> |
| | | <div> |
| | | <span |
| | | ng-click="menuToDetail(3)" |
| | | class="dashboard_inactive ng-binding" |
| | | >掉线</span |
| | | > |
| | | <span class="dashboard_inactive ng-binding">掉线</span> |
| | | </div> |
| | | <div><span class="ng-binding">15</span></div> |
| | | <div class="ng-binding">占比 10%</div> |
| | | <div> |
| | | <span class="ng-binding">{{ dx }}</span> |
| | | </div> |
| | | <div class="ng-binding">占比 {{ dxper }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | :data="tableData" |
| | | stripe |
| | | style="width: 100%; margin: 10px" |
| | | max-height="352px" |
| | | max-height="380px" |
| | | :resizable="false" |
| | | > |
| | | <el-table-column prop="waringType" label="警情类型" width="100"> |
| | |
| | | getList, |
| | | getEquipmentList, |
| | | getDayWarnList, |
| | | getEquipment, |
| | | } from "@/api/supervisory/data"; |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | tableData: [], |
| | | dx: null, |
| | | zx: null, |
| | | gz: null, |
| | | yj: null, |
| | | dxper: null, |
| | | zxper: null, |
| | | gzper: null, |
| | | yjper: null, |
| | | }; |
| | | }, |
| | | created() { |
| | |
| | | getDayWarnList().then((res) => { |
| | | that.drawPillar(res.data.data); |
| | | }); |
| | | |
| | | getEquipment().then((res) => { |
| | | console.log(res.data.data, 123); |
| | | |
| | | var total = 0; |
| | | |
| | | total += res.data.data.zx; |
| | | total += res.data.data.dx; |
| | | total += res.data.data.gz; |
| | | |
| | | console.log(total, 45); |
| | | |
| | | that.dx = res.data.data.dx; |
| | | that.zx = res.data.data.zx; |
| | | that.gz = res.data.data.gz; |
| | | that.yj = res.data.data.yj; |
| | | that.dxper = ((res.data.data.dx / total) * 100).toFixed(2) + "%"; |
| | | that.zxper = ((res.data.data.zx / total) * 100).toFixed(2) + "%"; |
| | | that.gzper = ((res.data.data.gz / total) * 100).toFixed(2) + "%"; |
| | | that.yjper = ((res.data.data.yj / total) * 100).toFixed(2) + "%"; |
| | | |
| | | that.drawPie(); |
| | | }); |
| | | }, |
| | | mounted() { |
| | | this.drawPie(); |
| | | }, |
| | | mounted() {}, |
| | | methods: { |
| | | drawPie() { |
| | | var that = this; |
| | | var myChart = this.$echarts.init( |
| | | document.getElementById("base_information_pie_echarts") |
| | | ); |
| | | |
| | | var m2R2Data = [ |
| | | { |
| | | value: 125, |
| | | value: that.zx, |
| | | legendname: "正常", |
| | | name: "正常", |
| | | itemStyle: { color: "#29c194" }, |
| | | }, |
| | | { |
| | | value: 25, |
| | | value: that.gz, |
| | | legendname: "故障", |
| | | name: "故障", |
| | | itemStyle: { color: "#b6b6b6" }, |
| | | }, |
| | | { |
| | | value: 15, |
| | | value: that.dx, |
| | | legendname: "掉线", |
| | | name: "掉线", |
| | | itemStyle: { color: "#6d5eac" }, |
| | | itemStyle: { color: "#F48F57" }, |
| | | }, |
| | | ]; |
| | | |
| | |
| | | trigger: "item", |
| | | formatter: function (parms) { |
| | | var str = |
| | | parms.seriesName + |
| | | "</br>" + |
| | | parms.marker + |
| | | "" + |
| | | parms.data.legendname + |
| | |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "标题", |
| | | type: "pie", |
| | | center: ["50%", "50%"], |
| | | radius: ["66%", "86%"], |
| | |
| | | |
| | | data.dataList.forEach((item) => { |
| | | if (item.name == "一键求助") { |
| | | yData = item.alarmData |
| | | yData = item.alarmData; |
| | | } |
| | | }); |
| | | |
| | |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | margin-bottom: 0px !important; |
| | | height: 96% !important; |
| | | height: 100% !important; |
| | | font-size: 14px; |
| | | &:nth-child(2) { |
| | | padding-left: 10px; |
| | |
| | | background-color: #29c093; |
| | | } |
| | | &:nth-child(3)::before { |
| | | background-color: #6d5eac; |
| | | background-color: #F48F57; |
| | | } |
| | | &:nth-child(4)::before { |
| | | background-color: #dfdfdf; |
| | |
| | | color: #29c194; |
| | | } |
| | | .active-list:nth-child(2) > div:nth-child(1) span { |
| | | border: 1px solid #6d5eac; |
| | | color: #6d5eac; |
| | | border: 1px solid #F48F57; |
| | | color: #F48F57; |
| | | } |
| | | .active-list:nth-child(1) > div:nth-child(1) span:hover { |
| | | background: rgba(41, 192, 147, 0.15); |
| | | } |
| | | .active-list:nth-child(2) > div:nth-child(1) span:hover { |
| | | background: #e9e7f3; |
| | | background: #f3ab8448; |
| | | } |
| | | .active-list:nth-child(1) > div:nth-child(2) span { |
| | | color: #29c194; |
| | | } |
| | | .active-list:nth-child(2) > div:nth-child(2) span { |
| | | color: #6d5eac; |
| | | color: #F48F57; |
| | | } |
| | | } |
| | | .info-active-top, |
| | |
| | | <template> |
| | | <iframe src="" frameborder="0"></iframe> |
| | | <el-row> |
| | | <iframe |
| | | id="supervisoryMap" |
| | | ref="supervisoryMap" |
| | | :src="baseUrl" |
| | | frameborder="0" |
| | | width="100%" |
| | | height="100%" |
| | | ></iframe> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | |
| | | } |
| | | data() { |
| | | return { |
| | | baseUrl: "", |
| | | }; |
| | | }, |
| | | created() { |
| | | this.baseUrl = `/map/index.html?openid=SupervisoryMap`; |
| | | }, |
| | | mounted() { |
| | | // this.$refs.supervisoryMap.onload = () => { |
| | | // window.frames[0].init("AlertSecurity", { |
| | | // x: this.form.jd, |
| | | // y: this.form.wd, |
| | | // }); |
| | | // }; |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
| | |
| | | proxy: { |
| | | '/api': { |
| | | //本地服务接口地址 |
| | | //target: 'http://localhost:82/', |
| | | // target: 'http://192.168.0.111:82/', |
| | | target: 'https://web.byisf.com/api/', |
| | | //远程演示服务地址,可用于直接启动项目 |
| | | //target: 'https://saber.bladex.vip/api', |