Commit ec1ef1a51a646f3e4320a26454520978988897fd

Authored by 潘钊
1 parent a388c8b5

update

Showing 31 changed files with 2565 additions and 390 deletions
src/main/java/com/bsth/controller/realcontrol/ScheduleRealInfoController.java
@@ -38,4 +38,20 @@ public class ScheduleRealInfoController extends BaseController<ScheduleRealInfo, @@ -38,4 +38,20 @@ public class ScheduleRealInfoController extends BaseController<ScheduleRealInfo,
38 public Map<String, Object> outgoAdjust(@RequestParam Long id, @RequestParam String remarks,@RequestParam String dfsj){ 38 public Map<String, Object> outgoAdjust(@RequestParam Long id, @RequestParam String remarks,@RequestParam String dfsj){
39 return scheduleRealInfoService.outgoAdjust(id, remarks, dfsj); 39 return scheduleRealInfoService.outgoAdjust(id, remarks, dfsj);
40 } 40 }
  41 +
  42 + /**
  43 + *
  44 + * @Title: destroy
  45 + * @Description: TODO(销毁,烂班)
  46 + * @param @param idsStr 要烂掉的班次ID ,分隔
  47 + * @param @param spaceAdjust 自动调整后续间隔(1 是 -1 否)
  48 + * @param @param remarks 备注
  49 + * @param @param reason 理由
  50 + * @param @param spaceNum 间隔(分钟)
  51 + * @throws
  52 + */
  53 + @RequestMapping(value = "/destroy", method = RequestMethod.POST)
  54 + public Map<String, Object> destroy(@RequestParam String idsStr,@RequestParam int spaceAdjust,@RequestParam String remarks,@RequestParam String reason,@RequestParam int spaceNum){
  55 + return scheduleRealInfoService.destroy(idsStr, spaceAdjust, remarks, reason, spaceNum);
  56 + }
41 } 57 }
src/main/java/com/bsth/entity/realcontrol/ScheduleRealInfo.java
@@ -92,47 +92,42 @@ public class ScheduleRealInfo { @@ -92,47 +92,42 @@ public class ScheduleRealInfo {
92 @Column(name = "update_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") 92 @Column(name = "update_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
93 private Date updateDate; 93 private Date updateDate;
94 94
95 - /**  
96 - * 实际发车时间  
97 - */ 95 + /** 实际发车时间*/
98 private String fcsjActual; 96 private String fcsjActual;
99 - /**  
100 - * 实际终点时间  
101 - */ 97 + /**实际终点时间 */
102 private String zdsjActual; 98 private String zdsjActual;
103 99
104 - /**  
105 - * 班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班  
106 - *  
107 - */ 100 + /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */
108 private int status; 101 private int status;
109 102
110 - /**  
111 - * 是否误点  
112 - */ 103 + /** 是否误点*/
113 private boolean isLate; 104 private boolean isLate;
114 105
115 - /**  
116 - * 实际里程  
117 - */ 106 + /**实际里程*/
118 private Float realMileage; 107 private Float realMileage;
119 108
120 - /**  
121 - * 备注  
122 - */ 109 + /** 备注*/
123 private String remarks; 110 private String remarks;
124 111
125 - /**  
126 - * 待发时间(格式 HH:mm)  
127 - */ 112 + /**待发时间(格式 HH:mm) */
128 private String dfsj; 113 private String dfsj;
129 114
130 - /**  
131 - * 发车时间戳  
132 - */ 115 + /**待发时间戳 */
  116 + @Transient
  117 + private Long dfsjT;
  118 +
  119 + /** 发车时间戳*/
133 @Transient 120 @Transient
134 private Long fcsjT; 121 private Long fcsjT;
135 - 122 +
  123 + public void addRemarks(String remark){
  124 + String newRem = this.getRemarks();
  125 + if(null == newRem)
  126 + newRem = "";
  127 + newRem += remark;
  128 + this.setRemarks(newRem);
  129 + }
  130 +
136 public Long getId() { 131 public Long getId() {
137 return id; 132 return id;
138 } 133 }
@@ -444,4 +439,12 @@ public class ScheduleRealInfo { @@ -444,4 +439,12 @@ public class ScheduleRealInfo {
444 public void setFcsjT(Long fcsjT) { 439 public void setFcsjT(Long fcsjT) {
445 this.fcsjT = fcsjT; 440 this.fcsjT = fcsjT;
446 } 441 }
  442 +
  443 + public Long getDfsjT() {
  444 + return dfsjT;
  445 + }
  446 +
  447 + public void setDfsjT(Long dfsjT) {
  448 + this.dfsjT = dfsjT;
  449 + }
447 } 450 }
src/main/java/com/bsth/service/realcontrol/GetSchedulePlanThread.java
@@ -56,6 +56,7 @@ public class GetSchedulePlanThread extends Thread{ @@ -56,6 +56,7 @@ public class GetSchedulePlanThread extends Thread{
56 item.setDfsj(item.getFcsj()); 56 item.setDfsj(item.getFcsj());
57 //发车时间戳 57 //发车时间戳
58 item.setFcsjT(sdf2.parse(dateStr + " " + item.getFcsj()).getTime()); 58 item.setFcsjT(sdf2.parse(dateStr + " " + item.getFcsj()).getTime());
  59 + item.setDfsjT(item.getFcsjT());
59 } 60 }
60 61
61 //new BatchSaveUtils<ScheduleRealInfo>().saveList(realList, ScheduleRealInfo.class); 62 //new BatchSaveUtils<ScheduleRealInfo>().saveList(realList, ScheduleRealInfo.class);
src/main/java/com/bsth/service/realcontrol/ScheduleBuffer.java
@@ -32,6 +32,11 @@ public class ScheduleBuffer { @@ -32,6 +32,11 @@ public class ScheduleBuffer {
32 public static ArrayListMultimap<String, ScheduleRealInfo> schedulListMap; 32 public static ArrayListMultimap<String, ScheduleRealInfo> schedulListMap;
33 33
34 /** 34 /**
  35 + * K: 车辆自编号 V: 班次链表
  36 + */
  37 + public static Map<String, LinkedList<ScheduleRealInfo>> vehLinkedMap;
  38 +
  39 + /**
35 * 主键 和 排班映射 40 * 主键 和 排班映射
36 */ 41 */
37 public static Map<Long, ScheduleRealInfo> pkSchedulMap; 42 public static Map<Long, ScheduleRealInfo> pkSchedulMap;
@@ -45,6 +50,7 @@ public class ScheduleBuffer { @@ -45,6 +50,7 @@ public class ScheduleBuffer {
45 schedulListMap = ArrayListMultimap.create(); 50 schedulListMap = ArrayListMultimap.create();
46 pkSchedulMap = new HashMap<>(); 51 pkSchedulMap = new HashMap<>();
47 persistentList = new LinkedList<>(); 52 persistentList = new LinkedList<>();
  53 + vehLinkedMap = new HashMap<>();
48 } 54 }
49 55
50 public static int init(List<ScheduleRealInfo> list){ 56 public static int init(List<ScheduleRealInfo> list){
@@ -59,9 +65,17 @@ public class ScheduleBuffer { @@ -59,9 +65,17 @@ public class ScheduleBuffer {
59 } 65 }
60 }); 66 });
61 67
  68 + String zbh;
62 for(ScheduleRealInfo schedul : list){ 69 for(ScheduleRealInfo schedul : list){
63 schedulListMap.put(schedul.getXlBm(), schedul); 70 schedulListMap.put(schedul.getXlBm(), schedul);
64 pkSchedulMap.put(schedul.getId(), schedul); 71 pkSchedulMap.put(schedul.getId(), schedul);
  72 +
  73 + //初始化车辆和班次列表对照
  74 + zbh = schedul.getClZbh();
  75 + if(!vehLinkedMap.containsKey(zbh))
  76 + vehLinkedMap.put(zbh, new LinkedList<ScheduleRealInfo>());
  77 +
  78 + vehLinkedMap.get(zbh).add(schedul);
65 } 79 }
66 }catch(Exception e){ 80 }catch(Exception e){
67 logger.error("缓存排班数据失败...", e); 81 logger.error("缓存排班数据失败...", e);
src/main/java/com/bsth/service/realcontrol/ScheduleRealInfoService.java
@@ -15,4 +15,6 @@ public interface ScheduleRealInfoService extends BaseService&lt;ScheduleRealInfo, L @@ -15,4 +15,6 @@ public interface ScheduleRealInfoService extends BaseService&lt;ScheduleRealInfo, L
15 15
16 Map<String, Object> outgoAdjust(Long id, String remarks, String dfsj); 16 Map<String, Object> outgoAdjust(Long id, String remarks, String dfsj);
17 17
  18 + Map<String, Object> destroy(String idsStr, int spaceAdjust, String remarks, String reason, int spaceNum);
  19 +
18 } 20 }
src/main/java/com/bsth/service/realcontrol/impl/ScheduleRealInfoServiceImpl.java
1 package com.bsth.service.realcontrol.impl; 1 package com.bsth.service.realcontrol.impl;
2 2
  3 +import java.text.SimpleDateFormat;
  4 +import java.util.ArrayList;
3 import java.util.Collection; 5 import java.util.Collection;
  6 +import java.util.Date;
4 import java.util.HashMap; 7 import java.util.HashMap;
5 import java.util.List; 8 import java.util.List;
6 import java.util.Map; 9 import java.util.Map;
@@ -29,18 +32,19 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf @@ -29,18 +32,19 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
29 32
30 Logger logger = LoggerFactory.getLogger(this.getClass()); 33 Logger logger = LoggerFactory.getLogger(this.getClass());
31 34
  35 + SimpleDateFormat sdfMonth = new SimpleDateFormat("yyyy-MM-dd")
  36 + , sdfMinute = new SimpleDateFormat("yyyy-MM-dd HH:mm")
  37 + , sdfShort = new SimpleDateFormat("HH:mm");
  38 +
32 @Override 39 @Override
33 public Map<String, Collection<ScheduleRealInfo>> findByLines(String lines) { 40 public Map<String, Collection<ScheduleRealInfo>> findByLines(String lines) {
34 List<String> lineList = Lists.newArrayList(Splitter.on(',').trimResults().omitEmptyStrings().split(lines)); 41 List<String> lineList = Lists.newArrayList(Splitter.on(',').trimResults().omitEmptyStrings().split(lines));
35 - List<ScheduleRealInfo> list = scheduleRealInfoRepository.findByLines(lineList);  
36 42
37 - //按线路编码分组  
38 Multimap<String, ScheduleRealInfo> mMap = ArrayListMultimap.create(); 43 Multimap<String, ScheduleRealInfo> mMap = ArrayListMultimap.create();
39 44
40 - for(ScheduleRealInfo item : list){  
41 - mMap.put(item.getXlBm(), item); 45 + for(String lineCode : lineList){
  46 + mMap.putAll(lineCode, ScheduleBuffer.schedulListMap.get(lineCode));
42 } 47 }
43 -  
44 return mMap.asMap(); 48 return mMap.asMap();
45 } 49 }
46 50
@@ -50,18 +54,85 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf @@ -50,18 +54,85 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
50 try{ 54 try{
51 55
52 ScheduleRealInfo schedule = ScheduleBuffer.pkSchedulMap.get(id); 56 ScheduleRealInfo schedule = ScheduleBuffer.pkSchedulMap.get(id);
  57 + schedule.setDfsjT(sdfMinute.parse(sdfMonth.format(new Date()) + " " + dfsj).getTime());
53 schedule.setDfsj(dfsj); 58 schedule.setDfsj(dfsj);
54 - String newRem = schedule.getRemarks();  
55 - if(null == newRem)  
56 - newRem = "";  
57 - newRem += "[待发调整] " + remarks +";";  
58 - schedule.setRemarks(newRem); 59 + schedule.addRemarks("[待发调整] " + remarks +";");
59 //持久化到数据库 60 //持久化到数据库
60 ScheduleBuffer.persistentList.add(schedule); 61 ScheduleBuffer.persistentList.add(schedule);
61 62
62 map.put("status", ResponseCode.SUCCESS); 63 map.put("status", ResponseCode.SUCCESS);
63 map.put("dfsj", dfsj); 64 map.put("dfsj", dfsj);
64 - map.put("remarks", newRem); 65 + map.put("remarks", schedule.getRemarks());
  66 + }catch(Exception e){
  67 + logger.error("", e);
  68 + map.put("status", ResponseCode.ERROR);
  69 + }
  70 + return map;
  71 + }
  72 +
  73 + @Override
  74 + public Map<String, Object> destroy(String idsStr, int spaceAdjust, String remarks, String reason, int spaceNum) {
  75 +
  76 + Map<String, Object> map = new HashMap<>();
  77 + List<ScheduleRealInfo> rsList = new ArrayList<>();
  78 + map.put("list", rsList);
  79 + try{
  80 + List<String> idList = Lists.newArrayList(Splitter.on(',').trimResults().omitEmptyStrings().split(idsStr));
  81 +
  82 + ScheduleRealInfo schedule = null;
  83 + for(String id : idList){
  84 + schedule = ScheduleBuffer.pkSchedulMap.get(Long.parseLong(id));
  85 + if(null != schedule){
  86 + schedule.setStatus(-1);
  87 + schedule.setRemarks("计划烂班["+reason+"] " + remarks);
  88 +
  89 + rsList.add(schedule);
  90 + }
  91 + }
  92 +
  93 + //调整间隔
  94 + if(spaceAdjust == 1){
  95 +
  96 + ScheduleRealInfo first = ScheduleBuffer.pkSchedulMap.get(Long.parseLong(idList.get(0)));
  97 + String lineCode = first.getXlBm();
  98 + String upDown = first.getXlDir();
  99 +
  100 + List<ScheduleRealInfo> schList = ScheduleBuffer.schedulListMap.get(lineCode)
  101 + ,dirList = new ArrayList<>();
  102 + //筛选走向
  103 + for(ScheduleRealInfo s : schList){
  104 + if(s.getXlDir().equals(upDown)){
  105 + dirList.add(s);
  106 + }
  107 + }
  108 +
  109 + int size = dirList.size();
  110 + Long st = null;
  111 + int diff = spaceNum * 60 * 1000;
  112 + for(int i = 0; i < size; i ++){
  113 + schedule = dirList.get(i);
  114 +
  115 + if(schedule.getId() == first.getId()){
  116 + if(i == 0)
  117 + st = schedule.getDfsjT() - diff;
  118 + else
  119 + st = dirList.get(i - 1).getDfsjT();
  120 + continue;
  121 + }
  122 + if(null == st || schedule.getStatus() == -1)
  123 + continue;
  124 +
  125 + st = st + diff;
  126 + schedule.setDfsjT(st);
  127 + schedule.setDfsj(sdfShort.format(new Date(st)));
  128 +
  129 + ScheduleBuffer.persistentList.add(schedule);
  130 + //将调整的班次返回给页面
  131 + rsList.add(schedule);
  132 + }
  133 + }
  134 +
  135 + map.put("status", ResponseCode.SUCCESS);
65 }catch(Exception e){ 136 }catch(Exception e){
66 logger.error("", e); 137 logger.error("", e);
67 map.put("status", ResponseCode.ERROR); 138 map.put("status", ResponseCode.ERROR);
src/main/java/com/bsth/vehicle/directive/buffer/DirectiveBuffer.java
@@ -67,7 +67,6 @@ public class DirectiveBuffer { @@ -67,7 +67,6 @@ public class DirectiveBuffer {
67 } 67 }
68 68
69 public static void put(Directive directive){ 69 public static void put(Directive directive){
70 - transientList.add(directive);  
71 directiveMap.put(directive.getMsgId(), directive); 70 directiveMap.put(directive.getMsgId(), directive);
72 } 71 }
73 72
src/main/java/com/bsth/vehicle/directive/controller/DirectiveController.java
@@ -29,7 +29,7 @@ public class DirectiveController { @@ -29,7 +29,7 @@ public class DirectiveController {
29 * @Description: TODO(60协议短语下发) 29 * @Description: TODO(60协议短语下发)
30 * @throws 30 * @throws
31 */ 31 */
32 - @RequestMapping(value = "/phrase", method = RequestMethod.GET) 32 + @RequestMapping(value = "/phrase", method = RequestMethod.POST)
33 public int send60Phrase(@RequestParam String nbbm, @RequestParam String text){ 33 public int send60Phrase(@RequestParam String nbbm, @RequestParam String text){
34 return directiveService.send60Phrase(nbbm, text); 34 return directiveService.send60Phrase(nbbm, text);
35 } 35 }
@@ -42,7 +42,7 @@ public class DirectiveController { @@ -42,7 +42,7 @@ public class DirectiveController {
42 * @param @param lineId 新线路编码 42 * @param @param lineId 新线路编码
43 * @throws 43 * @throws
44 */ 44 */
45 - @RequestMapping(value = "/lineChnage", method = RequestMethod.GET) 45 + @RequestMapping(value = "/lineChnage", method = RequestMethod.POST)
46 public int lineChange(@RequestParam String nbbm, @RequestParam Integer lineId){ 46 public int lineChange(@RequestParam String nbbm, @RequestParam Integer lineId){
47 return directiveService.lineChange(nbbm, lineId); 47 return directiveService.lineChange(nbbm, lineId);
48 } 48 }
src/main/java/com/bsth/vehicle/directive/service/DirectiveServiceImpl.java
@@ -46,7 +46,16 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im @@ -46,7 +46,16 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im
46 46
47 @Override 47 @Override
48 public int send60Phrase(String nbbm, String text) { 48 public int send60Phrase(String nbbm, String text) {
49 - Directive directive = create60Data(nbbm, text, DispatchInstruct.PHRASE); 49 + Directive directive = null;
  50 + try {
  51 + directive = create60Data(nbbm, text, DispatchInstruct.PHRASE);
  52 + } catch (Exception e) {
  53 + logger.error("生成调度指令时出现异常", e);
  54 + return -1;
  55 + }
  56 +
  57 + if(null == directive)
  58 + return -1;
50 59
51 //发送指令 60 //发送指令
52 int code = postJson(JSON.toJSONString(directive)); 61 int code = postJson(JSON.toJSONString(directive));
@@ -90,14 +99,14 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im @@ -90,14 +99,14 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im
90 change.setTimestamp(t); 99 change.setTimestamp(t);
91 change.setData(data); 100 change.setData(data);
92 101
93 - int code = 0;//postJson(JSON.toJSONString(change));  
94 - //if(code == 0){ 102 + int code = postJson(JSON.toJSONString(change));
  103 + if(code == 0){
95 //入库 104 //入库
96 lineChangeRepository.save(change); 105 lineChangeRepository.save(change);
97 DirectiveBuffer.changeMap.put(deviceId + '_' + t , change); 106 DirectiveBuffer.changeMap.put(deviceId + '_' + t , change);
98 - //}else{  
99 - // logger.error("send60Phrase error, code: " + code);  
100 - //} 107 + }else{
  108 + logger.error("send60Phrase error, code: " + code);
  109 + }
101 return code; 110 return code;
102 } 111 }
103 112
@@ -105,13 +114,16 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im @@ -105,13 +114,16 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im
105 public Directive create60Data(String nbbm, String text, DispatchInstruct dispatchInstruct){ 114 public Directive create60Data(String nbbm, String text, DispatchInstruct dispatchInstruct){
106 Long timestamp = System.currentTimeMillis(); 115 Long timestamp = System.currentTimeMillis();
107 116
108 - String deviceId = CommonMapped.vehicDeviceBiMap.inverse().get(nbbm); 117 + //向测试设备发送
  118 + String deviceId = "229L4041";
  119 + Short company = 5;
  120 +
  121 + /*String deviceId = CommonMapped.vehicDeviceBiMap.inverse().get(nbbm);
109 Short company = Short.parseShort(CommonMapped.vehicCompanyMap.get(nbbm)); 122 Short company = Short.parseShort(CommonMapped.vehicCompanyMap.get(nbbm));
110 if(null == deviceId){ 123 if(null == deviceId){
111 logger.error("没有设备号对照的车辆:" + nbbm); 124 logger.error("没有设备号对照的车辆:" + nbbm);
112 return null; 125 return null;
113 - }  
114 - 126 + }*/
115 GpsRealData gpsData = gpsRealDataBuffer.findOneByDeviceId(deviceId); 127 GpsRealData gpsData = gpsRealDataBuffer.findOneByDeviceId(deviceId);
116 if(null == gpsData){ 128 if(null == gpsData){
117 logger.error("没有找到gps对照,无法确认营运状态和上下行:" + nbbm); 129 logger.error("没有找到gps对照,无法确认营运状态和上下行:" + nbbm);
@@ -154,6 +166,7 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im @@ -154,6 +166,7 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive, Integer&gt; im
154 int code = -1; 166 int code = -1;
155 try{ 167 try{
156 httpClient = HttpClients.createDefault(); 168 httpClient = HttpClients.createDefault();
  169 +
157 HttpPost post = new HttpPost(Consts.SEND_DIRECTIVE_URL); 170 HttpPost post = new HttpPost(Consts.SEND_DIRECTIVE_URL);
158 171
159 post.setEntity(new StringEntity(jsonStr, "utf-8")); 172 post.setEntity(new StringEntity(jsonStr, "utf-8"));
src/main/java/com/bsth/vehicle/gpsdata/buffer/GpsRealDataBuffer.java
@@ -3,6 +3,7 @@ package com.bsth.vehicle.gpsdata.buffer; @@ -3,6 +3,7 @@ package com.bsth.vehicle.gpsdata.buffer;
3 import java.util.ArrayList; 3 import java.util.ArrayList;
4 import java.util.HashMap; 4 import java.util.HashMap;
5 import java.util.Iterator; 5 import java.util.Iterator;
  6 +import java.util.LinkedList;
6 import java.util.List; 7 import java.util.List;
7 import java.util.Map; 8 import java.util.Map;
8 import java.util.Set; 9 import java.util.Set;
@@ -11,6 +12,8 @@ import org.slf4j.Logger; @@ -11,6 +12,8 @@ import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory; 12 import org.slf4j.LoggerFactory;
12 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
13 14
  15 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  16 +import com.bsth.service.realcontrol.ScheduleBuffer;
14 import com.bsth.vehicle.common.CommonMapped; 17 import com.bsth.vehicle.common.CommonMapped;
15 import com.bsth.vehicle.gpsdata.entity.GpsRealData; 18 import com.bsth.vehicle.gpsdata.entity.GpsRealData;
16 import com.google.common.collect.ArrayListMultimap; 19 import com.google.common.collect.ArrayListMultimap;
@@ -129,11 +132,24 @@ public class GpsRealDataBuffer { @@ -129,11 +132,24 @@ public class GpsRealDataBuffer {
129 132
130 //写入车辆自编号 133 //写入车辆自编号
131 String nbbm; 134 String nbbm;
  135 + LinkedList<ScheduleRealInfo> linkedList;
  136 + int size;
132 for(GpsRealData gpsData : list){ 137 for(GpsRealData gpsData : list){
133 nbbm = CommonMapped.vehicDeviceBiMap.get(gpsData.getDeviceId()); 138 nbbm = CommonMapped.vehicDeviceBiMap.get(gpsData.getDeviceId());
134 if(null != nbbm){ 139 if(null != nbbm){
135 gpsData.setNbbm(nbbm); 140 gpsData.setNbbm(nbbm);
136 gpsData.setStationName(CommonMapped.stationCodeMap.get(gpsData.getStopNo())); 141 gpsData.setStationName(CommonMapped.stationCodeMap.get(gpsData.getStopNo()));
  142 +
  143 +
  144 + linkedList = ScheduleBuffer.vehLinkedMap.get(nbbm);
  145 + if(null != linkedList){
  146 + //为GPS点附加班次信息
  147 + size = linkedList.size();
  148 + if(size > 0)
  149 + gpsData.setCurrSchId(linkedList.peekFirst().getId());
  150 + if(size > 1)
  151 + gpsData.setNextSchId(linkedList.get(1).getId());
  152 + }
137 resList.add(gpsData); 153 resList.add(gpsData);
138 } 154 }
139 } 155 }
src/main/java/com/bsth/vehicle/gpsdata/entity/GpsRealData.java
@@ -51,6 +51,12 @@ public class GpsRealData { @@ -51,6 +51,12 @@ public class GpsRealData {
51 51
52 //站点名称 52 //站点名称
53 private String stationName; 53 private String stationName;
  54 +
  55 + //当前班次ID
  56 + private Long currSchId;
  57 +
  58 + //下一个班次ID
  59 + private Long nextSchId;
54 60
55 public Integer getCompanyCode() { 61 public Integer getCompanyCode() {
56 return companyCode; 62 return companyCode;
@@ -147,6 +153,22 @@ public class GpsRealData { @@ -147,6 +153,22 @@ public class GpsRealData {
147 public void setUpDown(Integer upDown) { 153 public void setUpDown(Integer upDown) {
148 this.upDown = upDown; 154 this.upDown = upDown;
149 } 155 }
  156 +
  157 + public Long getCurrSchId() {
  158 + return currSchId;
  159 + }
  160 +
  161 + public void setCurrSchId(Long currSchId) {
  162 + this.currSchId = currSchId;
  163 + }
  164 +
  165 + public Long getNextSchId() {
  166 + return nextSchId;
  167 + }
  168 +
  169 + public void setNextSchId(Long nextSchId) {
  170 + this.nextSchId = nextSchId;
  171 + }
150 172
151 public String getNbbm() { 173 public String getNbbm() {
152 return nbbm; 174 return nbbm;
src/main/resources/static/pages/control/line/css/lineControl.css
@@ -382,7 +382,7 @@ body{ @@ -382,7 +382,7 @@ body{
382 382
383 /* svg 样式 */ 383 /* svg 样式 */
384 .line_chart svg{ 384 .line_chart svg{
385 - height: calc(100% - 40px); 385 + height: 100% ;
386 margin: 0; 386 margin: 0;
387 z-index: 1; 387 z-index: 1;
388 position: absolute; 388 position: absolute;
@@ -763,7 +763,7 @@ height: 400px; @@ -763,7 +763,7 @@ height: 400px;
763 #top-tabs-wrap .tab-content{ 763 #top-tabs-wrap .tab-content{
764 height: calc(100% - 42px); 764 height: calc(100% - 42px);
765 padding: 3px 1px; 765 padding: 3px 1px;
766 - overflow-y: auto; 766 + /* overflow-y: auto; */
767 } 767 }
768 768
769 #top-tabs-wrap .tab-content .tab-pane{ 769 #top-tabs-wrap .tab-content .tab-pane{
@@ -864,7 +864,7 @@ height: 400px; @@ -864,7 +864,7 @@ height: 400px;
864 width: 9%; 864 width: 9%;
865 } 865 }
866 .pb-table tr td:nth-child(5){ 866 .pb-table tr td:nth-child(5){
867 - /* width: 15%; */ 867 + width: 15%;
868 } 868 }
869 .pb-table tr td:nth-child(6){ 869 .pb-table tr td:nth-child(6){
870 width: 10%; 870 width: 10%;
@@ -958,9 +958,9 @@ height: 400px; @@ -958,9 +958,9 @@ height: 400px;
958 .pic-panel span.tl-zzzx:before{ 958 .pic-panel span.tl-zzzx:before{
959 content: "正在执行"; 959 content: "正在执行";
960 } 960 }
961 -/* .pic-panel span.tl-sf-f:before{ 961 +.pic-panel span.tl-sf-f:before{
962 content: "实发(放)"; 962 content: "实发(放)";
963 -} */ 963 +}
964 .pic-panel span.tl-xxfc:before{ 964 .pic-panel span.tl-xxfc:before{
965 content: "消息发出"; 965 content: "消息发出";
966 } 966 }
@@ -991,8 +991,10 @@ height: 400px; @@ -991,8 +991,10 @@ height: 400px;
991 .tl-zzzx{ 991 .tl-zzzx{
992 background: #96F396; 992 background: #96F396;
993 } 993 }
994 -/* .tl-sf-f{  
995 -} */ 994 +.tl-sf-f{
  995 + background: gray;
  996 + color: white;
  997 +}
996 .tl-xxfc{ 998 .tl-xxfc{
997 background: #AE9CCE; 999 background: #AE9CCE;
998 color: white; 1000 color: white;
@@ -1472,4 +1474,41 @@ height: 400px; @@ -1472,4 +1474,41 @@ height: 400px;
1472 1474
1473 .form-custom hr{ 1475 .form-custom hr{
1474 margin: 15px 0; 1476 margin: 15px 0;
  1477 +}
  1478 +
  1479 +.layui-layer-cfm-delete .layui-layer-btn0{
  1480 + background-color: #e73d4a;
  1481 + border-color: #CE3643;
  1482 +}
  1483 +
  1484 +label.error{
  1485 + display: none !important;
  1486 +}
  1487 +
  1488 +.item .form-control.error{
  1489 + border: 1px solid red;
  1490 +}
  1491 +
  1492 +.up-number{
  1493 + font-family: arial;
  1494 + color: #5e96d2;
  1495 + font-size: 18px;
  1496 + font-weight: 700;
  1497 +}
  1498 +
  1499 +.down-number{
  1500 + font-family: arial;
  1501 + color: #e43a45;
  1502 + font-size: 18px;
  1503 + font-weight: 700;
  1504 +}
  1505 +
  1506 +.empty-table-td{
  1507 + background-color: #fff !important;
  1508 +}
  1509 +
  1510 +.empty-table-td:BEFORE{
  1511 + content: "暂无数据";
  1512 + color: #6f6c6c;
  1513 + font-size: 12px;
1475 } 1514 }
1476 \ No newline at end of file 1515 \ No newline at end of file
src/main/resources/static/pages/control/line/index.html
@@ -151,7 +151,7 @@ @@ -151,7 +151,7 @@
151 </li> 151 </li>
152 <li class="menu-separator"></li> 152 <li class="menu-separator"></li>
153 <li class="menu-item" > 153 <li class="menu-item" >
154 - <button type="button" class="menu-btn"> 154 + <button type="button" class="menu-btn" data-method="directiveRepeat">
155 <i class="fa fa-bell-o"></i> 155 <i class="fa fa-bell-o"></i>
156 <span class="menu-text">指令重发</span> 156 <span class="menu-text">指令重发</span>
157 </button> 157 </button>
@@ -171,9 +171,11 @@ @@ -171,9 +171,11 @@
171 <script src="/pages/control/line/js/alone.js"></script> 171 <script src="/pages/control/line/js/alone.js"></script>
172 <script src="/pages/control/line/js/main.js"></script> 172 <script src="/pages/control/line/js/main.js"></script>
173 <script> 173 <script>
174 -//初始化lineCodes  
175 -var lineCodes = '';  
176 174
  175 +var lineCodes = '' //全部线路编码字符串,由data.js初始化
  176 + , lineMap = {} //编码和线路详细对照,由data.js初始化;
  177 +
  178 +moment.locale('zh-cn');
177 $(function() { 179 $(function() {
178 //加载模板文件 180 //加载模板文件
179 getTemp('temps/home_tp.html'); 181 getTemp('temps/home_tp.html');
src/main/resources/static/pages/control/line/js/alone.js
@@ -8,25 +8,34 @@ var _alone = (function(){ @@ -8,25 +8,34 @@ var _alone = (function(){
8 ,downCode = '下行'; 8 ,downCode = '下行';
9 9
10 var aloneObject = { 10 var aloneObject = {
11 - init: function(){ 11 + init: function(cb){
12 _data.queryRealSchedule(lineCodes, function(schList){ 12 _data.queryRealSchedule(lineCodes, function(schList){
13 - for(var lineCode in schList){  
14 - //按上下行拆分数据  
15 - var rs = splitDir(schList[lineCode])  
16 - ,htmlStr = template('alone_main_temp', {up: rs.up, down: rs.down});  
17 -  
18 - $('#tab_line_' + lineCode).append(htmlStr).find('._body')  
19 - //滚动条  
20 - .slimscroll({  
21 - height: 'calc(100% - 80px)',  
22 - alwaysVisible: true  
23 - }); 13 +
  14 + var schTempList;
  15 + for(var lineCode in lineMap){
  16 + schTempList = schList[lineCode];
  17 + tab = $('#tab_line_' + lineCode);
  18 + tab.append(template('alone_main_temp', lineMap[lineCode]));
24 19
25 - //底部svg  
26 - _data.queryStationRoute(lineCode , 'lineSvg' + lineCode , drawSvg.init); 20 + //有排班数据
  21 + if(schTempList){
  22 + var rs = splitDir(schTempList);
  23 + //填充表格数据
  24 + calculateLineNo(
  25 + tab.find('table[data-type=up] tbody').html(template('alone_plan_table_temp', {list: rs.up}))[0]
  26 + );
  27 + calculateLineNo(
  28 + tab.find('table[data-type=down] tbody').html(template('alone_plan_table_temp', {list: rs.down}))[0]
  29 + );
  30 +
  31 + //滚动条
  32 + tab.find('._body').slimscroll({
  33 + height: 'calc(100% - 80px)',
  34 + alwaysVisible: true
  35 + });
  36 + }
  37 + _data.queryStationRoute(lineCode , 'lineSvg' + lineCode , drawSvg.initAloneSvg);
27 } 38 }
28 - //绑定右键菜单事件  
29 - _menu.bindClickMenu();  
30 39
31 $('.console-log .log-item-list').slimscroll({ 40 $('.console-log .log-item-list').slimscroll({
32 height: '100%' 41 height: '100%'
@@ -40,36 +49,31 @@ var _alone = (function(){ @@ -40,36 +49,31 @@ var _alone = (function(){
40 container: '.portlet-fullscreen' 49 container: '.portlet-fullscreen'
41 }); 50 });
42 51
43 - //备注POPOVER  
44 - $('.remarks-popover').popover({trigger: 'hover',container: '.portlet-fullscreen',placement:'bottom'}); 52 + initRemarksPop();
  53 +
  54 + cb && cb();
45 }); 55 });
46 -  
47 - //$('.tab-pane.aloneline')  
48 - /*_data.queryStationRoute('10904' , 'lineSvg10904' , drawSvg.init);  
49 - */  
50 }, 56 },
51 //刷新班次 57 //刷新班次
52 refreshSchedule: function(schedule){ 58 refreshSchedule: function(schedule){
53 //xlBm 59 //xlBm
54 - var tr = $('tr[data-id='+schedule.id+']', '#tab_line_' + schedule.xlBm)[0]  
55 - ,cells = tr.cells, name; 60 + var $tr = $('tr[data-id='+schedule.id+']', '#tab_line_' + schedule.xlBm)
  61 + ,newTr = template('alone_plan_table_temp', {list: [schedule]});
56 62
57 - $.each(cells, function(i, cell){  
58 - name = $(cell).data('name');  
59 - if(name == 'remarks'){  
60 - var link = $(cell).find('a');  
61 - if(link.length == 0){  
62 - $(cell).append('<a class="remarks-popover" href="javascript:;" data-toggle="popover" data-content="'+schedule[name]+'" >备注</a>')  
63 - }  
64 - else{  
65 - link.attr('data-content', schedule[name]);  
66 - }  
67 - }  
68 - else{  
69 - $(cell).text(schedule[name]);  
70 - }  
71 - });  
72 - } 63 + $tr.replaceWith(newTr);
  64 + initRemarksPop();
  65 + },
  66 + //重新计算行号
  67 + calculateLineNo: calculateLineNo
  68 + }
  69 +
  70 + //计算行号
  71 + function calculateLineNo(table){
  72 + var rows = table.rows;
  73 + $.each(rows,function(i, r){
  74 + var cells = r.cells;
  75 + $(cells[0]).text(i + 1);
  76 + });
73 } 77 }
74 78
75 function splitDir(list){ 79 function splitDir(list){
@@ -84,5 +88,9 @@ var _alone = (function(){ @@ -84,5 +88,9 @@ var _alone = (function(){
84 return rs; 88 return rs;
85 } 89 }
86 90
  91 + function initRemarksPop(){
  92 + //备注POPOVER
  93 + $('.remarks-popover', '.pb-table').popover({trigger: 'hover',container: '.portlet-fullscreen',placement:'bottom'});
  94 + }
87 return aloneObject; 95 return aloneObject;
88 })(); 96 })();
89 \ No newline at end of file 97 \ No newline at end of file
src/main/resources/static/pages/control/line/js/data.js
@@ -24,41 +24,24 @@ var _data = (function(){ @@ -24,41 +24,24 @@ var _data = (function(){
24 getLineIds: function(){ 24 getLineIds: function(){
25 return JSON.parse(storage.getItem('lineIds')); 25 return JSON.parse(storage.getItem('lineIds'));
26 }, 26 },
27 - getRealVehic: function(lineArray, cb){  
28 - var tabList = [  
29 - {nbbm: 'W9H108', endDistance: '13.14', endTime: '82', instructions: '', speed: '16', roadSigns: '另1'},  
30 - {nbbm: 'W9H108', endDistance: '13.14', endTime: '82', instructions: '', speed: '16', roadSigns: '另1'},  
31 - {nbbm: 'W9H108', endDistance: '13.14', endTime: '82', instructions: '', speed: '16', roadSigns: '另1'},  
32 - {nbbm: 'W9H108', endDistance: '13.14', endTime: '82', instructions: '', speed: '16', roadSigns: '另1'},  
33 - {nbbm: 'W9H108', endDistance: '13.14', endTime: '82', instructions: '', speed: '16', roadSigns: '另1'},  
34 - {nbbm: 'W9H108', endDistance: '13.14', endTime: '82', instructions: '', speed: '16', roadSigns: '另1'}  
35 - ];  
36 - var d = {  
37 - '10232_0': tabList,  
38 - '10232_1': tabList,  
39 - '10566_0': tabList,  
40 - '10566_1': tabList,  
41 - '10904_0': tabList,  
42 - '10904_1': tabList,  
43 - '10069_0': tabList,  
44 - '10069_1': tabList,  
45 - '10474_0': tabList,  
46 - '10474_1': tabList,  
47 - '10507_0': tabList,  
48 - '10507_1': tabList,  
49 - '10702_0': tabList,  
50 - '10702_1': tabList,  
51 - '10220_0': tabList,  
52 - '10220_1': tabList  
53 - };  
54 - cb && cb(d); 27 + //为GPS点附加班次信息
  28 + attachSchedulInfo: function(gpsArray){
  29 + $.each(gpsArray, function(){
  30 + gps = this;
  31 + if(gps.currSchId)
  32 + gps.currSch = schedules[gps.currSchId];
  33 + if(gps.nextSchId)
  34 + gps.nextSch = schedules[gps.nextSchId];
  35 +
  36 + });
  37 +
  38 + return gpsArray;
55 } 39 }
56 //查询站点路由 40 //查询站点路由
57 - ,queryStationRoute : function(lineId,container, cb){ 41 + ,queryStationRoute : function(lineId,container, cb, width){
58 $get('/stationroute/all', {'line.lineCode_eq': lineId}, function(routes){ 42 $get('/stationroute/all', {'line.lineCode_eq': lineId}, function(routes){
59 var svgData = analyData(routes); 43 var svgData = analyData(routes);
60 -  
61 - cb && cb(lineId, svgData, container); 44 + cb && cb(lineId, svgData, container, width);
62 }); 45 });
63 }, 46 },
64 //实时GPS定时刷新 47 //实时GPS定时刷新
@@ -116,6 +99,7 @@ var _data = (function(){ @@ -116,6 +99,7 @@ var _data = (function(){
116 //初始化lineCodes 99 //初始化lineCodes
117 $.each(dataObject.getLines(), function(i, obj){ 100 $.each(dataObject.getLines(), function(i, obj){
118 lineCodes += (obj.lineCode + ','); 101 lineCodes += (obj.lineCode + ',');
  102 + lineMap[obj.lineCode] = obj;
119 }); 103 });
120 lineCodes = lineCodes.substr(0, lineCodes.length - 1); 104 lineCodes = lineCodes.substr(0, lineCodes.length - 1);
121 105
@@ -130,11 +114,11 @@ var _data = (function(){ @@ -130,11 +114,11 @@ var _data = (function(){
130 }); 114 });
131 } 115 }
132 var upSort = function(a, b){ 116 var upSort = function(a, b){
133 - return a.outStationNmber - b.outStationNmber; 117 + return a.stationRouteCode - b.stationRouteCode;
134 } 118 }
135 119
136 var downSort = function(a, b){ 120 var downSort = function(a, b){
137 - return b.outStationNmber - a.outStationNmber; 121 + return b.stationRouteCode - a.stationRouteCode;
138 } 122 }
139 123
140 var station_indexof = function(array, station , start){ 124 var station_indexof = function(array, station , start){
src/main/resources/static/pages/control/line/js/drawSvg.js
@@ -8,7 +8,8 @@ var drawSvg = (function(){ @@ -8,7 +8,8 @@ var drawSvg = (function(){
8 ,p = 112//上下行之间的间隔 132 8 ,p = 112//上下行之间的间隔 132
9 ,x = d3.scale.linear() 9 ,x = d3.scale.linear()
10 ,w 10 ,w
11 - ,lineSvgMapp = {} 11 + ,homeSvgMapp = {}
  12 + ,aloneSvgMapp = {}
12 ,lineStations = {} 13 ,lineStations = {}
13 ,seGps = {} //起终点gps信号; 14 ,seGps = {} //起终点gps信号;
14 15
@@ -41,28 +42,39 @@ var drawSvg = (function(){ @@ -41,28 +42,39 @@ var drawSvg = (function(){
41 var cutNbbm = function(nbbm){ 42 var cutNbbm = function(nbbm){
42 return nbbm.substr(nbbm.length - 3, nbbm.length); 43 return nbbm.substr(nbbm.length - 3, nbbm.length);
43 } 44 }
44 - 45 +
45 var drawSvgObject = { 46 var drawSvgObject = {
46 - init: function(lineId, data, container){ 47 + initHomeSvg: function(lineId, data, container){
  48 + var w = $('.line_chart:first').width(),
  49 + svg = drawSvgObject.init(lineId, data, container, w, 80);
  50 + //线路编码 和 首页SVG对照
  51 + homeSvgMapp[lineId] = svg;
  52 + },
  53 + initAloneSvg: function(lineId, data, container){
  54 + var w = $(document).width(),
  55 + svg = drawSvgObject.init(lineId, data, container,w , 44);
  56 + //线路编码 和 单线路SVG对照
  57 + aloneSvgMapp[lineId] = svg;
  58 + },
  59 + init: function(lineId, data, container, w, mtop){
47 if(!data || data.length == 0) 60 if(!data || data.length == 0)
48 return; 61 return;
49 62
  63 + mt = mtop;
50 //起终点站 64 //起终点站
51 $.each(data, function(){ 65 $.each(data, function(){
52 if(this.stationMark == 'B' || this.stationMark == 'E' ) 66 if(this.stationMark == 'B' || this.stationMark == 'E' )
53 seGps[lineId + '_' + this.id[0]] = []; 67 seGps[lineId + '_' + this.id[0]] = [];
54 }); 68 });
55 69
56 - //w = $('.line_chart:first').width();  
57 - w = $('#' + container).width();  
58 var svg = d3.select('#' + container).append('svg') 70 var svg = d3.select('#' + container).append('svg')
59 .attr('width', w).attr('opacity', 0) 71 .attr('width', w).attr('opacity', 0)
60 .attr('id', lineId); 72 .attr('id', lineId);
61 73
62 - lineSvgMapp[lineId] = svg; 74 +
63 lineStations[lineId] = data.slice(0); 75 lineStations[lineId] = data.slice(0);
64 //抽站 76 //抽站
65 - cleanStation(data); 77 + cleanStation(w, data);
66 var dLen = data.length; 78 var dLen = data.length;
67 79
68 x.range([ 60 , w - 15]).domain([ 0, dLen]); 80 x.range([ 60 , w - 15]).domain([ 0, dLen]);
@@ -153,63 +165,15 @@ var drawSvg = (function(){ @@ -153,63 +165,15 @@ var drawSvg = (function(){
153 return $(this).attr('class')?null:this; 165 return $(this).attr('class')?null:this;
154 }).remove(); 166 }).remove();
155 167
  168 + return svg;
156 }, 169 },
157 170
158 //画出GPS点 171 //画出GPS点
159 drawVehicle: function(gpsArray){ 172 drawVehicle: function(gpsArray){
160 173
161 for(var i = 0, gps; gps = gpsArray[i ++];){ 174 for(var i = 0, gps; gps = gpsArray[i ++];){
162 - var svg = lineSvgMapp[gps.lineId]  
163 - ,stionId = gps.lineId + '_' + gps.stopNo  
164 - ,station = $('#' + stionId)  
165 - ,c = station.attr('class')||""  
166 - ,start = c.indexOf('start') != -1  
167 - ,end = c.indexOf('end') != -1;  
168 -  
169 - if(station.length == 0)  
170 - continue;  
171 -  
172 - //起终点站GPS信号  
173 - if(seGps[stionId]){  
174 - seGps[stionId].push(gps);  
175 - continue;  
176 - }  
177 -  
178 - var cx = parseInt(station.attr('cx'))  
179 - ,cy = parseInt(station.attr('cy'))  
180 - ,updown = station.attr('updown')  
181 - ,gpsGWrap = svg.select('.gps-g-wrap')  
182 - ,gpscont;  
183 -  
184 - if($('g[for='+stionId+']').length == 0){  
185 - gpscont = gpsGWrap.append('g')  
186 - .attr('class', 'station-gps-container')  
187 - .attr('updown', updown)  
188 - .attr('for', stionId);  
189 - }else{  
190 - gpscont = gpsGWrap.selectAll('g')  
191 - .select(function(){return $(this).attr('for') == stionId?this:null})  
192 - .classed({'multiple': true});  
193 - }  
194 - var vg = gpscont.selectAll('g[deviceId="'+gps.deviceId+'"]')  
195 - .data([gps]).enter().append('g')  
196 - .attr('deviceId', gps.deviceId)  
197 - .attr('class', 'vehci-g ' + (updown==0?'up':'down'))  
198 - .attr('station', gps.stopNo);  
199 -  
200 - //上下行异常  
201 - /*if(!start && !end && updown != gps.upDown){  
202 - vg.classed({'updown-error': true});  
203 - }*/  
204 -  
205 - vg.append('text')  
206 - .attr('x', cx + 4).attr('y', cy + 17)  
207 - .text(cutNbbm(gps.nbbm));  
208 -  
209 - var rect = vg.append('rect').attr('x', cx).attr('y', cy);  
210 -  
211 - //tooltip  
212 - _tooltip.initGpsTip(vg); 175 + //drawGpsToSvg(gps, aloneSvgMapp[gps.lineId]);
  176 + drawGpsToSvg(gps, homeSvgMapp[gps.lineId]);
213 } 177 }
214 178
215 //画出起终点GPS信号 179 //画出起终点GPS信号
@@ -221,7 +185,7 @@ var drawSvg = (function(){ @@ -221,7 +185,7 @@ var drawSvg = (function(){
221 ,x = parseInt(e.attr('cx')) 185 ,x = parseInt(e.attr('cx'))
222 ,y = parseInt(e.attr('cy')); 186 ,y = parseInt(e.attr('cy'));
223 187
224 - var svg = lineSvgMapp[seGps[eid][0].lineId]; 188 + var svg = homeSvgMapp[seGps[eid][0].lineId];
225 189
226 var gs = svg.append('g').classed({'start': e.attr('class').indexOf('start') != -1, 'park': true}) 190 var gs = svg.append('g').classed({'start': e.attr('class').indexOf('start') != -1, 'park': true})
227 .selectAll('g').data(seGps[eid]).enter().append('g'); 191 .selectAll('g').data(seGps[eid]).enter().append('g');
@@ -240,12 +204,14 @@ var drawSvg = (function(){ @@ -240,12 +204,14 @@ var drawSvg = (function(){
240 return y + i * 27 + 17; 204 return y + i * 27 + 17;
241 }) 205 })
242 .text(function(d){return cutNbbm(d.nbbm)}); 206 .text(function(d){return cutNbbm(d.nbbm)});
  207 +
  208 + _tooltip.initStartAndEndGPS(gs);
243 } 209 }
244 } 210 }
245 211
246 /** 212 /**
247 * 堆叠多个GPS信号 213 * 堆叠多个GPS信号
248 - 214 + */
249 $.each($('.station-gps-container'), function(i, multiGps){ 215 $.each($('.station-gps-container'), function(i, multiGps){
250 var tArray = $(multiGps).find('g') 216 var tArray = $(multiGps).find('g')
251 ,updowm = $(multiGps).attr('updown') 217 ,updowm = $(multiGps).attr('updown')
@@ -268,7 +234,7 @@ var drawSvg = (function(){ @@ -268,7 +234,7 @@ var drawSvg = (function(){
268 234
269 $(tArray[1]).css('transform', 'translate(-15px, '+ translateY +'px)'); 235 $(tArray[1]).css('transform', 'translate(-15px, '+ translateY +'px)');
270 } 236 }
271 - }); */ 237 + });
272 238
273 /* function drawNumber(multiGps, num, that, start, end){ 239 /* function drawNumber(multiGps, num, that, start, end){
274 var circle = $('#' + $(multiGps).attr('for')) 240 var circle = $('#' + $(multiGps).attr('for'))
@@ -289,6 +255,59 @@ var drawSvg = (function(){ @@ -289,6 +255,59 @@ var drawSvg = (function(){
289 } 255 }
290 }; 256 };
291 257
  258 + function drawGpsToSvg(gps, svg){
  259 + var stionId = gps.lineId + '_' + gps.stopNo
  260 + ,station = $('#' + stionId)
  261 + ,c = station.attr('class')||""
  262 + ,start = c.indexOf('start') != -1
  263 + ,end = c.indexOf('end') != -1;
  264 +
  265 + if(station.length == 0)
  266 + return;
  267 +
  268 + //起终点站GPS信号
  269 + if(seGps[stionId]){
  270 + seGps[stionId].push(gps);
  271 + return;
  272 + }
  273 +
  274 + var cx = parseInt(station.attr('cx'))
  275 + ,cy = parseInt(station.attr('cy'))
  276 + ,updown = station.attr('updown')
  277 + ,gpsGWrap = svg.select('.gps-g-wrap')
  278 + ,gpscont;
  279 +
  280 + if($('g[for='+stionId+']').length == 0){
  281 + gpscont = gpsGWrap.append('g')
  282 + .attr('class', 'station-gps-container')
  283 + .attr('updown', updown)
  284 + .attr('for', stionId);
  285 + }else{
  286 + gpscont = gpsGWrap.selectAll('g')
  287 + .select(function(){return $(this).attr('for') == stionId?this:null})
  288 + .classed({'multiple': true});
  289 + }
  290 + var vg = gpscont.selectAll('g[deviceId="'+gps.deviceId+'"]')
  291 + .data([gps]).enter().append('g')
  292 + .attr('deviceId', gps.deviceId)
  293 + .attr('class', 'vehci-g ' + (updown==0?'up':'down'))
  294 + .attr('station', gps.stopNo);
  295 +
  296 + //上下行异常
  297 + /*if(!start && !end && updown != gps.upDown){
  298 + vg.classed({'updown-error': true});
  299 + }*/
  300 +
  301 + vg.append('text')
  302 + .attr('x', cx + 4).attr('y', cy + 17)
  303 + .text(cutNbbm(gps.nbbm));
  304 +
  305 + var rect = vg.append('rect').attr('x', cx).attr('y', cy);
  306 +
  307 + //tooltip
  308 + _tooltip.initGpsTip(vg);
  309 + }
  310 +
292 function drawPath(svg, data,updown, noclear){ 311 function drawPath(svg, data,updown, noclear){
293 svg.append('g').selectAll('path') 312 svg.append('g').selectAll('path')
294 .data(data.slice(0, data.length - 1)).enter().append('path') 313 .data(data.slice(0, data.length - 1)).enter().append('path')
@@ -330,8 +349,8 @@ var drawSvg = (function(){ @@ -330,8 +349,8 @@ var drawSvg = (function(){
330 }); 349 });
331 } 350 }
332 351
333 - function cleanStation(data){  
334 - var ms = w / 52 352 + function cleanStation(w,data){
  353 + var ms = w / 45
335 ,dLen = data.length; 354 ,dLen = data.length;
336 if(ms < dLen){ 355 if(ms < dLen){
337 var end; 356 var end;
src/main/resources/static/pages/control/line/js/main.js
@@ -26,24 +26,16 @@ @@ -26,24 +26,16 @@
26 26
27 $('#tab_home').html(homeHtmlStr); 27 $('#tab_home').html(homeHtmlStr);
28 28
29 - //车辆信息  
30 - _data.getRealVehic(lineArray, function(d){  
31 - for(var n in d){  
32 - var htmlStr = template('home_table_temp', {list: d[n]});  
33 - $('#tab_' + n).find('tbody').html(htmlStr);  
34 - }  
35 -  
36 - //滚动条  
37 - $('.card_wrap .table_wrap').slimscroll({  
38 - height: '187px',  
39 - alwaysVisible: true,  
40 - opacity: .8  
41 - }); 29 + //滚动条
  30 + $('.card_wrap .table_wrap').slimscroll({
  31 + height: '187px',
  32 + alwaysVisible: true,
  33 + opacity: .8
42 }); 34 });
43 35
44 - //svg线路图 36 + //SVG线路图
45 $.each(lineArray, function(i, obj){ 37 $.each(lineArray, function(i, obj){
46 - _data.queryStationRoute( obj.lineCode, 'line_chart_' + obj.lineCode , drawSvg.init); 38 + _data.queryStationRoute( obj.lineCode, 'line_chart_' + obj.lineCode , drawSvg.initHomeSvg);
47 }); 39 });
48 40
49 $('.line_chart .top .top-remark').slimscroll({ 41 $('.line_chart .top .top-remark').slimscroll({
@@ -52,11 +44,24 @@ @@ -52,11 +44,24 @@
52 44
53 //模拟图GPS刷新事件 45 //模拟图GPS刷新事件
54 $('#tab_home').on('gps_refresh', function(e, add, up){ 46 $('#tab_home').on('gps_refresh', function(e, add, up){
55 - drawSvg.drawVehicle(add); 47 + //附加班次信息
  48 + addList = _data.attachSchedulInfo(add);
  49 + drawSvg.drawVehicle(addList);
  50 +
  51 + //按线路分组
  52 + var listMap = groupByLine(addList);
  53 + for(var key in listMap){
  54 + var htmlStr = template('home_table_temp', {list: listMap[key]});
  55 + $('#tab_' + key).find('tbody').html(htmlStr);
  56 + //更新badge
  57 + $('#'+key+'_badge').text('( ' + listMap[key].length + ' )');
  58 + }
56 }); 59 });
57 60
58 - //定时刷新GPS  
59 - _data.startRefreshGpsTimer(); 61 +
  62 + setTimeout(function(){
  63 + _data.startRefreshGpsTimer();
  64 + }, 300);
60 /* setTimeout(function(){ 65 /* setTimeout(function(){
61 homeObject.refreshGps(function(add, update){ 66 homeObject.refreshGps(function(add, update){
62 //将新增的点画到模拟图上 67 //将新增的点画到模拟图上
@@ -80,14 +85,14 @@ setTimeout(function(){ @@ -80,14 +85,14 @@ setTimeout(function(){
80 $('#top-tabs-wrap .nav-tabs').append(topTabs); 85 $('#top-tabs-wrap .nav-tabs').append(topTabs);
81 $('#top-tabs-wrap .tab-content').append(tabPanels); 86 $('#top-tabs-wrap .tab-content').append(tabPanels);
82 87
83 - //初始化主页  
84 - homeObject.init();  
85 -  
86 //加载地图页数据 88 //加载地图页数据
87 $('#tab_map').load('/pages/mapmonitor/real/real.html'); 89 $('#tab_map').load('/pages/mapmonitor/real/real.html');
88 90
89 //初始化单线路调度页面 91 //初始化单线路调度页面
90 - _alone.init(); 92 + _alone.init(function(){
  93 + //初始化主页
  94 + homeObject.init();
  95 + });
91 96
92 }, 200) 97 }, 200)
93 98
@@ -99,4 +104,16 @@ setTimeout(function(){ @@ -99,4 +104,16 @@ setTimeout(function(){
99 } 104 }
100 return map; 105 return map;
101 } 106 }
  107 +
  108 + function groupByLine(gpsArray){
  109 + var rs = {}, gps;
  110 + $.each(gpsArray, function(){
  111 + key = this.lineId + '_' + this.upDown;
  112 + if(!rs[key])
  113 + rs[key] = [];
  114 +
  115 + rs[key].push(this);
  116 + });
  117 + return rs;
  118 + }
102 }(); 119 }();
103 \ No newline at end of file 120 \ No newline at end of file
src/main/resources/static/pages/control/line/js/rightMenu.js
@@ -18,29 +18,29 @@ var _menu = (function() { @@ -18,29 +18,29 @@ var _menu = (function() {
18 menuObject[method](schedul); 18 menuObject[method](schedul);
19 }); 19 });
20 20
21 - var menuObject = {  
22 - bindClickMenu : function() {  
23 - var ac = 'active-menu';  
24 - // 表格右键呼出菜单  
25 - $('.pb-table.data tr td[name!=lineNo]').on('contextmenu',  
26 - function(e) {  
27 - e.preventDefault();  
28 - $('.pb-table tr td.' + ac).removeClass(ac);  
29 - var item = $(this);  
30 - item.addClass(ac);  
31 -  
32 - showMenu(e.pageX, e.pageY + 3);  
33 - $(document).one('click', function() {  
34 - $('#rightMenu').removeClass('show-menu');  
35 - item.removeClass(ac);  
36 - });  
37 - })  
38 - // 点击选中  
39 - .on('click', function() { 21 + // 表格右键呼出菜单
  22 + var ac = 'active-menu'
  23 + ,items = '.pb-table.data tr td[name!=lineNo]';
  24 + $('.portlet-fullscreen').on('contextmenu', items,
  25 + function(e) {
  26 + e.preventDefault();
40 $('.pb-table tr td.' + ac).removeClass(ac); 27 $('.pb-table tr td.' + ac).removeClass(ac);
41 - $(this).addClass(ac);  
42 - });  
43 - }, 28 + var item = $(this);
  29 + item.addClass(ac);
  30 +
  31 + showMenu(e.pageX, e.pageY + 3);
  32 + $(document).one('click', function() {
  33 + $('#rightMenu').removeClass('show-menu');
  34 + item.removeClass(ac);
  35 + });
  36 + })
  37 + // 点击选中
  38 + .on('click',items, function() {
  39 + $('.pb-table tr td.' + ac).removeClass(ac);
  40 + $(this).addClass(ac);
  41 + });
  42 +
  43 + var menuObject = {
44 //待发调整 44 //待发调整
45 outgoAdjust: function(schedul){ 45 outgoAdjust: function(schedul){
46 var index = layer.open({ 46 var index = layer.open({
@@ -68,9 +68,9 @@ var _menu = (function() { @@ -68,9 +68,9 @@ var _menu = (function() {
68 //计划烂班 68 //计划烂班
69 planDestroy: function(schedul){ 69 planDestroy: function(schedul){
70 var data = {item: schedul, array : _data.getSchedulByVeh(schedul.clZbh)} 70 var data = {item: schedul, array : _data.getSchedulByVeh(schedul.clZbh)}
71 - layer.open({ 71 + var index = layer.open({
72 type: 1, 72 type: 1,
73 - area: ['370px', '605px'], 73 + area: ['370px', '645px'],
74 maxmin: true, 74 maxmin: true,
75 skin:'layui-layer-molv', 75 skin:'layui-layer-molv',
76 content: template('plan_destroy_body_temp', data), 76 content: template('plan_destroy_body_temp', data),
@@ -78,10 +78,17 @@ var _menu = (function() { @@ -78,10 +78,17 @@ var _menu = (function() {
78 title: '计划烂班设置', 78 title: '计划烂班设置',
79 success: function(){ 79 success: function(){
80 var f = $('#planDestroyForm'); 80 var f = $('#planDestroyForm');
  81 + //红色
81 $('.icheck', f).iCheck({ 82 $('.icheck', f).iCheck({
82 checkboxClass: 'icheckbox_square-red', 83 checkboxClass: 'icheckbox_square-red',
83 increaseArea: '20%' 84 increaseArea: '20%'
84 }); 85 });
  86 + //蓝色
  87 + $('.icheck-blue', f).iCheck({
  88 + checkboxClass: 'icheckbox_minimal-blue',
  89 + increaseArea: '20%'
  90 + });
  91 + $('[data-toggle="tooltip"]', f).tooltip();
85 //滚动到选中项 92 //滚动到选中项
86 var cont = $('.custom-check-box', f) 93 var cont = $('.custom-check-box', f)
87 ,checked = $('.icheck:checked', f); 94 ,checked = $('.icheck:checked', f);
@@ -91,13 +98,51 @@ var _menu = (function() { @@ -91,13 +98,51 @@ var _menu = (function() {
91 }, 500); 98 }, 500);
92 } 99 }
93 //确定 100 //确定
94 - $('button.confirm', f).one('click', function(){  
95 - var params = f.serializeJSON()  
96 - ,text = '确定烂掉部分班次?,';  
97 - $.each(params.ids, function(i, id){  
98 - var s = _data.getSchedulById(id);  
99 - text += (s.)  
100 - }); 101 + $('button.confirm', f).on('click', function(){
  102 + f.submit();
  103 + });
  104 +
  105 + f.validate({
  106 + submitHandler : function(){
  107 + var params = f.serializeJSON()
  108 + ,text = '确定烂掉部分班次['+schedul.clZbh+']&nbsp;&nbsp;'
  109 + ,idsStr = '';
  110 +
  111 + $.each(params.ids, function(i, id){
  112 + var s = _data.getSchedulById(id);
  113 + text += (s.fcsj + ', ');
  114 + idsStr += (id + ',');
  115 + });
  116 + text = text.substr(0, text.length - 2);
  117 + if(params.spaceAdjust == 1){
  118 + text += '<br>并自动调整后续班次间隔 <span class="font-red">'+params.spaceNum+'</span>分钟'
  119 + }
  120 + layer.close(index);
  121 + //弹出确认框
  122 + index = layer.confirm(text, {
  123 + btn : [ '确定烂班' , '取消' ],
  124 + icon : 3,
  125 + shift: 5,
  126 + skin : 'layui-layer-cfm-delete'
  127 + }, function(){
  128 + params.idsStr = idsStr;
  129 + $post('/realSchedule/destroy', params, function(rs){
  130 + layer.close(index);
  131 + $.each(rs.list, function(){
  132 + var old = _data.getSchedulById(this.id);
  133 + old.dfsj = this.dfsj;
  134 + old.dfsjT = this.dfsjT;
  135 + old.remarks = this.remarks;
  136 + old.status = this.status;
  137 + _alone.refreshSchedule(old);
  138 + });
  139 + layer.msg('调整间隔成功!');
  140 + console.log($('tr[data-id='+schedul.id+']').parents('table')[0]);
  141 + _alone.calculateLineNo($('tr[data-id='+schedul.id+']').parents('table')[0]);
  142 + });
  143 + });
  144 + return false;
  145 + }
101 }); 146 });
102 } 147 }
103 }); 148 });
@@ -163,6 +208,27 @@ var _menu = (function() { @@ -163,6 +208,27 @@ var _menu = (function() {
163 } 208 }
164 }); 209 });
165 }); 210 });
  211 + },
  212 + //指令重发
  213 + directiveRepeat: function(schedul){
  214 + var text = '[路牌: '+schedul.lpName+' 计划时间:'+schedul.fcsj+' 待发时间:'+schedul.dfsj+']';
  215 + var index = layer.confirm(schedul.clZbh + '重发调度指令? ' + text, {
  216 + btn : [ '是' , '否' ],
  217 + icon : 3,
  218 + shift: 5
  219 + }, function(){
  220 + //走短语下发
  221 + layer.close(index);
  222 + layer.msg('正在下发指令', {icon: 16});
  223 + $.post('/directive/phrase', {nbbm: schedul.clZbh, text: text},
  224 + function(code){
  225 + if(code == 0){
  226 + layer.msg('发送成功');
  227 + }
  228 + else
  229 + layer.alert('发送调度指令失败', {icon: 2, title: '操作失败'});
  230 + });
  231 + });
166 } 232 }
167 } 233 }
168 234
src/main/resources/static/pages/control/line/js/tooltip.js
@@ -12,7 +12,6 @@ var _tooltip = (function(){ @@ -12,7 +12,6 @@ var _tooltip = (function(){
12 12
13 var position = {}; 13 var position = {};
14 var lastDom; 14 var lastDom;
15 - //toolTip hover  
16 tip.hover(function() { 15 tip.hover(function() {
17 clearTime(); 16 clearTime();
18 $(this).addClass('hover'); 17 $(this).addClass('hover');
@@ -55,18 +54,24 @@ var _tooltip = (function(){ @@ -55,18 +54,24 @@ var _tooltip = (function(){
55 .addClass('tooltip-modal'); 54 .addClass('tooltip-modal');
56 } 55 }
57 56
  57 + var lineIds;
  58 + setTimeout(function(){
  59 + lineIds = _data.getLineIds();
  60 + }, 1000);
  61 +
58 var tooltipObject = { 62 var tooltipObject = {
59 //正常 GPS toolTip 63 //正常 GPS toolTip
60 initGpsTip: function(e){ 64 initGpsTip: function(e){
61 - var lineIds = _data.getLineIds();  
62 -  
63 e.on('mouseover', function(d){ 65 e.on('mouseover', function(d){
64 clearTime(); 66 clearTime();
65 var offset = $(this).offset() 67 var offset = $(this).offset()
66 ,y = $(this).attr('y'); 68 ,y = $(this).attr('y');
67 69
  70 + //获取线路名称
68 if(!d.lineName) 71 if(!d.lineName)
69 d.lineName = lineIds[d.lineId]; 72 d.lineName = lineIds[d.lineId];
  73 +
  74 + d.fromNow = moment(d.timestamp).fromNow();
70 var html = template('tooltip_gps_temp', d); 75 var html = template('tooltip_gps_temp', d);
71 showTip({ 76 showTip({
72 top: offset.top - 45, 77 top: offset.top - 45,
@@ -74,25 +79,55 @@ var _tooltip = (function(){ @@ -74,25 +79,55 @@ var _tooltip = (function(){
74 container: html 79 container: html
75 }); 80 });
76 }) 81 })
77 - .on('mouseout', function(){  
78 - et = setTimeout(function(){  
79 - if(tip.hasClass('fixed'))  
80 - return;  
81 - if(tip.hasClass('hover'))  
82 - return;  
83 -  
84 - tip.hide();  
85 - },300);  
86 - }); 82 + .on('mouseout', hideTip);
  83 + },
  84 + //首末站GPS
  85 + initStartAndEndGPS: function(e){
  86 + e.on('mouseover', function(d){
  87 + clearTime();
  88 + var offset = $(this).offset()
  89 + ,y = $(this).attr('y');
  90 +
  91 + //获取线路名称
  92 + if(!d.lineName)
  93 + d.lineName = lineIds[d.lineId];
  94 +
  95 + d.fromNow = moment(d.timestamp).fromNow();
  96 + var html = template('tooltip_startend_gps_temp', d);
  97 + showTip({
  98 + top: offset.top - 45,
  99 + left: offset.left,
  100 + container: html
  101 + });
  102 + })
  103 + .on('mouseout', hideTip);
87 } 104 }
88 }; 105 };
89 106
90 - 107 + var ftHeight = 40 + 40,//页脚
  108 + docHeight = $(document).height();
91 function showTip(op){ 109 function showTip(op){
92 tip.css('top', op.top) 110 tip.css('top', op.top)
93 .css('left', op.left) 111 .css('left', op.left)
94 .html(op.container) 112 .html(op.container)
95 .addClass('open').show(); 113 .addClass('open').show();
  114 +
  115 + var h = tip.height();
  116 + //超出下边界了
  117 + if(h + op.top + ftHeight > docHeight){
  118 + tip.css('top', op.top - h - 38);
  119 + }
  120 + }
  121 +
  122 + function hideTip(){
  123 + et = setTimeout(function(){
  124 + if(tip.hasClass('fixed'))
  125 + return;
  126 + if(tip.hasClass('hover'))
  127 + return;
  128 +
  129 + tip.hide();
  130 + },300);
96 } 131 }
97 132
98 function clearTime(){ 133 function clearTime(){
src/main/resources/static/pages/control/line/temps/alone_tp.html
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 <div class="col-md-6 panel-wrap"> 6 <div class="col-md-6 panel-wrap">
7 <div class="_panel"> 7 <div class="_panel">
8 <div class="_head" style="color: #2765A7;"> 8 <div class="_head" style="color: #2765A7;">
9 - 上行/上海火车站北广场 9 + 上行/{{startStationName}}
10 </div> 10 </div>
11 <table class="table table-striped table-bordered table-advance pb-table head"> 11 <table class="table table-striped table-bordered table-advance pb-table head">
12 <thead> 12 <thead>
@@ -25,26 +25,11 @@ @@ -25,26 +25,11 @@
25 </thead> 25 </thead>
26 </table> 26 </table>
27 <div class="_body"> 27 <div class="_body">
28 - <table class="table table-striped table-bordered table-advance pb-table data"> 28 + <table class="table table-striped table-bordered table-advance pb-table data" data-type="up">
29 <tbody> 29 <tbody>
30 - {{each up as item i}}  
31 - <tr data-id={{item.id}}>  
32 - <td name="lineNo">{{i + 1}}</td>  
33 - <td data-name="lpName"><a href="javascript:;">{{item.lpName}}</a></td>  
34 - <td data-name="clZbh">{{item.clZbh}}</td>  
35 - <td data-name="zdsj">{{item.zdsj}}</td>  
36 - <td></td>  
37 - <td data-name="fcsj">{{item.fcsj}}</td>  
38 - <td data-name="dfsj">{{item.dfsj}}</td>  
39 - <td></td>  
40 - <td class="hide-lt-1080" data-name="remarks">  
41 - {{if item.remarks != null}}  
42 - <a class="remarks-popover" href="javascript:;" data-toggle="popover" data-content="{{item.remarks}}" >备注</a>  
43 - {{/if}}  
44 - </td>  
45 - <td><a href="javascript:;">主</a></td> 30 + <tr>
  31 + <td colspan=10 class="empty-table-td"></td>
46 </tr> 32 </tr>
47 - {{/each}}  
48 </tbody> 33 </tbody>
49 </table> 34 </table>
50 </div> 35 </div>
@@ -53,7 +38,7 @@ @@ -53,7 +38,7 @@
53 <div class="col-md-6 panel-wrap"> 38 <div class="col-md-6 panel-wrap">
54 <div class="_panel"> 39 <div class="_panel">
55 <div class="_head" style="color: #C92121;"> 40 <div class="_head" style="color: #C92121;">
56 - 下行/华戴路川环南路 41 + 下行/{{endStationName}}
57 </div> 42 </div>
58 <table class="table table-striped table-bordered table-advance pb-table head"> 43 <table class="table table-striped table-bordered table-advance pb-table head">
59 <thead> 44 <thead>
@@ -72,26 +57,11 @@ @@ -72,26 +57,11 @@
72 </thead> 57 </thead>
73 </table> 58 </table>
74 <div class="_body"> 59 <div class="_body">
75 - <table class="table table-striped table-bordered table-advance pb-table data"> 60 + <table class="table table-striped table-bordered table-advance pb-table data" data-type="down">
76 <tbody> 61 <tbody>
77 - {{each down as item i}}  
78 - <tr data-id={{item.id}}>  
79 - <td name="lineNo">{{i + 1}}</td>  
80 - <td data-name="lpName"><a href="javascript:;">{{item.lpName}}</a></td>  
81 - <td data-name="clZbh">{{item.clZbh}}</td>  
82 - <td data-name="zdsj">{{item.zdsj}}</td>  
83 - <td></td>  
84 - <td data-name="fcsj">{{item.fcsj}}</td>  
85 - <td data-name="dfsj">{{item.dfsj}}</td>  
86 - <td></td>  
87 - <td class="hide-lt-1080" data-name="remarks">  
88 - {{if item.remarks != null}}  
89 - <a class="remarks-popover" href="javascript:;" data-toggle="popover" data-content="{{item.remarks}}" >备注</a>  
90 - {{/if}}  
91 - </td>  
92 - <td><a href="javascript:;">主</a></td> 62 + <tr>
  63 + <td colspan=10 class="empty-table-td"></td>
93 </tr> 64 </tr>
94 - {{/each}}  
95 </tbody> 65 </tbody>
96 </table> 66 </table>
97 </div> 67 </div>
@@ -102,16 +72,17 @@ @@ -102,16 +72,17 @@
102 <div class="pic-panel"> 72 <div class="pic-panel">
103 图例: 73 图例:
104 <span class="tl-yzx"></span> 74 <span class="tl-yzx"></span>
105 - <span class="tl-wzx"></span> 75 + <!--<span class="tl-wzx"></span>-->
106 <span class="tl-wd"></span> 76 <span class="tl-wd"></span>
107 <span class="tl-qrlb"></span> 77 <span class="tl-qrlb"></span>
108 <span class="tl-zzzx"></span> 78 <span class="tl-zzzx"></span>
109 - &nbsp;&nbsp;&nbsp;  
110 - <span class="tl-sf-f"></span> 79 + <!-- <span class="tl-sf-f"></span> -->
  80 +&nbsp;&nbsp;&nbsp;
  81 +
111 <span class="tl-xxfc"></span> 82 <span class="tl-xxfc"></span>
112 <span class="tl-xxsd"></span> 83 <span class="tl-xxsd"></span>
113 <span class="tl-xxrd"></span> 84 <span class="tl-xxrd"></span>
114 - <span class="tl-fcpqr"></span> 85 + <!--<span class="tl-fcpqr"></span>-->
115 </div> 86 </div>
116 </div> 87 </div>
117 88
@@ -167,12 +138,39 @@ @@ -167,12 +138,39 @@
167 </div> 138 </div>
168 139
169 <div class="panel-wrap" style="height: 209px;margin-top: 6px;"> 140 <div class="panel-wrap" style="height: 209px;margin-top: 6px;">
170 - <div class="_panel" id="lineSvg10904"> 141 + <div class="_panel" id="lineSvg{{lineCode}}">
171 142
172 </div> 143 </div>
173 </div> 144 </div>
174 </script> 145 </script>
175 146
  147 +<!-- 班次table -->
  148 +<script id="alone_plan_table_temp" type="text/html">
  149 +{{each list as item i}}
  150 + <tr data-id={{item.id}}>
  151 + <td name="lineNo"></td>
  152 + <td data-name="lpName"><a href="javascript:;">{{item.lpName}}</a></td>
  153 + <td data-name="clZbh">{{item.clZbh}}</td>
  154 + <td data-name="zdsj">{{item.zdsj}}</td>
  155 + <td></td>
  156 + <td data-name="fcsj">{{item.fcsj}}</td>
  157 + <td data-name="dfsj">{{item.dfsj}}</td>
  158 +
  159 + {{if item.status == -1}}
  160 + <td class="tl-qrlb">烂班</td>
  161 + {{else}}
  162 + <td></td>
  163 + {{/if}}
  164 + <td class="hide-lt-1080" data-name="remarks">
  165 + {{if item.remarks != null}}
  166 + <a class="remarks-popover" href="javascript:;" data-toggle="popover" data-content="{{item.remarks}}" >备注</a>
  167 + {{/if}}
  168 + </td>
  169 + <td><a href="javascript:;">主</a></td>
  170 + </tr>
  171 +{{/each}}
  172 +</script>
  173 +
176 <!-- 托管状态描述 --> 174 <!-- 托管状态描述 -->
177 <script id="tg_question_info_temp" type="text/html"> 175 <script id="tg_question_info_temp" type="text/html">
178 <table class="tg-question-table"> 176 <table class="tg-question-table">
@@ -313,7 +311,7 @@ @@ -313,7 +311,7 @@
313 {{each array as obj i}} 311 {{each array as obj i}}
314 <label> 312 <label>
315 <div class="checker"> 313 <div class="checker">
316 - <span><input type="checkbox" value={{obj.id}} name="ids[]" class="icheck" {{if obj.fcsj==item.fcsj}}checked{{/if}}></span></div> {{obj.fcsj}} 314 + <span><input type="checkbox" value={{obj.id}} name="ids[]" class="icheck" {{if obj.dfsj==item.dfsj}}checked{{/if}}></span></div> {{obj.dfsj}}
317 </label> 315 </label>
318 {{/each}} 316 {{/each}}
319 </div> 317 </div>
@@ -325,7 +323,7 @@ @@ -325,7 +323,7 @@
325 <div class="item full"> 323 <div class="item full">
326 <span class="item-label" style="width: 80px;line-height: 32px;">调整说明:</span> 324 <span class="item-label" style="width: 80px;line-height: 32px;">调整说明:</span>
327 <br> 325 <br>
328 - <select class="form-control" style="width: 100%;"> 326 + <select class="form-control" style="width: 100%;" name="reason">
329 <option value="配车">配车</option> 327 <option value="配车">配车</option>
330 <option value="保养">保养</option> 328 <option value="保养">保养</option>
331 <option value="故障">故障</option> 329 <option value="故障">故障</option>
@@ -346,10 +344,22 @@ @@ -346,10 +344,22 @@
346 344
347 <div class="form-custom-row"> 345 <div class="form-custom-row">
348 <div class="item full" > 346 <div class="item full" >
349 - <textarea class="form-control" rows="4" name="remarks" placeholder="烂班说明!不超过50个字符,必填"></textarea> 347 + <textarea class="form-control" rows="4" name="remarks" placeholder="烂班说明,必填" required></textarea>
350 </div> 348 </div>
351 </div> 349 </div>
352 350
  351 + <div class="form-custom-row">
  352 + <div class="item full" >
  353 + <label>
  354 + <div class="checker">
  355 + <span><input type="checkbox" value=1 name="spaceAdjust" class="icheck-blue" checked></span></div> 自动调整后续班次间隔为
  356 + </label>
  357 + <input type="number" name="spaceNum" value=15 style="width: 50px;height: 30px;margin: 0 5px;" > 分钟
  358 + &nbsp;<i class="fa fa-question-circle" style="cursor: pointer;" data-toggle="tooltip" data-placement="left" title="当前首个烂班为起点,调整后续班次间隔"></i>
  359 + </div>
  360 + </div>
  361 +
  362 +
353 <hr> 363 <hr>
354 <div class="form-custom-footer"> 364 <div class="form-custom-footer">
355 <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;确&nbsp;&nbsp;定 </button> 365 <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;确&nbsp;&nbsp;定 </button>
src/main/resources/static/pages/control/line/temps/home_table_tp.html
@@ -3,11 +3,22 @@ @@ -3,11 +3,22 @@
3 {{each list as obj i}} 3 {{each list as obj i}}
4 <tr> 4 <tr>
5 <td> {{obj.nbbm}} </td> 5 <td> {{obj.nbbm}} </td>
6 - <td> {{obj.endDistance}} </td>  
7 - <td class="col_hide_1680"> {{obj.endTime}} </td>  
8 - <td>{{obj.instructions}}</td>  
9 - <td> {{obj.speed}} </td>  
10 - <td> {{obj.roadSigns}} </td> 6 + <td>
  7 + {{if obj.currSch != null}}
  8 + {{obj.currSch.lpName}}
  9 + {{else}}
  10 + 无
  11 + {{/if}}
  12 + </td>
  13 + <td class="col_hide_1680"> {{obj.speed}} </td>
  14 + <td> 暂无 </td>
  15 + <td>
  16 +{{if obj.nextSch != null}}
  17 + {{obj.nextSch.dfsj}}
  18 +{{else}}
  19 + 无
  20 +{{/if}}
  21 + </td>
11 </tr> 22 </tr>
12 {{/each}} 23 {{/each}}
13 </script> 24 </script>
14 \ No newline at end of file 25 \ No newline at end of file
src/main/resources/static/pages/control/line/temps/home_tp.html
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 <div class="col-lg-2 "> 8 <div class="col-lg-2 ">
9 9
10 <div class="title"> 10 <div class="title">
11 - 发往{{lineObj.startStationName}}方向 <span class="badge"> 13 </span> 11 + 发往{{lineObj.startStationName}}方向 <span class="up-number" id="{{lineObj.lineCode}}_0_badge"> 0 </span>
12 <div class="help_text dropdown"> 12 <div class="help_text dropdown">
13 <span class=" blue dropdown-toggle col_hide_1440" 13 <span class=" blue dropdown-toggle col_hide_1440"
14 data-toggle="dropdown" aria-expanded="true" 14 data-toggle="dropdown" aria-expanded="true"
@@ -30,21 +30,20 @@ @@ -30,21 +30,20 @@
30 <table class="table table-striped table-bordered table-advance" 30 <table class="table table-striped table-bordered table-advance"
31 style="table-layout: fixed;"> 31 style="table-layout: fixed;">
32 <colgroup> 32 <colgroup>
33 - <col style="width: 20%;">  
34 - <col style="width: 19%;">  
35 - <col style="width: 20%;">  
36 - <col style="width: 14%;">  
37 - <col style="width: 14%;"> 33 + <col style="width: 22%;">
  34 + <col style="width: 17%;">
  35 + <col style="width: 17%;">
  36 + <col style="width: 22%;">
  37 + <col style="width: 22%;">
38 38
39 </colgroup> 39 </colgroup>
40 <thead> 40 <thead>
41 <tr> 41 <tr>
42 <th>车辆编码</th> 42 <th>车辆编码</th>
43 - <th>终点距离</th>  
44 - <th class="col_hide_1680">终点时间</th>  
45 - <th>指令</th>  
46 - <th>速度</th>  
47 <th>路牌</th> 43 <th>路牌</th>
  44 + <th>速度</th>
  45 + <th class="col_hide_1680">终点时间</th>
  46 + <th>下一班</th>
48 </tr> 47 </tr>
49 </thead> 48 </thead>
50 </table> 49 </table>
@@ -53,12 +52,11 @@ @@ -53,12 +52,11 @@
53 class="table table-striped table-bordered table-advance table-hover vehicDataTable" 52 class="table table-striped table-bordered table-advance table-hover vehicDataTable"
54 style="table-layout: fixed;" id="tab_{{lineObj.lineCode}}_0"> 53 style="table-layout: fixed;" id="tab_{{lineObj.lineCode}}_0">
55 <colgroup> 54 <colgroup>
56 - <col style="width: 20%;">  
57 - <col style="width: 19%;">  
58 - <col style="width: 20%;">  
59 - <col style="width: 14%;">  
60 - <col style="width: 14%;">  
61 - 55 + <col style="width: 22%;">
  56 + <col style="width: 17%;">
  57 + <col style="width: 17%;">
  58 + <col style="width: 22%;">
  59 + <col style="width: 22%;">
62 </colgroup> 60 </colgroup>
63 <tbody></tbody> 61 <tbody></tbody>
64 </table> 62 </table>
@@ -75,7 +73,7 @@ @@ -75,7 +73,7 @@
75 <div class="col-lg-2 down"> 73 <div class="col-lg-2 down">
76 74
77 <div class="title"> 75 <div class="title">
78 - 发往{{lineObj.endStationName}}方向 <span class="badge"> 7 </span> 76 + 发往{{lineObj.endStationName}}方向 <span class="down-number" id="{{lineObj.lineCode}}_1_badge"> 0 </span>
79 <div class="help_text dropdown"> 77 <div class="help_text dropdown">
80 <span class=" blue dropdown-toggle col_hide_1440" 78 <span class=" blue dropdown-toggle col_hide_1440"
81 data-toggle="dropdown" aria-expanded="true" 79 data-toggle="dropdown" aria-expanded="true"
@@ -93,21 +91,19 @@ @@ -93,21 +91,19 @@
93 <table class="table table-striped table-bordered table-advance" 91 <table class="table table-striped table-bordered table-advance"
94 style="table-layout: fixed;"> 92 style="table-layout: fixed;">
95 <colgroup> 93 <colgroup>
96 - <col style="width: 20%;">  
97 - <col style="width: 19%;">  
98 - <col style="width: 20%;">  
99 - <col style="width: 14%;">  
100 - <col style="width: 14%;">  
101 - 94 + <col style="width: 22%;">
  95 + <col style="width: 17%;">
  96 + <col style="width: 17%;">
  97 + <col style="width: 22%;">
  98 + <col style="width: 22%;">
102 </colgroup> 99 </colgroup>
103 <thead> 100 <thead>
104 <tr> 101 <tr>
105 <th>车辆编码</th> 102 <th>车辆编码</th>
106 - <th>终点距离</th>  
107 - <th class="col_hide_1680">终点时间</th>  
108 - <th>指令</th>  
109 - <th>速度</th>  
110 <th>路牌</th> 103 <th>路牌</th>
  104 + <th>速度</th>
  105 + <th class="col_hide_1680">终点时间</th>
  106 + <th>下一班</th>
111 </tr> 107 </tr>
112 </thead> 108 </thead>
113 </table> 109 </table>
@@ -116,11 +112,11 @@ @@ -116,11 +112,11 @@
116 class="table table-striped table-bordered table-advance table-hover vehicDataTable" 112 class="table table-striped table-bordered table-advance table-hover vehicDataTable"
117 style="table-layout: fixed;" id="tab_{{lineObj.lineCode}}_1"> 113 style="table-layout: fixed;" id="tab_{{lineObj.lineCode}}_1">
118 <colgroup> 114 <colgroup>
119 - <col style="width: 20%;">  
120 - <col style="width: 19%;">  
121 - <col style="width: 20%;">  
122 - <col style="width: 14%;">  
123 - <col style="width: 14%;"> 115 + <col style="width: 22%;">
  116 + <col style="width: 17%;">
  117 + <col style="width: 17%;">
  118 + <col style="width: 22%;">
  119 + <col style="width: 22%;">
124 120
125 </colgroup> 121 </colgroup>
126 <tbody> 122 <tbody>
src/main/resources/static/pages/control/line/temps/tooltip_tp.html
@@ -9,10 +9,41 @@ @@ -9,10 +9,41 @@
9 <div><a href="javascript:;" data-for="station" class="tip_modal">{{stationName}}</a></div> 9 <div><a href="javascript:;" data-for="station" class="tip_modal">{{stationName}}</a></div>
10 <div>速度:{{speed}}</div> 10 <div>速度:{{speed}}</div>
11 <hr > 11 <hr >
12 - <div>预计2分钟后到达<a href="javascript:;" data-for="station" class="tip_modal">下一站</a></div>  
13 - <div>终点站:<a href="javascript:;" data-for="station" > 终点</a></div> 12 + <div>预计 ? 分钟后到达<a href="javascript:;" data-for="station" class="tip_modal">下一站</a></div>
  13 + <div>终点站:
  14 + <a href="javascript:;" data-for="station" >
  15 + {{if currSch != null}}
  16 + {{currSch.zdzName}}
  17 + {{/if}}
  18 +
  19 + </a></div>
14 <hr > 20 <hr >
15 - <div class="subtitle">10秒前更新(在线)</div> 21 + <div class="subtitle">{{fromNow}}更新(在线)</div>
  22 + <div class="subtitle" style="margin-top: 8px;">
  23 + <a href="javascript:;" data-for="map" class="tip_modal" data-lon={{lon}} data-lat={{lat}} data-nbbm={{nbbm}}>
  24 + <i class="fa fa-map-marker"></i>
  25 + 地图查看
  26 + </a>
  27 + </div>
  28 +</div>
  29 +</script>
  30 +
  31 +<script id="tooltip_startend_gps_temp" type="text/html">
  32 +<div id="tooltip-Container" >
  33 + <div class="title">
  34 + <a href="javascript:;" data-for="station" class="tip_modal">{{nbbm}}</a>
  35 + </div>
  36 + <div>
  37 + {{lineName}}
  38 + </div>
  39 + <div><a href="javascript:;" data-for="station" class="tip_modal">{{stationName}}</a></div>
  40 + <div>停站时间:无 </div>
  41 + {{if nextSch != null}}
  42 + <div>计划 {{nextSch.dfsj}} 发车</div>
  43 + {{/if}}
  44 +
  45 + <hr >
  46 + <div class="subtitle">{{fromNow}}更新(在线)</div>
16 <div class="subtitle" style="margin-top: 8px;"> 47 <div class="subtitle" style="margin-top: 8px;">
17 <a href="javascript:;" data-for="map" class="tip_modal" data-lon={{lon}} data-lat={{lat}} data-nbbm={{nbbm}}> 48 <a href="javascript:;" data-for="map" class="tip_modal" data-lon={{lon}} data-lat={{lat}} data-nbbm={{nbbm}}>
18 <i class="fa fa-map-marker"></i> 49 <i class="fa fa-map-marker"></i>
src/main/resources/static/pages/mapmonitor/real/css/real.css
@@ -87,6 +87,7 @@ label.BMapLabel{ @@ -87,6 +87,7 @@ label.BMapLabel{
87 87
88 .mapRightWrap.vehicle{ 88 .mapRightWrap.vehicle{
89 height: calc(100% - 110px); 89 height: calc(100% - 110px);
  90 + overflow: auto;
90 } 91 }
91 92
92 .mapRightWrap.search{ 93 .mapRightWrap.search{
@@ -567,4 +568,22 @@ html{ @@ -567,4 +568,22 @@ html{
567 background: #ddd; 568 background: #ddd;
568 color: #333333; 569 color: #333333;
569 } 570 }
570 -/* GaoDe style end------- */  
571 \ No newline at end of file 571 \ No newline at end of file
  572 +/* GaoDe style end------- */
  573 +
  574 +
  575 +.map-gps-empty{
  576 + padding: 10px;
  577 + text-align: center;
  578 + color: #b37f7f;
  579 + border-bottom: 1px dashed #556471;
  580 + font-size: 13px;
  581 +}
  582 +
  583 +.mapRightWrap::-webkit-scrollbar-thumb {
  584 + box-shadow: 0 0 0 5px rgba(231, 236, 241, 0.52) inset;
  585 +}
  586 +
  587 +.gps_info_win p{
  588 + margin-bottom: 13px;
  589 + font-size: 13px;
  590 +}
src/main/resources/static/pages/mapmonitor/real/js/map_platform.js
@@ -12,6 +12,11 @@ var realMap = (function() { @@ -12,6 +12,11 @@ var realMap = (function() {
12 }); 12 });
13 } 13 }
14 14
  15 + /**
  16 + * 透明点,用于替换隐藏百度Marker的icon
  17 + */
  18 + var tmIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAbSURBVHjaYvz//z8DAwMDAxMDFAAAAAD//wMAMAYDAW/BVI8AAAAASUVORK5CYII=';
  19 +
15 var REAL_BAIDU_TEXT = '百度地图', REAL_GAODE_TEXT = '高德地图'; 20 var REAL_BAIDU_TEXT = '百度地图', REAL_GAODE_TEXT = '高德地图';
16 21
17 // 中心点 (上海市浦东新区政府) 22 // 中心点 (上海市浦东新区政府)
@@ -34,6 +39,14 @@ var realMap = (function() { @@ -34,6 +39,14 @@ var realMap = (function() {
34 //百度API Key 39 //百度API Key
35 var bdKey = 'IGGrr4UjwIYzatoCRFKEL8sT'; 40 var bdKey = 'IGGrr4UjwIYzatoCRFKEL8sT';
36 41
  42 + var bd_gps_info_win_opts = {
  43 + width : 190,
  44 + height: 255,
  45 + enableMessage:true
  46 + };
  47 +
  48 + //设备号和marker对照
  49 + var markersMap;
37 var real_map = { 50 var real_map = {
38 getMap: function(){ 51 getMap: function(){
39 return currentMap; 52 return currentMap;
@@ -75,6 +88,10 @@ var realMap = (function() { @@ -75,6 +88,10 @@ var realMap = (function() {
75 isVisible = true; 88 isVisible = true;
76 } 89 }
77 }); 90 });
  91 + //百度路况控件自身关闭按钮
  92 + $('.portlet-fullscreen').on('click', '.maplibTc .maplibTcClose', function(){
  93 + isVisible = false;
  94 + });
78 95
79 $('#tcWrap.maplibTc').addClass('animated bounceInLeft'); 96 $('#tcWrap.maplibTc').addClass('animated bounceInLeft');
80 $('.maplibTcBtn_deskTop.anchorTR').remove(); 97 $('.maplibTcBtn_deskTop.anchorTR').remove();
@@ -143,9 +160,6 @@ var realMap = (function() { @@ -143,9 +160,6 @@ var realMap = (function() {
143 cb && cb(); 160 cb && cb();
144 }, 161 },
145 onPolylinesSet: function(pline){ 162 onPolylinesSet: function(pline){
146 - //pline.setStrokeColor('#333');  
147 - //console.log(pline.getStrokeColor());  
148 - console.log(pline);  
149 cb && cb(); 163 cb && cb();
150 }, 164 },
151 onGetBusLineComplete: function(line){ 165 onGetBusLineComplete: function(line){
@@ -156,19 +170,32 @@ var realMap = (function() { @@ -156,19 +170,32 @@ var realMap = (function() {
156 }, 170 },
157 //将GPS信号画到地图上 171 //将GPS信号画到地图上
158 drawGpsMarker: function(gpsList){ 172 drawGpsMarker: function(gpsList){
  173 + markersMap = {};
159 var map = currentMap.map; 174 var map = currentMap.map;
  175 + var markerClusterer = new BMapLib.MarkerClusterer(map, {isAverangeCenter : true,minClusterSize : 3});
160 real_map.baidu.coordsConvert(gpsList, function(){ 176 real_map.baidu.coordsConvert(gpsList, function(){
161 - console.log(gpsList);  
162 //绘制车辆位置 177 //绘制车辆位置
163 - var label; 178 + var marker;
164 $.each(gpsList, function(i, gpsData){ 179 $.each(gpsList, function(i, gpsData){
165 - //生成marker  
166 - label = createLabel(gpsData);  
167 - map.addOverlay(label); 180 + marker = createBDMarkerByGps(gpsData)
  181 + map.addOverlay(marker);
  182 + //marker加入点聚合
  183 + markerClusterer.addMarker(marker);
  184 +
  185 + markersMap[gpsData.deviceId] = marker;
168 }); 186 });
169 187
170 }); 188 });
171 }, 189 },
  190 + goToMarker: function(deviceId){
  191 + var m = markersMap[deviceId];
  192 + if(m){
  193 + currentMap.map.panTo(m.point);
  194 + setTimeout(function(){
  195 + bdOpenWindow(m);
  196 + }, 500);
  197 + }
  198 + },
172 coordsConvert: function(list, cb){ 199 coordsConvert: function(list, cb){
173 if(list.length > 100) 200 if(list.length > 100)
174 list = list.slice(0, 100); 201 list = list.slice(0, 100);
@@ -317,14 +344,6 @@ var realMap = (function() { @@ -317,14 +344,6 @@ var realMap = (function() {
317 layer.msg('正在切换到' + text + '...', {icon : 16,shade : [ 0.6, '#393D49' ],time : 0}); 344 layer.msg('正在切换到' + text + '...', {icon : 16,shade : [ 0.6, '#393D49' ],time : 0});
318 } 345 }
319 346
320 - function createLabel(gpsData){  
321 - var point = new BMap.Point(gpsData.bd_coord.x, gpsData.bd_coord.y)  
322 - //label  
323 - ,label = new BMap.Label(gpsData.nbbm.replace('-',''), {position: point, offset: new BMap.Size(-28,-10)});  
324 - label.setStyle({borderColor: bgColor(gpsData),borderRadius: '5px', padding: '3px 5px', color: tColor(gpsData), backgroundColor: bgColor(gpsData)});  
325 - return label;  
326 - }  
327 -  
328 /** 347 /**
329 * 颜色 348 * 颜色
330 */ 349 */
@@ -348,5 +367,31 @@ var realMap = (function() { @@ -348,5 +367,31 @@ var realMap = (function() {
348 return "rgb(229, 229, 229)"; 367 return "rgb(229, 229, 229)";
349 } 368 }
350 369
  370 + function createBDMarkerByGps(gpsData){
  371 + //marker
  372 + var point = new BMap.Point(gpsData.bd_coord.x, gpsData.bd_coord.y)
  373 + //label
  374 + ,label = new BMap.Label(gpsData.nbbm.replace('-',''), {position: point, offset: new BMap.Size(-20,8)});
  375 + label.setStyle({borderColor: bgColor(gpsData), padding: '6px 6px 4px 6px', color: tColor(gpsData), backgroundColor: bgColor(gpsData)});
  376 + var marker = new BMap.Marker(point);
  377 + marker.setLabel(label);
  378 + //icon
  379 + marker.setIcon(new BMap.Icon(tmIcon, new BMap.Size(25,25)));
  380 + //window 绑定到 label
  381 + marker.infoWindow = new BMap.InfoWindow(bd_gps_info_win_opts);
  382 + //数据绑定到label
  383 + marker.gpsData = gpsData;
  384 +
  385 + //mouseover
  386 + label.addEventListener('mouseover', function(){
  387 + bdOpenWindow(marker);
  388 + });
  389 + return marker;
  390 + }
  391 +
  392 + function bdOpenWindow(marker){
  393 + marker.infoWindow.setContent(template('gps_info_win_temp', marker.gpsData));
  394 + currentMap.map.openInfoWindow(marker.infoWindow, marker.point);
  395 + }
351 return real_map; 396 return real_map;
352 })(); 397 })();
353 \ No newline at end of file 398 \ No newline at end of file
src/main/resources/static/pages/mapmonitor/real/js/real.js
@@ -39,8 +39,9 @@ @@ -39,8 +39,9 @@
39 // 刷新 39 // 刷新
40 return; 40 return;
41 } 41 }
  42 + var method = $(this).data('click');
42 43
43 - if (playAnimation) 44 + if (!method || playAnimation)
44 return; 45 return;
45 playAnimation = true; 46 playAnimation = true;
46 47
@@ -48,7 +49,7 @@ @@ -48,7 +49,7 @@
48 $('.mapTools div.item.active').removeClass('active'); 49 $('.mapTools div.item.active').removeClass('active');
49 $(this).addClass('active'); 50 $(this).addClass('active');
50 51
51 - toolsEvent[$(this).data('click')](); 52 + toolsEvent[method]();
52 }); 53 });
53 54
54 var classzz = 'mapRightWrap z-depth-3 '; 55 var classzz = 'mapRightWrap z-depth-3 ';
@@ -65,8 +66,10 @@ @@ -65,8 +66,10 @@
65 resetRotate(null, searchPanel.init); 66 resetRotate(null, searchPanel.init);
66 }, 67 },
67 notice : function() { 68 notice : function() {
  69 + alert('notice');
68 }, 70 },
69 playBack : function() { 71 playBack : function() {
  72 + alert('playBack');
70 }, 73 },
71 clearStyle : function() { 74 clearStyle : function() {
72 mrw.removeClass( 75 mrw.removeClass(
src/main/resources/static/pages/mapmonitor/real/js/vehicle.js
@@ -4,16 +4,15 @@ @@ -4,16 +4,15 @@
4 4
5 var vehiclePanel = (function() { 5 var vehiclePanel = (function() {
6 6
7 - function getCurr(){ 7 + function getCurrMap(){
8 return realMap[realMap.getMap().fName]; 8 return realMap[realMap.getMap().fName];
9 } 9 }
10 var storage = window.localStorage; 10 var storage = window.localStorage;
11 11
12 function closeAll(){ 12 function closeAll(){
13 - $('a[data-toggle=collapse]').collapse('hide'); 13 + $('.mapRightWrap .collapse.in').collapse('hide');
14 } 14 }
15 15
16 -  
17 // 手风琴收拢 16 // 手风琴收拢
18 $('.mapRightWrap').on('hide.bs.collapse', '.panel-collapse', function() { 17 $('.mapRightWrap').on('hide.bs.collapse', '.panel-collapse', function() {
19 $(this).prev().find('span.icon').addClass('rotate'); 18 $(this).prev().find('span.icon').addClass('rotate');
@@ -23,27 +22,45 @@ var vehiclePanel = (function() { @@ -23,27 +22,45 @@ var vehiclePanel = (function() {
23 $('.mapRightWrap').on('show.bs.collapse', '.panel-collapse', function() { 22 $('.mapRightWrap').on('show.bs.collapse', '.panel-collapse', function() {
24 $(this).prev().find('span.icon').removeClass('rotate'); 23 $(this).prev().find('span.icon').removeClass('rotate');
25 var lineCode = $(this).data('line'); 24 var lineCode = $(this).data('line');
26 -  
27 //收拢其他 25 //收拢其他
28 closeAll(); 26 closeAll();
29 -  
30 - //该线路的GPS点 27 + //过滤出该线路的GPS点
31 var showList = []; 28 var showList = [];
32 - $.each(lineGps[lineCode], function(){  
33 - showList.push(allGps[this]);  
34 - })  
35 - //在地图上画出线路  
36 - var mapObj = getCurr();  
37 - console.log('allGps', allGps, 'lineCode', lineCode);  
38 - mapObj.drawLine($(this).data('name'), function(){  
39 - mapObj.drawGpsMarker(showList);  
40 - });  
41 - 29 + if(lineGps[lineCode]){
  30 + $.each(lineGps[lineCode], function(){
  31 + showList.push(allGps[this]);
  32 + });
  33 + }
42 //显示车辆列表 34 //显示车辆列表
43 var htmlStr = template('vehicle_panel_collapse_temp', {list: showList}); 35 var htmlStr = template('vehicle_panel_collapse_temp', {list: showList});
44 $(this).html(htmlStr); 36 $(this).html(htmlStr);
  37 +
  38 + /**
  39 + * 延迟一下再画地图,不然会有点卡
  40 + */
  41 + var that = $(this);
  42 + setTimeout(function(){
  43 + //在地图上画出线路
  44 + var mapObj = getCurrMap();
  45 + mapObj.drawLine(that.data('name'), function(){
  46 + mapObj.drawGpsMarker(showList);
  47 + });
  48 + }, 500);
45 }); 49 });
46 50
  51 + //展开完成
  52 + $('.mapRightWrap').on('shown.bs.collapse', '.panel-collapse', function() {
  53 + //滚动到激活项
  54 + var cont = $('.mapRightWrap'),h = $(this).prev();
  55 + cont.scrollTop(h.offset().top - cont.offset().top + h.scrollTop());
  56 + });
  57 +
  58 + //go to marker
  59 + $('.mapRightWrap').on('click', '.goto-marker', function() {
  60 + getCurrMap().goToMarker($(this).data('deviceid'));
  61 + });
  62 +
  63 +
47 //GPS刷新事件 64 //GPS刷新事件
48 var allGps = {}; 65 var allGps = {};
49 var lineGps = {}; 66 var lineGps = {};
@@ -75,10 +92,10 @@ var vehiclePanel = (function() { @@ -75,10 +92,10 @@ var vehiclePanel = (function() {
75 var htmlStr = template('vehicle_panel_temp', {list: lines}); 92 var htmlStr = template('vehicle_panel_temp', {list: lines});
76 $('.mapRightWrap').html(htmlStr).addClass('vehicle'); 93 $('.mapRightWrap').html(htmlStr).addClass('vehicle');
77 //滚动条 94 //滚动条
78 - $('.gps-line-wrap').slimscroll({ 95 + /*$('.gps-line-wrap').slimscroll({
79 height: '100%', 96 height: '100%',
80 alwaysVisible: true 97 alwaysVisible: true
81 - }); 98 + });*/
82 /*var line = {code: 10103, name: '119路'}; 99 /*var line = {code: 10103, name: '119路'};
83 $get('/gps/real/line/' + line.code, null, function(data){ 100 $get('/gps/real/line/' + line.code, null, function(data){
84 //过滤掉没有自编号和站点名为空的 101 //过滤掉没有自编号和站点名为空的
src/main/resources/static/pages/mapmonitor/real/plugins/MarkerClusterer.js 0 → 100644
  1 +/**
  2 + * @fileoverview MarkerClusterer标记聚合器用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。
  3 + * 主入口类是<a href="symbols/BMapLib.MarkerClusterer.html">MarkerClusterer</a>,
  4 + * 基于Baidu Map API 1.2。
  5 + *
  6 + * @author Baidu Map Api Group
  7 + * @version 1.2
  8 + */
  9 +
  10 +
  11 +/**
  12 + * @namespace BMap的所有library类均放在BMapLib命名空间下
  13 + */
  14 +var BMapLib = window.BMapLib = BMapLib || {};
  15 +(function(){
  16 +
  17 + /**
  18 + * 获取一个扩展的视图范围,把上下左右都扩大一样的像素值。
  19 + * @param {Map} map BMap.Map的实例化对象
  20 + * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
  21 + * @param {Number} gridSize 要扩大的像素值
  22 + *
  23 + * @return {BMap.Bounds} 返回扩大后的视图范围。
  24 + */
  25 + var getExtendedBounds = function(map, bounds, gridSize){
  26 + bounds = cutBoundsInRange(bounds);
  27 + var pixelNE = map.pointToPixel(bounds.getNorthEast());
  28 + var pixelSW = map.pointToPixel(bounds.getSouthWest());
  29 + pixelNE.x += gridSize;
  30 + pixelNE.y -= gridSize;
  31 + pixelSW.x -= gridSize;
  32 + pixelSW.y += gridSize;
  33 + var newNE = map.pixelToPoint(pixelNE);
  34 + var newSW = map.pixelToPoint(pixelSW);
  35 + return new BMap.Bounds(newSW, newNE);
  36 + };
  37 +
  38 + /**
  39 + * 按照百度地图支持的世界范围对bounds进行边界处理
  40 + * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
  41 + *
  42 + * @return {BMap.Bounds} 返回不越界的视图范围
  43 + */
  44 + var cutBoundsInRange = function (bounds) {
  45 + var maxX = getRange(bounds.getNorthEast().lng, -180, 180);
  46 + var minX = getRange(bounds.getSouthWest().lng, -180, 180);
  47 + var maxY = getRange(bounds.getNorthEast().lat, -74, 74);
  48 + var minY = getRange(bounds.getSouthWest().lat, -74, 74);
  49 + return new BMap.Bounds(new BMap.Point(minX, minY), new BMap.Point(maxX, maxY));
  50 + };
  51 +
  52 + /**
  53 + * 对单个值进行边界处理。
  54 + * @param {Number} i 要处理的数值
  55 + * @param {Number} min 下边界值
  56 + * @param {Number} max 上边界值
  57 + *
  58 + * @return {Number} 返回不越界的数值
  59 + */
  60 + var getRange = function (i, mix, max) {
  61 + mix && (i = Math.max(i, mix));
  62 + max && (i = Math.min(i, max));
  63 + return i;
  64 + };
  65 +
  66 + /**
  67 + * 判断给定的对象是否为数组
  68 + * @param {Object} source 要测试的对象
  69 + *
  70 + * @return {Boolean} 如果是数组返回true,否则返回false
  71 + */
  72 + var isArray = function (source) {
  73 + return '[object Array]' === Object.prototype.toString.call(source);
  74 + };
  75 +
  76 + /**
  77 + * 返回item在source中的索引位置
  78 + * @param {Object} item 要测试的对象
  79 + * @param {Array} source 数组
  80 + *
  81 + * @return {Number} 如果在数组内,返回索引,否则返回-1
  82 + */
  83 + var indexOf = function(item, source){
  84 + var index = -1;
  85 + if(isArray(source)){
  86 + if (source.indexOf) {
  87 + index = source.indexOf(item);
  88 + } else {
  89 + for (var i = 0, m; m = source[i]; i++) {
  90 + if (m === item) {
  91 + index = i;
  92 + break;
  93 + }
  94 + }
  95 + }
  96 + }
  97 + return index;
  98 + };
  99 +
  100 + /**
  101 + *@exports MarkerClusterer as BMapLib.MarkerClusterer
  102 + */
  103 + var MarkerClusterer =
  104 + /**
  105 + * MarkerClusterer
  106 + * @class 用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能
  107 + * @constructor
  108 + * @param {Map} map 地图的一个实例。
  109 + * @param {Json Object} options 可选参数,可选项包括:<br />
  110 + * markers {Array<Marker>} 要聚合的标记数组<br />
  111 + * girdSize {Number} 聚合计算时网格的像素大小,默认60<br />
  112 + * maxZoom {Number} 最大的聚合级别,大于该级别就不进行相应的聚合<br />
  113 + * minClusterSize {Number} 最小的聚合数量,小于该数量的不能成为一个聚合,默认为2<br />
  114 + * isAverangeCenter {Boolean} 聚合点的落脚位置是否是所有聚合在内点的平均值,默认为否,落脚在聚合内的第一个点<br />
  115 + * styles {Array<IconStyle>} 自定义聚合后的图标风格,请参考TextIconOverlay类<br />
  116 + */
  117 + BMapLib.MarkerClusterer = function(map, options){
  118 + if (!map){
  119 + return;
  120 + }
  121 + this._map = map;
  122 + this._markers = [];
  123 + this._clusters = [];
  124 +
  125 + var opts = options || {};
  126 + this._gridSize = opts["gridSize"] || 60;
  127 + this._maxZoom = opts["maxZoom"] || 18;
  128 + this._minClusterSize = opts["minClusterSize"] || 2;
  129 + this._isAverageCenter = false;
  130 + if (opts['isAverageCenter'] != undefined) {
  131 + this._isAverageCenter = opts['isAverageCenter'];
  132 + }
  133 + this._styles = opts["styles"] || [];
  134 +
  135 + var that = this;
  136 + this._map.addEventListener("zoomend",function(){
  137 + that._redraw();
  138 + });
  139 +
  140 + this._map.addEventListener("moveend",function(){
  141 + that._redraw();
  142 + });
  143 +
  144 + var mkrs = opts["markers"];
  145 + isArray(mkrs) && this.addMarkers(mkrs);
  146 + };
  147 +
  148 + /**
  149 + * 添加要聚合的标记数组。
  150 + * @param {Array<Marker>} markers 要聚合的标记数组
  151 + *
  152 + * @return 无返回值。
  153 + */
  154 + MarkerClusterer.prototype.addMarkers = function(markers){
  155 + for(var i = 0, len = markers.length; i <len ; i++){
  156 + this._pushMarkerTo(markers[i]);
  157 + }
  158 + this._createClusters();
  159 + };
  160 +
  161 + /**
  162 + * 把一个标记添加到要聚合的标记数组中
  163 + * @param {BMap.Marker} marker 要添加的标记
  164 + *
  165 + * @return 无返回值。
  166 + */
  167 + MarkerClusterer.prototype._pushMarkerTo = function(marker){
  168 + var index = indexOf(marker, this._markers);
  169 + if(index === -1){
  170 + marker.isInCluster = false;
  171 + this._markers.push(marker);//Marker拖放后enableDragging不做变化,忽略
  172 + }
  173 + };
  174 +
  175 + /**
  176 + * 添加一个聚合的标记。
  177 + * @param {BMap.Marker} marker 要聚合的单个标记。
  178 + * @return 无返回值。
  179 + */
  180 + MarkerClusterer.prototype.addMarker = function(marker) {
  181 + this._pushMarkerTo(marker);
  182 + this._createClusters();
  183 + };
  184 +
  185 + /**
  186 + * 根据所给定的标记,创建聚合点
  187 + * @return 无返回值
  188 + */
  189 + MarkerClusterer.prototype._createClusters = function(){
  190 + var mapBounds = this._map.getBounds();
  191 + var extendedBounds = getExtendedBounds(this._map, mapBounds, this._gridSize);
  192 + for(var i = 0, marker; marker = this._markers[i]; i++){
  193 + if(!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition()) ){
  194 + this._addToClosestCluster(marker);
  195 + }
  196 + }
  197 + };
  198 +
  199 + /**
  200 + * 根据标记的位置,把它添加到最近的聚合中
  201 + * @param {BMap.Marker} marker 要进行聚合的单个标记
  202 + *
  203 + * @return 无返回值。
  204 + */
  205 + MarkerClusterer.prototype._addToClosestCluster = function (marker){
  206 + var distance = 4000000;
  207 + var clusterToAddTo = null;
  208 + var position = marker.getPosition();
  209 + for(var i = 0, cluster; cluster = this._clusters[i]; i++){
  210 + var center = cluster.getCenter();
  211 + if(center){
  212 + var d = this._map.getDistance(center, marker.getPosition());
  213 + if(d < distance){
  214 + distance = d;
  215 + clusterToAddTo = cluster;
  216 + }
  217 + }
  218 + }
  219 +
  220 + if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)){
  221 + clusterToAddTo.addMarker(marker);
  222 + } else {
  223 + var cluster = new Cluster(this);
  224 + cluster.addMarker(marker);
  225 + this._clusters.push(cluster);
  226 + }
  227 + };
  228 +
  229 + /**
  230 + * 清除上一次的聚合的结果
  231 + * @return 无返回值。
  232 + */
  233 + MarkerClusterer.prototype._clearLastClusters = function(){
  234 + for(var i = 0, cluster; cluster = this._clusters[i]; i++){
  235 + cluster.remove();
  236 + }
  237 + this._clusters = [];//置空Cluster数组
  238 + this._removeMarkersFromCluster();//把Marker的cluster标记设为false
  239 + };
  240 +
  241 + /**
  242 + * 清除某个聚合中的所有标记
  243 + * @return 无返回值
  244 + */
  245 + MarkerClusterer.prototype._removeMarkersFromCluster = function(){
  246 + for(var i = 0, marker; marker = this._markers[i]; i++){
  247 + marker.isInCluster = false;
  248 + }
  249 + };
  250 +
  251 + /**
  252 + * 把所有的标记从地图上清除
  253 + * @return 无返回值
  254 + */
  255 + MarkerClusterer.prototype._removeMarkersFromMap = function(){
  256 + var tmplabel;
  257 + for(var i = 0, marker; marker = this._markers[i]; i++){
  258 + marker.isInCluster = false;
  259 +
  260 + tmplabel = marker.getLabel();
  261 +
  262 + this._map.removeOverlay(marker);
  263 +
  264 + marker.setLabel(tmplabel);
  265 + }
  266 + };
  267 +
  268 + /**
  269 + * 删除单个标记
  270 + * @param {BMap.Marker} marker 需要被删除的marker
  271 + *
  272 + * @return {Boolean} 删除成功返回true,否则返回false
  273 + */
  274 + MarkerClusterer.prototype._removeMarker = function(marker) {
  275 + var index = indexOf(marker, this._markers),tmplabel;
  276 + if (index === -1) {
  277 + return false;
  278 + }
  279 + tmplabel = marker.getLabel();
  280 + this._map.removeOverlay(marker);
  281 + marker.setLabel(tmplabel);
  282 + this._markers.splice(index, 1);
  283 + return true;
  284 + };
  285 +
  286 + /**
  287 + * 删除单个标记
  288 + * @param {BMap.Marker} marker 需要被删除的marker
  289 + *
  290 + * @return {Boolean} 删除成功返回true,否则返回false
  291 + */
  292 + MarkerClusterer.prototype.removeMarker = function(marker) {
  293 + var success = this._removeMarker(marker);
  294 + if (success) {
  295 + this._clearLastClusters();
  296 + this._createClusters();
  297 + }
  298 + return success;
  299 + };
  300 +
  301 + /**
  302 + * 删除一组标记
  303 + * @param {Array<BMap.Marker>} markers 需要被删除的marker数组
  304 + *
  305 + * @return {Boolean} 删除成功返回true,否则返回false
  306 + */
  307 + MarkerClusterer.prototype.removeMarkers = function(markers) {
  308 + var success = false;
  309 + for (var i = 0; i < markers.length; i++) {
  310 + var r = this._removeMarker(markers[i]);
  311 + success = success || r;
  312 + }
  313 +
  314 + if (success) {
  315 + this._clearLastClusters();
  316 + this._createClusters();
  317 + }
  318 + return success;
  319 + };
  320 +
  321 + /**
  322 + * 从地图上彻底清除所有的标记
  323 + * @return 无返回值
  324 + */
  325 + MarkerClusterer.prototype.clearMarkers = function() {
  326 + this._clearLastClusters();
  327 + this._removeMarkersFromMap();
  328 + this._markers = [];
  329 + };
  330 +
  331 + /**
  332 + * 重新生成,比如改变了属性等
  333 + * @return 无返回值
  334 + */
  335 + MarkerClusterer.prototype._redraw = function () {
  336 + this._clearLastClusters();
  337 + this._createClusters();
  338 + };
  339 +
  340 + /**
  341 + * 获取网格大小
  342 + * @return {Number} 网格大小
  343 + */
  344 + MarkerClusterer.prototype.getGridSize = function() {
  345 + return this._gridSize;
  346 + };
  347 +
  348 + /**
  349 + * 设置网格大小
  350 + * @param {Number} size 网格大小
  351 + * @return 无返回值
  352 + */
  353 + MarkerClusterer.prototype.setGridSize = function(size) {
  354 + this._gridSize = size;
  355 + this._redraw();
  356 + };
  357 +
  358 + /**
  359 + * 获取聚合的最大缩放级别。
  360 + * @return {Number} 聚合的最大缩放级别。
  361 + */
  362 + MarkerClusterer.prototype.getMaxZoom = function() {
  363 + return this._maxZoom;
  364 + };
  365 +
  366 + /**
  367 + * 设置聚合的最大缩放级别
  368 + * @param {Number} maxZoom 聚合的最大缩放级别
  369 + * @return 无返回值
  370 + */
  371 + MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
  372 + this._maxZoom = maxZoom;
  373 + this._redraw();
  374 + };
  375 +
  376 + /**
  377 + * 获取聚合的样式风格集合
  378 + * @return {Array<IconStyle>} 聚合的样式风格集合
  379 + */
  380 + MarkerClusterer.prototype.getStyles = function() {
  381 + return this._styles;
  382 + };
  383 +
  384 + /**
  385 + * 设置聚合的样式风格集合
  386 + * @param {Array<IconStyle>} styles 样式风格数组
  387 + * @return 无返回值
  388 + */
  389 + MarkerClusterer.prototype.setStyles = function(styles) {
  390 + this._styles = styles;
  391 + this._redraw();
  392 + };
  393 +
  394 + /**
  395 + * 获取单个聚合的最小数量。
  396 + * @return {Number} 单个聚合的最小数量。
  397 + */
  398 + MarkerClusterer.prototype.getMinClusterSize = function() {
  399 + return this._minClusterSize;
  400 + };
  401 +
  402 + /**
  403 + * 设置单个聚合的最小数量。
  404 + * @param {Number} size 单个聚合的最小数量。
  405 + * @return 无返回值。
  406 + */
  407 + MarkerClusterer.prototype.setMinClusterSize = function(size) {
  408 + this._minClusterSize = size;
  409 + this._redraw();
  410 + };
  411 +
  412 + /**
  413 + * 获取单个聚合的落脚点是否是聚合内所有标记的平均中心。
  414 + * @return {Boolean} true或false。
  415 + */
  416 + MarkerClusterer.prototype.isAverageCenter = function() {
  417 + return this._isAverageCenter;
  418 + };
  419 +
  420 + /**
  421 + * 获取聚合的Map实例。
  422 + * @return {Map} Map的示例。
  423 + */
  424 + MarkerClusterer.prototype.getMap = function() {
  425 + return this._map;
  426 + };
  427 +
  428 + /**
  429 + * 获取所有的标记数组。
  430 + * @return {Array<Marker>} 标记数组。
  431 + */
  432 + MarkerClusterer.prototype.getMarkers = function() {
  433 + return this._markers;
  434 + };
  435 +
  436 + /**
  437 + * 获取聚合的总数量。
  438 + * @return {Number} 聚合的总数量。
  439 + */
  440 + MarkerClusterer.prototype.getClustersCount = function() {
  441 + var count = 0;
  442 + for(var i = 0, cluster; cluster = this._clusters[i]; i++){
  443 + cluster.isReal() && count++;
  444 + }
  445 + return count;
  446 + };
  447 +
  448 + /**
  449 + * @ignore
  450 + * Cluster
  451 + * @class 表示一个聚合对象,该聚合,包含有N个标记,这N个标记组成的范围,并有予以显示在Map上的TextIconOverlay等。
  452 + * @constructor
  453 + * @param {MarkerClusterer} markerClusterer 一个标记聚合器示例。
  454 + */
  455 + function Cluster(markerClusterer){
  456 + this._markerClusterer = markerClusterer;
  457 + this._map = markerClusterer.getMap();
  458 + this._minClusterSize = markerClusterer.getMinClusterSize();
  459 + this._isAverageCenter = markerClusterer.isAverageCenter();
  460 + this._center = null;//落脚位置
  461 + this._markers = [];//这个Cluster中所包含的markers
  462 + this._gridBounds = null;//以中心点为准,向四边扩大gridSize个像素的范围,也即网格范围
  463 + this._isReal = false; //真的是个聚合
  464 +
  465 + this._clusterMarker = new BMapLib.TextIconOverlay(this._center, this._markers.length, {"styles":this._markerClusterer.getStyles()});
  466 + //this._map.addOverlay(this._clusterMarker);
  467 + }
  468 +
  469 + /**
  470 + * 向该聚合添加一个标记。
  471 + * @param {Marker} marker 要添加的标记。
  472 + * @return 无返回值。
  473 + */
  474 + Cluster.prototype.addMarker = function(marker){
  475 + if(this.isMarkerInCluster(marker)){
  476 + return false;
  477 + }//也可用marker.isInCluster判断,外面判断OK,这里基本不会命中
  478 +
  479 + if (!this._center){
  480 + this._center = marker.getPosition();
  481 + this.updateGridBounds();//
  482 + } else {
  483 + if(this._isAverageCenter){
  484 + var l = this._markers.length + 1;
  485 + var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;
  486 + var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;
  487 + this._center = new BMap.Point(lng, lat);
  488 + this.updateGridBounds();
  489 + }//计算新的Center
  490 + }
  491 +
  492 + marker.isInCluster = true;
  493 + this._markers.push(marker);
  494 +
  495 + var len = this._markers.length,tmplabel;
  496 + if(len < this._minClusterSize ){
  497 + this._map.addOverlay(marker);
  498 + //this.updateClusterMarker();
  499 + return true;
  500 + } else if (len === this._minClusterSize) {
  501 + for (var i = 0; i < len; i++) {
  502 + tmplabel = this._markers[i].getLabel();
  503 + this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);
  504 + this._markers[i].setLabel(tmplabel);
  505 + }
  506 +
  507 + }
  508 + this._map.addOverlay(this._clusterMarker);
  509 + this._isReal = true;
  510 + this.updateClusterMarker();
  511 + return true;
  512 + };
  513 +
  514 + /**
  515 + * 判断一个标记是否在该聚合中。
  516 + * @param {Marker} marker 要判断的标记。
  517 + * @return {Boolean} true或false。
  518 + */
  519 + Cluster.prototype.isMarkerInCluster= function(marker){
  520 + if (this._markers.indexOf) {
  521 + return this._markers.indexOf(marker) != -1;
  522 + } else {
  523 + for (var i = 0, m; m = this._markers[i]; i++) {
  524 + if (m === marker) {
  525 + return true;
  526 + }
  527 + }
  528 + }
  529 + return false;
  530 + };
  531 +
  532 + /**
  533 + * 判断一个标记是否在该聚合网格范围中。
  534 + * @param {Marker} marker 要判断的标记。
  535 + * @return {Boolean} true或false。
  536 + */
  537 + Cluster.prototype.isMarkerInClusterBounds = function(marker) {
  538 + return this._gridBounds.containsPoint(marker.getPosition());
  539 + };
  540 +
  541 + Cluster.prototype.isReal = function(marker) {
  542 + return this._isReal;
  543 + };
  544 +
  545 + /**
  546 + * 更新该聚合的网格范围。
  547 + * @return 无返回值。
  548 + */
  549 + Cluster.prototype.updateGridBounds = function() {
  550 + var bounds = new BMap.Bounds(this._center, this._center);
  551 + this._gridBounds = getExtendedBounds(this._map, bounds, this._markerClusterer.getGridSize());
  552 + };
  553 +
  554 + /**
  555 + * 更新该聚合的显示样式,也即TextIconOverlay。
  556 + * @return 无返回值。
  557 + */
  558 + Cluster.prototype.updateClusterMarker = function () {
  559 + if (this._map.getZoom() > this._markerClusterer.getMaxZoom()) {
  560 + this._clusterMarker && this._map.removeOverlay(this._clusterMarker);
  561 + for (var i = 0, marker; marker = this._markers[i]; i++) {
  562 + this._map.addOverlay(marker);
  563 + }
  564 + return;
  565 + }
  566 +
  567 + if (this._markers.length < this._minClusterSize) {
  568 + this._clusterMarker.hide();
  569 + return;
  570 + }
  571 +
  572 + this._clusterMarker.setPosition(this._center);
  573 +
  574 + this._clusterMarker.setText(this._markers.length);
  575 +
  576 + var thatMap = this._map;
  577 + var thatBounds = this.getBounds();
  578 + this._clusterMarker.addEventListener("click", function(event){
  579 + thatMap.setViewport(thatBounds);
  580 + });
  581 +
  582 + };
  583 +
  584 + /**
  585 + * 删除该聚合。
  586 + * @return 无返回值。
  587 + */
  588 + Cluster.prototype.remove = function(){
  589 + var tmplabel;
  590 + for (var i = 0, m; m = this._markers[i]; i++) {
  591 + tmplabel = this._markers[i].getLabel();
  592 + this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);
  593 + this._markers[i].setLabel(tmplabel);
  594 + }//清除散的标记点
  595 + this._map.removeOverlay(this._clusterMarker);
  596 + this._markers.length = 0;
  597 + delete this._markers;
  598 + }
  599 +
  600 + /**
  601 + * 获取该聚合所包含的所有标记的最小外接矩形的范围。
  602 + * @return {BMap.Bounds} 计算出的范围。
  603 + */
  604 + Cluster.prototype.getBounds = function() {
  605 + var bounds = new BMap.Bounds(this._center,this._center);
  606 + for (var i = 0, marker; marker = this._markers[i]; i++) {
  607 + bounds.extend(marker.getPosition());
  608 + }
  609 + return bounds;
  610 + };
  611 +
  612 + /**
  613 + * 获取该聚合的落脚点。
  614 + * @return {BMap.Point} 该聚合的落脚点。
  615 + */
  616 + Cluster.prototype.getCenter = function() {
  617 + return this._center;
  618 + };
  619 +
  620 +})();
src/main/resources/static/pages/mapmonitor/real/plugins/TextIconOverlay.js 0 → 100644
  1 +/**
  2 + * @fileoverview 此类表示地图上的一个覆盖物,该覆盖物由文字和图标组成,从Overlay继承。
  3 + * 主入口类是<a href="symbols/BMapLib.TextIconOverlay.html">TextIconOverlay</a>,
  4 + * 基于Baidu Map API 1.2。
  5 + *
  6 + * @author Baidu Map Api Group
  7 + * @version 1.2
  8 + */
  9 +
  10 +
  11 + /**
  12 + * @namespace BMap的所有library类均放在BMapLib命名空间下
  13 + */
  14 +var BMapLib = window.BMapLib = BMapLib || {};
  15 +
  16 +(function () {
  17 +
  18 + /**
  19 + * 声明baidu包
  20 + */
  21 + var T,
  22 + baidu = T = baidu || {version: "1.3.8"};
  23 +
  24 + (function (){
  25 + //提出guid,防止在与老版本Tangram混用时
  26 + //在下一行错误的修改window[undefined]
  27 + baidu.guid = "$BAIDU$";
  28 +
  29 + //Tangram可能被放在闭包中
  30 + //一些页面级别唯一的属性,需要挂载在window[baidu.guid]上
  31 + window[baidu.guid] = window[baidu.guid] || {};
  32 +
  33 + /**
  34 + * @ignore
  35 + * @namespace baidu.dom 操作dom的方法。
  36 + */
  37 + baidu.dom = baidu.dom || {};
  38 +
  39 +
  40 + /**
  41 + * 从文档中获取指定的DOM元素
  42 + * @name baidu.dom.g
  43 + * @function
  44 + * @grammar baidu.dom.g(id)
  45 + * @param {string|HTMLElement} id 元素的id或DOM元素
  46 + * @shortcut g,T.G
  47 + * @meta standard
  48 + * @see baidu.dom.q
  49 + *
  50 + * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数
  51 + */
  52 + baidu.dom.g = function (id) {
  53 + if ('string' == typeof id || id instanceof String) {
  54 + return document.getElementById(id);
  55 + } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
  56 + return id;
  57 + }
  58 + return null;
  59 + };
  60 +
  61 + // 声明快捷方法
  62 + baidu.g = baidu.G = baidu.dom.g;
  63 +
  64 + /**
  65 + * 获取目标元素所属的document对象
  66 + * @name baidu.dom.getDocument
  67 + * @function
  68 + * @grammar baidu.dom.getDocument(element)
  69 + * @param {HTMLElement|string} element 目标元素或目标元素的id
  70 + * @meta standard
  71 + * @see baidu.dom.getWindow
  72 + *
  73 + * @returns {HTMLDocument} 目标元素所属的document对象
  74 + */
  75 + baidu.dom.getDocument = function (element) {
  76 + element = baidu.dom.g(element);
  77 + return element.nodeType == 9 ? element : element.ownerDocument || element.document;
  78 + };
  79 +
  80 + /**
  81 + * @ignore
  82 + * @namespace baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
  83 + */
  84 + baidu.lang = baidu.lang || {};
  85 +
  86 + /**
  87 + * 判断目标参数是否string类型或String对象
  88 + * @name baidu.lang.isString
  89 + * @function
  90 + * @grammar baidu.lang.isString(source)
  91 + * @param {Any} source 目标参数
  92 + * @shortcut isString
  93 + * @meta standard
  94 + * @see baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  95 + *
  96 + * @returns {boolean} 类型判断结果
  97 + */
  98 + baidu.lang.isString = function (source) {
  99 + return '[object String]' == Object.prototype.toString.call(source);
  100 + };
  101 +
  102 + // 声明快捷方法
  103 + baidu.isString = baidu.lang.isString;
  104 +
  105 + /**
  106 + * 从文档中获取指定的DOM元素
  107 + * **内部方法**
  108 + *
  109 + * @param {string|HTMLElement} id 元素的id或DOM元素
  110 + * @meta standard
  111 + * @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数
  112 + */
  113 + baidu.dom._g = function (id) {
  114 + if (baidu.lang.isString(id)) {
  115 + return document.getElementById(id);
  116 + }
  117 + return id;
  118 + };
  119 +
  120 + // 声明快捷方法
  121 + baidu._g = baidu.dom._g;
  122 +
  123 + /**
  124 + * @ignore
  125 + * @namespace baidu.browser 判断浏览器类型和特性的属性。
  126 + */
  127 + baidu.browser = baidu.browser || {};
  128 +
  129 + if (/msie (\d+\.\d)/i.test(navigator.userAgent)) {
  130 + //IE 8下,以documentMode为准
  131 + //在百度模板中,可能会有$,防止冲突,将$1 写成 \x241
  132 + /**
  133 + * 判断是否为ie浏览器
  134 + * @property ie ie版本号
  135 + * @grammar baidu.browser.ie
  136 + * @meta standard
  137 + * @shortcut ie
  138 + * @see baidu.browser.firefox,baidu.browser.safari,baidu.browser.opera,baidu.browser.chrome,baidu.browser.maxthon
  139 + */
  140 + baidu.browser.ie = baidu.ie = document.documentMode || + RegExp['\x241'];
  141 + }
  142 +
  143 + /**
  144 + * 获取目标元素的computed style值。如果元素的样式值不能被浏览器计算,则会返回空字符串(IE)
  145 + *
  146 + * @author berg
  147 + * @name baidu.dom.getComputedStyle
  148 + * @function
  149 + * @grammar baidu.dom.getComputedStyle(element, key)
  150 + * @param {HTMLElement|string} element 目标元素或目标元素的id
  151 + * @param {string} key 要获取的样式名
  152 + *
  153 + * @see baidu.dom.getStyle
  154 + *
  155 + * @returns {string} 目标元素的computed style值
  156 + */
  157 +
  158 + baidu.dom.getComputedStyle = function(element, key){
  159 + element = baidu.dom._g(element);
  160 + var doc = baidu.dom.getDocument(element),
  161 + styles;
  162 + if (doc.defaultView && doc.defaultView.getComputedStyle) {
  163 + styles = doc.defaultView.getComputedStyle(element, null);
  164 + if (styles) {
  165 + return styles[key] || styles.getPropertyValue(key);
  166 + }
  167 + }
  168 + return '';
  169 + };
  170 +
  171 + /**
  172 + * 提供给setStyle与getStyle使用
  173 + */
  174 + baidu.dom._styleFixer = baidu.dom._styleFixer || {};
  175 +
  176 + /**
  177 + * 提供给setStyle与getStyle使用
  178 + */
  179 + baidu.dom._styleFilter = baidu.dom._styleFilter || [];
  180 +
  181 + /**
  182 + * 为获取和设置样式的过滤器
  183 + * @private
  184 + * @meta standard
  185 + */
  186 + baidu.dom._styleFilter.filter = function (key, value, method) {
  187 + for (var i = 0, filters = baidu.dom._styleFilter, filter; filter = filters[i]; i++) {
  188 + if (filter = filter[method]) {
  189 + value = filter(key, value);
  190 + }
  191 + }
  192 + return value;
  193 + };
  194 +
  195 + /**
  196 + * @ignore
  197 + * @namespace baidu.string 操作字符串的方法。
  198 + */
  199 + baidu.string = baidu.string || {};
  200 +
  201 + /**
  202 + * 将目标字符串进行驼峰化处理
  203 + * @name baidu.string.toCamelCase
  204 + * @function
  205 + * @grammar baidu.string.toCamelCase(source)
  206 + * @param {string} source 目标字符串
  207 + * @remark
  208 + * 支持单词以“-_”分隔
  209 + * @meta standard
  210 + *
  211 + * @returns {string} 驼峰化处理后的字符串
  212 + */
  213 + baidu.string.toCamelCase = function (source) {
  214 + //提前判断,提高getStyle等的效率 thanks xianwei
  215 + if (source.indexOf('-') < 0 && source.indexOf('_') < 0) {
  216 + return source;
  217 + }
  218 + return source.replace(/[-_][^-_]/g, function (match) {
  219 + return match.charAt(1).toUpperCase();
  220 + });
  221 + };
  222 +
  223 + /**
  224 + * 获取目标元素的样式值
  225 + * @name baidu.dom.getStyle
  226 + * @function
  227 + * @grammar baidu.dom.getStyle(element, key)
  228 + * @param {HTMLElement|string} element 目标元素或目标元素的id
  229 + * @param {string} key 要获取的样式名
  230 + * @remark
  231 + *
  232 + * 为了精简代码,本模块默认不对任何浏览器返回值进行归一化处理(如使用getStyle时,不同浏览器下可能返回rgb颜色或hex颜色),也不会修复浏览器的bug和差异性(如设置IE的float属性叫styleFloat,firefox则是cssFloat)。<br />
  233 + * baidu.dom._styleFixer和baidu.dom._styleFilter可以为本模块提供支持。<br />
  234 + * 其中_styleFilter能对颜色和px进行归一化处理,_styleFixer能对display,float,opacity,textOverflow的浏览器兼容性bug进行处理。
  235 + * @shortcut getStyle
  236 + * @meta standard
  237 + * @see baidu.dom.setStyle,baidu.dom.setStyles, baidu.dom.getComputedStyle
  238 + *
  239 + * @returns {string} 目标元素的样式值
  240 + */
  241 + baidu.dom.getStyle = function (element, key) {
  242 + var dom = baidu.dom;
  243 +
  244 + element = dom.g(element);
  245 + key = baidu.string.toCamelCase(key);
  246 + //computed style, then cascaded style, then explicitly set style.
  247 + var value = element.style[key] ||
  248 + (element.currentStyle ? element.currentStyle[key] : "") ||
  249 + dom.getComputedStyle(element, key);
  250 +
  251 + // 在取不到值的时候,用fixer进行修正
  252 + if (!value) {
  253 + var fixer = dom._styleFixer[key];
  254 + if(fixer){
  255 + value = fixer.get ? fixer.get(element) : baidu.dom.getStyle(element, fixer);
  256 + }
  257 + }
  258 +
  259 + /* 检查结果过滤器 */
  260 + if (fixer = dom._styleFilter) {
  261 + value = fixer.filter(key, value, 'get');
  262 + }
  263 +
  264 + return value;
  265 + };
  266 +
  267 + // 声明快捷方法
  268 + baidu.getStyle = baidu.dom.getStyle;
  269 +
  270 +
  271 + if (/opera\/(\d+\.\d)/i.test(navigator.userAgent)) {
  272 + /**
  273 + * 判断是否为opera浏览器
  274 + * @property opera opera版本号
  275 + * @grammar baidu.browser.opera
  276 + * @meta standard
  277 + * @see baidu.browser.ie,baidu.browser.firefox,baidu.browser.safari,baidu.browser.chrome
  278 + */
  279 + baidu.browser.opera = + RegExp['\x241'];
  280 + }
  281 +
  282 + /**
  283 + * 判断是否为webkit内核
  284 + * @property isWebkit
  285 + * @grammar baidu.browser.isWebkit
  286 + * @meta standard
  287 + * @see baidu.browser.isGecko
  288 + */
  289 + baidu.browser.isWebkit = /webkit/i.test(navigator.userAgent);
  290 +
  291 + /**
  292 + * 判断是否为gecko内核
  293 + * @property isGecko
  294 + * @grammar baidu.browser.isGecko
  295 + * @meta standard
  296 + * @see baidu.browser.isWebkit
  297 + */
  298 + baidu.browser.isGecko = /gecko/i.test(navigator.userAgent) && !/like gecko/i.test(navigator.userAgent);
  299 +
  300 + /**
  301 + * 判断是否严格标准的渲染模式
  302 + * @property isStrict
  303 + * @grammar baidu.browser.isStrict
  304 + * @meta standard
  305 + */
  306 + baidu.browser.isStrict = document.compatMode == "CSS1Compat";
  307 +
  308 + /**
  309 + * 获取目标元素相对于整个文档左上角的位置
  310 + * @name baidu.dom.getPosition
  311 + * @function
  312 + * @grammar baidu.dom.getPosition(element)
  313 + * @param {HTMLElement|string} element 目标元素或目标元素的id
  314 + * @meta standard
  315 + *
  316 + * @returns {Object} 目标元素的位置,键值为top和left的Object。
  317 + */
  318 + baidu.dom.getPosition = function (element) {
  319 + element = baidu.dom.g(element);
  320 + var doc = baidu.dom.getDocument(element),
  321 + browser = baidu.browser,
  322 + getStyle = baidu.dom.getStyle,
  323 + // Gecko 1.9版本以下用getBoxObjectFor计算位置
  324 + // 但是某些情况下是有bug的
  325 + // 对于这些有bug的情况
  326 + // 使用递归查找的方式
  327 + BUGGY_GECKO_BOX_OBJECT = browser.isGecko > 0 &&
  328 + doc.getBoxObjectFor &&
  329 + getStyle(element, 'position') == 'absolute' &&
  330 + (element.style.top === '' || element.style.left === ''),
  331 + pos = {"left":0,"top":0},
  332 + viewport = (browser.ie && !browser.isStrict) ? doc.body : doc.documentElement,
  333 + parent,
  334 + box;
  335 +
  336 + if(element == viewport){
  337 + return pos;
  338 + }
  339 +
  340 + if(element.getBoundingClientRect){ // IE and Gecko 1.9+
  341 +
  342 + //当HTML或者BODY有border width时, 原生的getBoundingClientRect返回值是不符合预期的
  343 + //考虑到通常情况下 HTML和BODY的border只会设成0px,所以忽略该问题.
  344 + box = element.getBoundingClientRect();
  345 +
  346 + pos.left = Math.floor(box.left) + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft);
  347 + pos.top = Math.floor(box.top) + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop);
  348 +
  349 + // IE会给HTML元素添加一个border,默认是medium(2px)
  350 + // 但是在IE 6 7 的怪异模式下,可以被html { border: 0; } 这条css规则覆盖
  351 + // 在IE7的标准模式下,border永远是2px,这个值通过clientLeft 和 clientTop取得
  352 + // 但是。。。在IE 6 7的怪异模式,如果用户使用css覆盖了默认的medium
  353 + // clientTop和clientLeft不会更新
  354 + pos.left -= doc.documentElement.clientLeft;
  355 + pos.top -= doc.documentElement.clientTop;
  356 +
  357 + var htmlDom = doc.body,
  358 + // 在这里,不使用element.style.borderLeftWidth,只有computedStyle是可信的
  359 + htmlBorderLeftWidth = parseInt(getStyle(htmlDom, 'borderLeftWidth')),
  360 + htmlBorderTopWidth = parseInt(getStyle(htmlDom, 'borderTopWidth'));
  361 + if(browser.ie && !browser.isStrict){
  362 + pos.left -= isNaN(htmlBorderLeftWidth) ? 2 : htmlBorderLeftWidth;
  363 + pos.top -= isNaN(htmlBorderTopWidth) ? 2 : htmlBorderTopWidth;
  364 + }
  365 + } else {
  366 + // safari/opera/firefox
  367 + parent = element;
  368 +
  369 + do {
  370 + pos.left += parent.offsetLeft;
  371 + pos.top += parent.offsetTop;
  372 +
  373 + // safari里面,如果遍历到了一个fixed的元素,后面的offset都不准了
  374 + if (browser.isWebkit > 0 && getStyle(parent, 'position') == 'fixed') {
  375 + pos.left += doc.body.scrollLeft;
  376 + pos.top += doc.body.scrollTop;
  377 + break;
  378 + }
  379 +
  380 + parent = parent.offsetParent;
  381 + } while (parent && parent != element);
  382 +
  383 + // 对body offsetTop的修正
  384 + if(browser.opera > 0 || (browser.isWebkit > 0 && getStyle(element, 'position') == 'absolute')){
  385 + pos.top -= doc.body.offsetTop;
  386 + }
  387 +
  388 + // 计算除了body的scroll
  389 + parent = element.offsetParent;
  390 + while (parent && parent != doc.body) {
  391 + pos.left -= parent.scrollLeft;
  392 + // see https://bugs.opera.com/show_bug.cgi?id=249965
  393 + if (!browser.opera || parent.tagName != 'TR') {
  394 + pos.top -= parent.scrollTop;
  395 + }
  396 + parent = parent.offsetParent;
  397 + }
  398 + }
  399 +
  400 + return pos;
  401 + };
  402 +
  403 + /**
  404 + * @ignore
  405 + * @namespace baidu.event 屏蔽浏览器差异性的事件封装。
  406 + * @property target 事件的触发元素
  407 + * @property pageX 鼠标事件的鼠标x坐标
  408 + * @property pageY 鼠标事件的鼠标y坐标
  409 + * @property keyCode 键盘事件的键值
  410 + */
  411 + baidu.event = baidu.event || {};
  412 +
  413 + /**
  414 + * 事件监听器的存储表
  415 + * @private
  416 + * @meta standard
  417 + */
  418 + baidu.event._listeners = baidu.event._listeners || [];
  419 +
  420 + /**
  421 + * 为目标元素添加事件监听器
  422 + * @name baidu.event.on
  423 + * @function
  424 + * @grammar baidu.event.on(element, type, listener)
  425 + * @param {HTMLElement|string|window} element 目标元素或目标元素id
  426 + * @param {string} type 事件类型
  427 + * @param {Function} listener 需要添加的监听器
  428 + * @remark
  429 + *
  430 + 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
  431 + 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败
  432 +
  433 + * @shortcut on
  434 + * @meta standard
  435 + * @see baidu.event.un
  436 + *
  437 + * @returns {HTMLElement|window} 目标元素
  438 + */
  439 + baidu.event.on = function (element, type, listener) {
  440 + type = type.replace(/^on/i, '');
  441 + element = baidu.dom._g(element);
  442 +
  443 + var realListener = function (ev) {
  444 + // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
  445 + // 2. element是为了修正this
  446 + listener.call(element, ev);
  447 + },
  448 + lis = baidu.event._listeners,
  449 + filter = baidu.event._eventFilter,
  450 + afterFilter,
  451 + realType = type;
  452 + type = type.toLowerCase();
  453 + // filter过滤
  454 + if(filter && filter[type]){
  455 + afterFilter = filter[type](element, type, realListener);
  456 + realType = afterFilter.type;
  457 + realListener = afterFilter.listener;
  458 + }
  459 +
  460 + // 事件监听器挂载
  461 + if (element.addEventListener) {
  462 + element.addEventListener(realType, realListener, false);
  463 + } else if (element.attachEvent) {
  464 + element.attachEvent('on' + realType, realListener);
  465 + }
  466 +
  467 + // 将监听器存储到数组中
  468 + lis[lis.length] = [element, type, listener, realListener, realType];
  469 + return element;
  470 + };
  471 +
  472 + // 声明快捷方法
  473 + baidu.on = baidu.event.on;
  474 +
  475 + /**
  476 + * 返回一个当前页面的唯一标识字符串。
  477 + * @name baidu.lang.guid
  478 + * @function
  479 + * @grammar baidu.lang.guid()
  480 + * @version 1.1.1
  481 + * @meta standard
  482 + *
  483 + * @returns {String} 当前页面的唯一标识字符串
  484 + */
  485 +
  486 + (function(){
  487 + //不直接使用window,可以提高3倍左右性能
  488 + var guid = window[baidu.guid];
  489 +
  490 + baidu.lang.guid = function() {
  491 + return "TANGRAM__" + (guid._counter ++).toString(36);
  492 + };
  493 +
  494 + guid._counter = guid._counter || 1;
  495 + })();
  496 +
  497 + /**
  498 + * 所有类的实例的容器
  499 + * key为每个实例的guid
  500 + * @meta standard
  501 + */
  502 +
  503 + window[baidu.guid]._instances = window[baidu.guid]._instances || {};
  504 +
  505 + /**
  506 + * 判断目标参数是否为function或Function实例
  507 + * @name baidu.lang.isFunction
  508 + * @function
  509 + * @grammar baidu.lang.isFunction(source)
  510 + * @param {Any} source 目标参数
  511 + * @version 1.2
  512 + * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  513 + * @meta standard
  514 + * @returns {boolean} 类型判断结果
  515 + */
  516 + baidu.lang.isFunction = function (source) {
  517 + // chrome下,'function' == typeof /a/ 为true.
  518 + return '[object Function]' == Object.prototype.toString.call(source);
  519 + };
  520 +
  521 + /**
  522 + *
  523 + * @ignore
  524 + * @class Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。
  525 + * @name baidu.lang.Class
  526 + * @grammar baidu.lang.Class(guid)
  527 + * @param {string} guid 对象的唯一标识
  528 + * @meta standard
  529 + * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。
  530 + * @meta standard
  531 + * @see baidu.lang.inherits,baidu.lang.Event
  532 + */
  533 + baidu.lang.Class = function(guid) {
  534 + this.guid = guid || baidu.lang.guid();
  535 + window[baidu.guid]._instances[this.guid] = this;
  536 + };
  537 + window[baidu.guid]._instances = window[baidu.guid]._instances || {};
  538 +
  539 + /**
  540 + * 释放对象所持有的资源,主要是自定义事件。
  541 + * @name dispose
  542 + * @grammar obj.dispose()
  543 + */
  544 + baidu.lang.Class.prototype.dispose = function(){
  545 + delete window[baidu.guid]._instances[this.guid];
  546 +
  547 + for(var property in this){
  548 + if (!baidu.lang.isFunction(this[property])) {
  549 + delete this[property];
  550 + }
  551 + }
  552 + this.disposed = true;
  553 + };
  554 +
  555 + /**
  556 + * 重载了默认的toString方法,使得返回信息更加准确一些。
  557 + * @return {string} 对象的String表示形式
  558 + */
  559 + baidu.lang.Class.prototype.toString = function(){
  560 + return "[object " + (this._className || "Object" ) + "]";
  561 + };
  562 +
  563 + /**
  564 + * @ignore
  565 + * @class 自定义的事件对象。
  566 + * @name baidu.lang.Event
  567 + * @grammar baidu.lang.Event(type[, target])
  568 + * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。
  569 + * @param {Object} [target]触发事件的对象
  570 + * @meta standard
  571 + * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。
  572 + * @meta standard
  573 + * @see baidu.lang.Class
  574 + */
  575 + baidu.lang.Event = function (type, target) {
  576 + this.type = type;
  577 + this.returnValue = true;
  578 + this.target = target || null;
  579 + this.currentTarget = null;
  580 + };
  581 +
  582 + /**
  583 + * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  584 + * @grammar obj.addEventListener(type, handler[, key])
  585 + * @param {string} type 自定义事件的名称
  586 + * @param {Function} handler 自定义事件被触发时应该调用的回调函数
  587 + * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。
  588 + * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。
  589 + */
  590 + baidu.lang.Class.prototype.addEventListener = function (type, handler, key) {
  591 + if (!baidu.lang.isFunction(handler)) {
  592 + return;
  593 + }
  594 +
  595 + !this.__listeners && (this.__listeners = {});
  596 +
  597 + var t = this.__listeners, id;
  598 + if (typeof key == "string" && key) {
  599 + if (/[^\w\-]/.test(key)) {
  600 + throw("nonstandard key:" + key);
  601 + } else {
  602 + handler.hashCode = key;
  603 + id = key;
  604 + }
  605 + }
  606 + type.indexOf("on") != 0 && (type = "on" + type);
  607 +
  608 + typeof t[type] != "object" && (t[type] = {});
  609 + id = id || baidu.lang.guid();
  610 + handler.hashCode = id;
  611 + t[type][id] = handler;
  612 + };
  613 +
  614 + /**
  615 + * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  616 + * @grammar obj.removeEventListener(type, handler)
  617 + * @param {string} type 事件类型
  618 + * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key
  619 + * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。
  620 + */
  621 + baidu.lang.Class.prototype.removeEventListener = function (type, handler) {
  622 + if (typeof handler != "undefined") {
  623 + if ( (baidu.lang.isFunction(handler) && ! (handler = handler.hashCode))
  624 + || (! baidu.lang.isString(handler))
  625 + ){
  626 + return;
  627 + }
  628 + }
  629 +
  630 + !this.__listeners && (this.__listeners = {});
  631 +
  632 + type.indexOf("on") != 0 && (type = "on" + type);
  633 +
  634 + var t = this.__listeners;
  635 + if (!t[type]) {
  636 + return;
  637 + }
  638 + if (typeof handler != "undefined") {
  639 + t[type][handler] && delete t[type][handler];
  640 + } else {
  641 + for(var guid in t[type]){
  642 + delete t[type][guid];
  643 + }
  644 + }
  645 + };
  646 +
  647 + /**
  648 + * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  649 + * @grammar obj.dispatchEvent(event, options)
  650 + * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持)
  651 + * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持)
  652 + * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。例如:<br>
  653 + myobj.onMyEvent = function(){}<br>
  654 + myobj.addEventListener("onMyEvent", function(){});
  655 + */
  656 + baidu.lang.Class.prototype.dispatchEvent = function (event, options) {
  657 + if (baidu.lang.isString(event)) {
  658 + event = new baidu.lang.Event(event);
  659 + }
  660 + !this.__listeners && (this.__listeners = {});
  661 +
  662 + // 20100603 添加本方法的第二个参数,将 options extend到event中去传递
  663 + options = options || {};
  664 + for (var i in options) {
  665 + event[i] = options[i];
  666 + }
  667 +
  668 + var i, t = this.__listeners, p = event.type;
  669 + event.target = event.target || this;
  670 + event.currentTarget = this;
  671 +
  672 + p.indexOf("on") != 0 && (p = "on" + p);
  673 +
  674 + baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments);
  675 +
  676 + if (typeof t[p] == "object") {
  677 + for (i in t[p]) {
  678 + t[p][i].apply(this, arguments);
  679 + }
  680 + }
  681 + return event.returnValue;
  682 + };
  683 +
  684 +
  685 + baidu.lang.inherits = function (subClass, superClass, className) {
  686 + var key, proto,
  687 + selfProps = subClass.prototype,
  688 + clazz = new Function();
  689 +
  690 + clazz.prototype = superClass.prototype;
  691 + proto = subClass.prototype = new clazz();
  692 + for (key in selfProps) {
  693 + proto[key] = selfProps[key];
  694 + }
  695 + subClass.prototype.constructor = subClass;
  696 + subClass.superClass = superClass.prototype;
  697 +
  698 + // 类名标识,兼容Class的toString,基本没用
  699 + if ("string" == typeof className) {
  700 + proto._className = className;
  701 + }
  702 + };
  703 + // 声明快捷方法
  704 + baidu.inherits = baidu.lang.inherits;
  705 + })();
  706 +
  707 +
  708 + /**
  709 +
  710 + * 图片的路径
  711 +
  712 + * @private
  713 + * @type {String}
  714 +
  715 + */
  716 + var _IMAGE_PATH = 'http://api.map.baidu.com/library/TextIconOverlay/1.2/src/images/m';
  717 +
  718 + /**
  719 +
  720 + * 图片的后缀名
  721 +
  722 + * @private
  723 + * @type {String}
  724 +
  725 + */
  726 + var _IMAGE_EXTENSION = 'png';
  727 +
  728 + /**
  729 + *@exports TextIconOverlay as BMapLib.TextIconOverlay
  730 + */
  731 + var TextIconOverlay =
  732 + /**
  733 + * TextIconOverlay
  734 + * @class 此类表示地图上的一个覆盖物,该覆盖物由文字和图标组成,从Overlay继承。文字通常是数字(0-9)或字母(A-Z ),而文字与图标之间有一定的映射关系。
  735 + *该覆盖物适用于以下类似的场景:需要在地图上添加一系列覆盖物,这些覆盖物之间用不同的图标和文字来区分,文字可能表示了该覆盖物的某一属性值,根据该文字和一定的映射关系,自动匹配相应颜色和大小的图标。
  736 + *
  737 + *@constructor
  738 + *@param {Point} position 表示一个经纬度坐标位置。
  739 + *@param {String} text 表示该覆盖物显示的文字信息。
  740 + *@param {Json Object} options 可选参数,可选项包括:<br />
  741 + *"<b>styles</b>":{Array<IconStyle>} 一组图标风格。单个图表风格包括以下几个属性:<br />
  742 + * url {String} 图片的url地址。(必选)<br />
  743 + * size {Size} 图片的大小。(必选)<br />
  744 + * anchor {Size} 图标定位在地图上的位置相对于图标左上角的偏移值,默认偏移值为图标的中心位置。(可选)<br />
  745 + * offset {Size} 图片相对于可视区域的偏移值,此功能的作用等同于CSS中的background-position属性。(可选)<br />
  746 + * textSize {Number} 文字的大小。(可选,默认10)<br />
  747 + * textColor {String} 文字的颜色。(可选,默认black)<br />
  748 + */
  749 + BMapLib.TextIconOverlay = function(position, text, options){
  750 + this._position = position;
  751 + this._text = text;
  752 + this._options = options || {};
  753 + this._styles = this._options['styles'] || [];
  754 + (!this._styles.length) && this._setupDefaultStyles();
  755 + };
  756 +
  757 + T.lang.inherits(TextIconOverlay, BMap.Overlay, "TextIconOverlay");
  758 +
  759 + TextIconOverlay.prototype._setupDefaultStyles = function(){
  760 + var sizes = [53, 56, 66, 78, 90];
  761 + for(var i = 0, size; size = sizes[i]; i++){
  762 + this._styles.push({
  763 + url:_IMAGE_PATH + i + '.' + _IMAGE_EXTENSION,
  764 + size: new BMap.Size(size, size)
  765 + });
  766 + }//for循环的简洁写法
  767 + };
  768 +
  769 + /**
  770 + *继承Overlay的intialize方法,自定义覆盖物时必须。
  771 + *@param {Map} map BMap.Map的实例化对象。
  772 + *@return {HTMLElement} 返回覆盖物对应的HTML元素。
  773 + */
  774 + TextIconOverlay.prototype.initialize = function(map){
  775 + this._map = map;
  776 +
  777 + this._domElement = document.createElement('div');
  778 + this._updateCss();
  779 + this._updateText();
  780 + this._updatePosition();
  781 +
  782 + this._bind();
  783 +
  784 + this._map.getPanes().markerMouseTarget.appendChild(this._domElement);
  785 + return this._domElement;
  786 + };
  787 +
  788 + /**
  789 + *继承Overlay的draw方法,自定义覆盖物时必须。
  790 + *@return 无返回值。
  791 + */
  792 + TextIconOverlay.prototype.draw = function(){
  793 + this._map && this._updatePosition();
  794 + };
  795 +
  796 + /**
  797 + *获取该覆盖物上的文字。
  798 + *@return {String} 该覆盖物上的文字。
  799 + */
  800 + TextIconOverlay.prototype.getText = function(){
  801 + return this._text;
  802 + };
  803 +
  804 + /**
  805 + *设置该覆盖物上的文字。
  806 + *@param {String} text 要设置的文字,通常是字母A-Z或数字0-9。
  807 + *@return 无返回值。
  808 + */
  809 + TextIconOverlay.prototype.setText = function(text){
  810 + if(text && (!this._text || (this._text.toString() != text.toString()))){
  811 + this._text = text;
  812 + this._updateText();
  813 + this._updateCss();
  814 + this._updatePosition();
  815 + }
  816 + };
  817 +
  818 + /**
  819 + *获取该覆盖物的位置。
  820 + *@return {Point} 该覆盖物的经纬度坐标。
  821 + */
  822 + TextIconOverlay.prototype.getPosition = function () {
  823 + return this._position;
  824 + };
  825 +
  826 + /**
  827 + *设置该覆盖物的位置。
  828 + *@param {Point} position 要设置的经纬度坐标。
  829 + *@return 无返回值。
  830 + */
  831 + TextIconOverlay.prototype.setPosition = function (position) {
  832 + if(position && (!this._position || !this._position.equals(position))){
  833 + this._position = position;
  834 + this._updatePosition();
  835 + }
  836 + };
  837 +
  838 + /**
  839 + *由文字信息获取风格数组的对应索引值。
  840 + *内部默认的对应函数为文字转换为数字除以10的结果,比如文字8返回索引0,文字25返回索引2.
  841 + *如果需要自定义映射关系,请覆盖该函数。
  842 + *@param {String} text 文字。
  843 + *@param {Array<IconStyle>} styles 一组图标风格。
  844 + *@return {Number} 对应的索引值。
  845 + */
  846 + TextIconOverlay.prototype.getStyleByText = function(text, styles){
  847 + var count = parseInt(text);
  848 + var index = parseInt(count / 10);
  849 + index = Math.max(0, index);
  850 + index = Math.min(index, styles.length - 1);
  851 + return styles[index];
  852 + }
  853 +
  854 + /**
  855 + *更新相应的CSS。
  856 + *@return 无返回值。
  857 + */
  858 + TextIconOverlay.prototype._updateCss = function(){
  859 + var style = this.getStyleByText(this._text, this._styles);
  860 + this._domElement.style.cssText = this._buildCssText(style);
  861 + };
  862 +
  863 + /**
  864 + *更新覆盖物的显示文字。
  865 + *@return 无返回值。
  866 + */
  867 + TextIconOverlay.prototype._updateText = function(){
  868 + if (this._domElement) {
  869 + this._domElement.innerHTML = this._text;
  870 + }
  871 + };
  872 +
  873 + /**
  874 + *调整覆盖物在地图上的位置更新覆盖物的显示文字。
  875 + *@return 无返回值。
  876 + */
  877 + TextIconOverlay.prototype._updatePosition = function(){
  878 + if (this._domElement && this._position) {
  879 + var style = this._domElement.style;
  880 + var pixelPosition= this._map.pointToOverlayPixel(this._position);
  881 + pixelPosition.x -= Math.ceil(parseInt(style.width) / 2);
  882 + pixelPosition.y -= Math.ceil(parseInt(style.height) / 2);
  883 + style.left = pixelPosition.x + "px";
  884 + style.top = pixelPosition.y + "px";
  885 + }
  886 + };
  887 +
  888 + /**
  889 + * 为该覆盖物的HTML元素构建CSS
  890 + * @param {IconStyle} 一个图标的风格。
  891 + * @return {String} 构建完成的CSSTEXT。
  892 + */
  893 + TextIconOverlay.prototype._buildCssText = function(style) {
  894 + //根据style来确定一些默认值
  895 + var url = style['url'];
  896 + var size = style['size'];
  897 + var anchor = style['anchor'];
  898 + var offset = style['offset'];
  899 + var textColor = style['textColor'] || 'black';
  900 + var textSize = style['textSize'] || 10;
  901 +
  902 + var csstext = [];
  903 + if (T.browser["ie"] < 7) {
  904 + csstext.push('filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(' +
  905 + 'sizingMethod=scale,src="' + url + '");');
  906 + } else {
  907 + csstext.push('background-image:url(' + url + ');');
  908 + var backgroundPosition = '0 0';
  909 + (offset instanceof BMap.Size) && (backgroundPosition = offset.width + 'px' + ' ' + offset.height + 'px');
  910 + csstext.push('background-position:' + backgroundPosition + ';');
  911 + }
  912 +
  913 + if (size instanceof BMap.Size){
  914 + if (anchor instanceof BMap.Size) {
  915 + if (anchor.height > 0 && anchor.height < size.height) {
  916 + csstext.push('height:' + (size.height - anchor.height) + 'px; padding-top:' + anchor.height + 'px;');
  917 + }
  918 + if(anchor.width > 0 && anchor.width < size.width){
  919 + csstext.push('width:' + (size.width - anchor.width) + 'px; padding-left:' + anchor.width + 'px;');
  920 + }
  921 + } else {
  922 + csstext.push('height:' + size.height + 'px; line-height:' + size.height + 'px;');
  923 + csstext.push('width:' + size.width + 'px; text-align:center;');
  924 + }
  925 + }
  926 +
  927 + csstext.push('cursor:pointer; color:' + textColor + '; position:absolute; font-size:' +
  928 + textSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
  929 + return csstext.join('');
  930 + };
  931 +
  932 +
  933 + /**
  934 +
  935 + * 当鼠标点击该覆盖物时会触发该事件
  936 +
  937 + * @name TextIconOverlay#click
  938 +
  939 + * @event
  940 +
  941 + * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  942 +
  943 + * <br />"<b>type</b> : {String} 事件类型
  944 +
  945 + * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
  946 +
  947 + *
  948 +
  949 + */
  950 +
  951 + /**
  952 +
  953 + * 当鼠标进入该覆盖物区域时会触发该事件
  954 +
  955 + * @name TextIconOverlay#mouseover
  956 +
  957 + * @event
  958 + * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  959 +
  960 + * <br />"<b>type</b> : {String} 事件类型
  961 +
  962 + * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
  963 +
  964 + * <br />"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象
  965 +
  966 + * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象
  967 +
  968 + *
  969 +
  970 + * @example <b>参考示例:</b><br />
  971 +
  972 + * myTextIconOverlay.addEventListener("mouseover", function(e) { alert(e.point); });
  973 +
  974 + */
  975 +
  976 + /**
  977 +
  978 + * 当鼠标离开该覆盖物区域时会触发该事件
  979 +
  980 + * @name TextIconOverlay#mouseout
  981 +
  982 + * @event
  983 +
  984 + * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  985 +
  986 + * <br />"<b>type</b> : {String} 事件类型
  987 +
  988 + * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
  989 +
  990 + * <br />"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象
  991 +
  992 + * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象
  993 +
  994 + *
  995 +
  996 + * @example <b>参考示例:</b><br />
  997 +
  998 + * myTextIconOverlay.addEventListener("mouseout", function(e) { alert(e.point); });
  999 +
  1000 + */
  1001 +
  1002 +
  1003 + /**
  1004 + * 为该覆盖物绑定一系列事件
  1005 + * 当前支持click mouseover mouseout
  1006 + * @return 无返回值。
  1007 + */
  1008 + TextIconOverlay.prototype._bind = function(){
  1009 + if (!this._domElement){
  1010 + return;
  1011 + }
  1012 +
  1013 + var me = this;
  1014 + var map = this._map;
  1015 +
  1016 + var BaseEvent = T.lang.Event;
  1017 + function eventExtend(e, be){
  1018 + var elem = e.srcElement || e.target;
  1019 + var x = e.clientX || e.pageX;
  1020 + var y = e.clientY || e.pageY;
  1021 + if (e && be && x && y && elem){
  1022 + var offset = T.dom.getPosition(map.getContainer());
  1023 + be.pixel = new BMap.Pixel(x - offset.left, y - offset.top);
  1024 + be.point = map.pixelToPoint(be.pixel);
  1025 + }
  1026 + return be;
  1027 + }//给事件参数增加pixel和point两个值
  1028 +
  1029 + T.event.on(this._domElement,"mouseover", function(e){
  1030 + me.dispatchEvent(eventExtend(e, new BaseEvent("onmouseover")));
  1031 + });
  1032 + T.event.on(this._domElement,"mouseout", function(e){
  1033 + me.dispatchEvent(eventExtend(e, new BaseEvent("onmouseout")));
  1034 + });
  1035 + T.event.on(this._domElement,"click", function(e){
  1036 + me.dispatchEvent(eventExtend(e, new BaseEvent("onclick")));
  1037 + });
  1038 + };
  1039 +
  1040 +})();
0 \ No newline at end of file 1041 \ No newline at end of file
src/main/resources/static/pages/mapmonitor/real/real.html
@@ -31,10 +31,12 @@ @@ -31,10 +31,12 @@
31 <div class="item" data-click="search"> 31 <div class="item" data-click="search">
32 <i class="fa fa-search"></i> &nbsp;搜索 32 <i class="fa fa-search"></i> &nbsp;搜索
33 </div> 33 </div>
34 - <div class="item" data-click="notice"> 34 + <!-- <div class="item" data-click="notice"> -->
  35 + <div class="item" >
35 <i class="fa fa-bell-o"></i> &nbsp;通知 36 <i class="fa fa-bell-o"></i> &nbsp;通知
36 </div> 37 </div>
37 - <div class="item" data-click="playBack"> 38 + <!-- <div class="item" data-click="playBack"> -->
  39 + <div class="item" >
38 <i class="fa fa-history"></i> &nbsp;回放 40 <i class="fa fa-history"></i> &nbsp;回放
39 </div> 41 </div>
40 </div> 42 </div>
@@ -44,6 +46,8 @@ @@ -44,6 +46,8 @@
44 46
45 <div id="temps"></div> 47 <div id="temps"></div>
46 48
  49 +<script src="/pages/mapmonitor/real/plugins/TextIconOverlay.js"></script>
  50 +<script src="/pages/mapmonitor/real/plugins/MarkerClusterer.js"></script>
47 <script src="/pages/mapmonitor/real/js/map_platform.js"></script> 51 <script src="/pages/mapmonitor/real/js/map_platform.js"></script>
48 <script src="/pages/mapmonitor/real/js/vehicle.js"></script> 52 <script src="/pages/mapmonitor/real/js/vehicle.js"></script>
49 <script src="/pages/mapmonitor/real/js/search.js"></script> 53 <script src="/pages/mapmonitor/real/js/search.js"></script>
src/main/resources/static/pages/mapmonitor/real/temps/vehicle.html
1 <script id="vehicle_panel_temp" type="text/html"> 1 <script id="vehicle_panel_temp" type="text/html">
2 <div class="gps-line-wrap"> 2 <div class="gps-line-wrap">
3 {{each list as line i}} 3 {{each list as line i}}
4 -<a data-toggle="collapse" href="#collapse_{{line.lineCode}}" aria-expanded="true" style="text-decoration:none"> 4 +<a data-toggle="collapse" href="#collapse_{{line.lineCode}}" style="text-decoration:none" class="collapseLink">
5 <p class="head" > 5 <p class="head" >
6 {{line.name}} 6 {{line.name}}
7 <span class="icon rotate"> 7 <span class="icon rotate">
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <!-- 14 <!--
15 <div class="vehicle-item offline" > 15 <div class="vehicle-item offline" >
16 <div class="text"> 16 <div class="text">
17 - <span><i class="fa fa-circle"></i> &nbsp;W1B-397</span> 17 + <span class="goto-marker" data-deviceId="{{deviceId}}"><i class="fa fa-circle"></i> &nbsp;W1B-397</span>
18 &nbsp;&nbsp;&nbsp; 18 &nbsp;&nbsp;&nbsp;
19 已掉线10分钟 19 已掉线10分钟
20 </div> 20 </div>
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 {{each list as gpsObj i}} 31 {{each list as gpsObj i}}
32 <div class="vehicle-item online" > 32 <div class="vehicle-item online" >
33 <div class="text"> 33 <div class="text">
34 - <span class="nbbm"><i class="fa fa-circle"></i> &nbsp;{{gpsObj.nbbm}}</span> 34 + <span class="nbbm goto-marker" data-deviceId="{{gpsObj.deviceId}}"><i class="fa fa-circle"></i> &nbsp;{{gpsObj.nbbm}}</span>
35 &nbsp;&nbsp;&nbsp; 35 &nbsp;&nbsp;&nbsp;
36 <span style="font-size: 13px;">{{gpsObj.stationName}}</span> 36 <span style="font-size: 13px;">{{gpsObj.stationName}}</span>
37 </div> 37 </div>
@@ -40,4 +40,56 @@ @@ -40,4 +40,56 @@
40 </div> 40 </div>
41 </div> 41 </div>
42 {{/each}} 42 {{/each}}
  43 +{{if list.length == 0}}
  44 +<div class="map-gps-empty">没有相关数据</div>
  45 +{{/if}}
  46 +</script>
  47 +
  48 +<!-- gps信息窗口 -->
  49 +<script id="gps_info_win_temp" type="text/html">
  50 +<div class="gps_info_win">
  51 +<h4 style="color:#0E6AF9;">
  52 +{{if stationName!=null}}
  53 + {{stationName}}
  54 +{{else}}
  55 + 未知站点
  56 +{{/if}}
  57 +
  58 +{{if upDown == 0}}
  59 +(上行)
  60 +{{else if upDown == 1}}
  61 +(下行)
  62 +{{else}}
  63 +(未知的上下行)
  64 +{{/if}}
  65 +</h4>
  66 +<h4 style="color: #0E6AF9;margin: 5px 0 5px 0;">
  67 + {{nbbm}}
  68 +</h4>
  69 +<p>
  70 +路牌:
  71 +{{if currSch!=null}}
  72 + {{currSch.lpName}}
  73 +{{/if}}
  74 +</p>
  75 +<p>
  76 +营运状态:{{if state==0}}营运{{else}}非营运{{/if}}
  77 +</p>
  78 +<p>
  79 +在线状态:在线
  80 +</p>
  81 +<p>速度:{{speed}}</p>
  82 +<hr>
  83 +<p class="banci-info">
  84 + 开往
  85 + {{if currSch!=null}}{{currSch.zdzName}}{{/if}}
  86 + ( 预计 未知时间 到达 )
  87 +</p>
  88 +<p class="banci-info">
  89 +{{if nextSch!=null}}
  90 + 下一班{{nextSch.qdzName}} {{nextSch.fcsj}} 发车
  91 +{{/if}}
  92 +</p>
  93 +<a href="javascript:void(0)" style="color:#006600;font-size:12px;">轨迹回放</a>
  94 +</div>
43 </script> 95 </script>
44 \ No newline at end of file 96 \ No newline at end of file