Commit ec1ef1a51a646f3e4320a26454520978988897fd
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 | 38 | public Map<String, Object> outgoAdjust(@RequestParam Long id, @RequestParam String remarks,@RequestParam String dfsj){ |
| 39 | 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 | 92 | @Column(name = "update_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") |
| 93 | 93 | private Date updateDate; |
| 94 | 94 | |
| 95 | - /** | |
| 96 | - * 实际发车时间 | |
| 97 | - */ | |
| 95 | + /** 实际发车时间*/ | |
| 98 | 96 | private String fcsjActual; |
| 99 | - /** | |
| 100 | - * 实际终点时间 | |
| 101 | - */ | |
| 97 | + /**实际终点时间 */ | |
| 102 | 98 | private String zdsjActual; |
| 103 | 99 | |
| 104 | - /** | |
| 105 | - * 班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 | |
| 106 | - * | |
| 107 | - */ | |
| 100 | + /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */ | |
| 108 | 101 | private int status; |
| 109 | 102 | |
| 110 | - /** | |
| 111 | - * 是否误点 | |
| 112 | - */ | |
| 103 | + /** 是否误点*/ | |
| 113 | 104 | private boolean isLate; |
| 114 | 105 | |
| 115 | - /** | |
| 116 | - * 实际里程 | |
| 117 | - */ | |
| 106 | + /**实际里程*/ | |
| 118 | 107 | private Float realMileage; |
| 119 | 108 | |
| 120 | - /** | |
| 121 | - * 备注 | |
| 122 | - */ | |
| 109 | + /** 备注*/ | |
| 123 | 110 | private String remarks; |
| 124 | 111 | |
| 125 | - /** | |
| 126 | - * 待发时间(格式 HH:mm) | |
| 127 | - */ | |
| 112 | + /**待发时间(格式 HH:mm) */ | |
| 128 | 113 | private String dfsj; |
| 129 | 114 | |
| 130 | - /** | |
| 131 | - * 发车时间戳 | |
| 132 | - */ | |
| 115 | + /**待发时间戳 */ | |
| 116 | + @Transient | |
| 117 | + private Long dfsjT; | |
| 118 | + | |
| 119 | + /** 发车时间戳*/ | |
| 133 | 120 | @Transient |
| 134 | 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 | 131 | public Long getId() { |
| 137 | 132 | return id; |
| 138 | 133 | } |
| ... | ... | @@ -444,4 +439,12 @@ public class ScheduleRealInfo { |
| 444 | 439 | public void setFcsjT(Long fcsjT) { |
| 445 | 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 | 56 | item.setDfsj(item.getFcsj()); |
| 57 | 57 | //发车时间戳 |
| 58 | 58 | item.setFcsjT(sdf2.parse(dateStr + " " + item.getFcsj()).getTime()); |
| 59 | + item.setDfsjT(item.getFcsjT()); | |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | 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 | 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 | 42 | public static Map<Long, ScheduleRealInfo> pkSchedulMap; |
| ... | ... | @@ -45,6 +50,7 @@ public class ScheduleBuffer { |
| 45 | 50 | schedulListMap = ArrayListMultimap.create(); |
| 46 | 51 | pkSchedulMap = new HashMap<>(); |
| 47 | 52 | persistentList = new LinkedList<>(); |
| 53 | + vehLinkedMap = new HashMap<>(); | |
| 48 | 54 | } |
| 49 | 55 | |
| 50 | 56 | public static int init(List<ScheduleRealInfo> list){ |
| ... | ... | @@ -59,9 +65,17 @@ public class ScheduleBuffer { |
| 59 | 65 | } |
| 60 | 66 | }); |
| 61 | 67 | |
| 68 | + String zbh; | |
| 62 | 69 | for(ScheduleRealInfo schedul : list){ |
| 63 | 70 | schedulListMap.put(schedul.getXlBm(), schedul); |
| 64 | 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 | 80 | }catch(Exception e){ |
| 67 | 81 | logger.error("缓存排班数据失败...", e); | ... | ... |
src/main/java/com/bsth/service/realcontrol/ScheduleRealInfoService.java
| ... | ... | @@ -15,4 +15,6 @@ public interface ScheduleRealInfoService extends BaseService<ScheduleRealInfo, L |
| 15 | 15 | |
| 16 | 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 | 1 | package com.bsth.service.realcontrol.impl; |
| 2 | 2 | |
| 3 | +import java.text.SimpleDateFormat; | |
| 4 | +import java.util.ArrayList; | |
| 3 | 5 | import java.util.Collection; |
| 6 | +import java.util.Date; | |
| 4 | 7 | import java.util.HashMap; |
| 5 | 8 | import java.util.List; |
| 6 | 9 | import java.util.Map; |
| ... | ... | @@ -29,18 +32,19 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl<ScheduleRealInf |
| 29 | 32 | |
| 30 | 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 | 39 | @Override |
| 33 | 40 | public Map<String, Collection<ScheduleRealInfo>> findByLines(String lines) { |
| 34 | 41 | List<String> lineList = Lists.newArrayList(Splitter.on(',').trimResults().omitEmptyStrings().split(lines)); |
| 35 | - List<ScheduleRealInfo> list = scheduleRealInfoRepository.findByLines(lineList); | |
| 36 | 42 | |
| 37 | - //按线路编码分组 | |
| 38 | 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 | 48 | return mMap.asMap(); |
| 45 | 49 | } |
| 46 | 50 | |
| ... | ... | @@ -50,18 +54,85 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl<ScheduleRealInf |
| 50 | 54 | try{ |
| 51 | 55 | |
| 52 | 56 | ScheduleRealInfo schedule = ScheduleBuffer.pkSchedulMap.get(id); |
| 57 | + schedule.setDfsjT(sdfMinute.parse(sdfMonth.format(new Date()) + " " + dfsj).getTime()); | |
| 53 | 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 | 61 | ScheduleBuffer.persistentList.add(schedule); |
| 61 | 62 | |
| 62 | 63 | map.put("status", ResponseCode.SUCCESS); |
| 63 | 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 | 136 | }catch(Exception e){ |
| 66 | 137 | logger.error("", e); |
| 67 | 138 | map.put("status", ResponseCode.ERROR); | ... | ... |
src/main/java/com/bsth/vehicle/directive/buffer/DirectiveBuffer.java
src/main/java/com/bsth/vehicle/directive/controller/DirectiveController.java
| ... | ... | @@ -29,7 +29,7 @@ public class DirectiveController { |
| 29 | 29 | * @Description: TODO(60协议短语下发) |
| 30 | 30 | * @throws |
| 31 | 31 | */ |
| 32 | - @RequestMapping(value = "/phrase", method = RequestMethod.GET) | |
| 32 | + @RequestMapping(value = "/phrase", method = RequestMethod.POST) | |
| 33 | 33 | public int send60Phrase(@RequestParam String nbbm, @RequestParam String text){ |
| 34 | 34 | return directiveService.send60Phrase(nbbm, text); |
| 35 | 35 | } |
| ... | ... | @@ -42,7 +42,7 @@ public class DirectiveController { |
| 42 | 42 | * @param @param lineId 新线路编码 |
| 43 | 43 | * @throws |
| 44 | 44 | */ |
| 45 | - @RequestMapping(value = "/lineChnage", method = RequestMethod.GET) | |
| 45 | + @RequestMapping(value = "/lineChnage", method = RequestMethod.POST) | |
| 46 | 46 | public int lineChange(@RequestParam String nbbm, @RequestParam Integer lineId){ |
| 47 | 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<Directive, Integer> im |
| 46 | 46 | |
| 47 | 47 | @Override |
| 48 | 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 | 61 | int code = postJson(JSON.toJSONString(directive)); |
| ... | ... | @@ -90,14 +99,14 @@ public class DirectiveServiceImpl extends BaseServiceImpl<Directive, Integer> im |
| 90 | 99 | change.setTimestamp(t); |
| 91 | 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 | 105 | lineChangeRepository.save(change); |
| 97 | 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 | 110 | return code; |
| 102 | 111 | } |
| 103 | 112 | |
| ... | ... | @@ -105,13 +114,16 @@ public class DirectiveServiceImpl extends BaseServiceImpl<Directive, Integer> im |
| 105 | 114 | public Directive create60Data(String nbbm, String text, DispatchInstruct dispatchInstruct){ |
| 106 | 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 | 122 | Short company = Short.parseShort(CommonMapped.vehicCompanyMap.get(nbbm)); |
| 110 | 123 | if(null == deviceId){ |
| 111 | 124 | logger.error("没有设备号对照的车辆:" + nbbm); |
| 112 | 125 | return null; |
| 113 | - } | |
| 114 | - | |
| 126 | + }*/ | |
| 115 | 127 | GpsRealData gpsData = gpsRealDataBuffer.findOneByDeviceId(deviceId); |
| 116 | 128 | if(null == gpsData){ |
| 117 | 129 | logger.error("没有找到gps对照,无法确认营运状态和上下行:" + nbbm); |
| ... | ... | @@ -154,6 +166,7 @@ public class DirectiveServiceImpl extends BaseServiceImpl<Directive, Integer> im |
| 154 | 166 | int code = -1; |
| 155 | 167 | try{ |
| 156 | 168 | httpClient = HttpClients.createDefault(); |
| 169 | + | |
| 157 | 170 | HttpPost post = new HttpPost(Consts.SEND_DIRECTIVE_URL); |
| 158 | 171 | |
| 159 | 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 | 3 | import java.util.ArrayList; |
| 4 | 4 | import java.util.HashMap; |
| 5 | 5 | import java.util.Iterator; |
| 6 | +import java.util.LinkedList; | |
| 6 | 7 | import java.util.List; |
| 7 | 8 | import java.util.Map; |
| 8 | 9 | import java.util.Set; |
| ... | ... | @@ -11,6 +12,8 @@ import org.slf4j.Logger; |
| 11 | 12 | import org.slf4j.LoggerFactory; |
| 12 | 13 | import org.springframework.stereotype.Component; |
| 13 | 14 | |
| 15 | +import com.bsth.entity.realcontrol.ScheduleRealInfo; | |
| 16 | +import com.bsth.service.realcontrol.ScheduleBuffer; | |
| 14 | 17 | import com.bsth.vehicle.common.CommonMapped; |
| 15 | 18 | import com.bsth.vehicle.gpsdata.entity.GpsRealData; |
| 16 | 19 | import com.google.common.collect.ArrayListMultimap; |
| ... | ... | @@ -129,11 +132,24 @@ public class GpsRealDataBuffer { |
| 129 | 132 | |
| 130 | 133 | //写入车辆自编号 |
| 131 | 134 | String nbbm; |
| 135 | + LinkedList<ScheduleRealInfo> linkedList; | |
| 136 | + int size; | |
| 132 | 137 | for(GpsRealData gpsData : list){ |
| 133 | 138 | nbbm = CommonMapped.vehicDeviceBiMap.get(gpsData.getDeviceId()); |
| 134 | 139 | if(null != nbbm){ |
| 135 | 140 | gpsData.setNbbm(nbbm); |
| 136 | 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 | 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 | 51 | |
| 52 | 52 | //站点名称 |
| 53 | 53 | private String stationName; |
| 54 | + | |
| 55 | + //当前班次ID | |
| 56 | + private Long currSchId; | |
| 57 | + | |
| 58 | + //下一个班次ID | |
| 59 | + private Long nextSchId; | |
| 54 | 60 | |
| 55 | 61 | public Integer getCompanyCode() { |
| 56 | 62 | return companyCode; |
| ... | ... | @@ -147,6 +153,22 @@ public class GpsRealData { |
| 147 | 153 | public void setUpDown(Integer upDown) { |
| 148 | 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 | 173 | public String getNbbm() { |
| 152 | 174 | return nbbm; | ... | ... |
src/main/resources/static/pages/control/line/css/lineControl.css
| ... | ... | @@ -382,7 +382,7 @@ body{ |
| 382 | 382 | |
| 383 | 383 | /* svg 样式 */ |
| 384 | 384 | .line_chart svg{ |
| 385 | - height: calc(100% - 40px); | |
| 385 | + height: 100% ; | |
| 386 | 386 | margin: 0; |
| 387 | 387 | z-index: 1; |
| 388 | 388 | position: absolute; |
| ... | ... | @@ -763,7 +763,7 @@ height: 400px; |
| 763 | 763 | #top-tabs-wrap .tab-content{ |
| 764 | 764 | height: calc(100% - 42px); |
| 765 | 765 | padding: 3px 1px; |
| 766 | - overflow-y: auto; | |
| 766 | + /* overflow-y: auto; */ | |
| 767 | 767 | } |
| 768 | 768 | |
| 769 | 769 | #top-tabs-wrap .tab-content .tab-pane{ |
| ... | ... | @@ -864,7 +864,7 @@ height: 400px; |
| 864 | 864 | width: 9%; |
| 865 | 865 | } |
| 866 | 866 | .pb-table tr td:nth-child(5){ |
| 867 | - /* width: 15%; */ | |
| 867 | + width: 15%; | |
| 868 | 868 | } |
| 869 | 869 | .pb-table tr td:nth-child(6){ |
| 870 | 870 | width: 10%; |
| ... | ... | @@ -958,9 +958,9 @@ height: 400px; |
| 958 | 958 | .pic-panel span.tl-zzzx:before{ |
| 959 | 959 | content: "正在执行"; |
| 960 | 960 | } |
| 961 | -/* .pic-panel span.tl-sf-f:before{ | |
| 961 | +.pic-panel span.tl-sf-f:before{ | |
| 962 | 962 | content: "实发(放)"; |
| 963 | -} */ | |
| 963 | +} | |
| 964 | 964 | .pic-panel span.tl-xxfc:before{ |
| 965 | 965 | content: "消息发出"; |
| 966 | 966 | } |
| ... | ... | @@ -991,8 +991,10 @@ height: 400px; |
| 991 | 991 | .tl-zzzx{ |
| 992 | 992 | background: #96F396; |
| 993 | 993 | } |
| 994 | -/* .tl-sf-f{ | |
| 995 | -} */ | |
| 994 | +.tl-sf-f{ | |
| 995 | + background: gray; | |
| 996 | + color: white; | |
| 997 | +} | |
| 996 | 998 | .tl-xxfc{ |
| 997 | 999 | background: #AE9CCE; |
| 998 | 1000 | color: white; |
| ... | ... | @@ -1472,4 +1474,41 @@ height: 400px; |
| 1472 | 1474 | |
| 1473 | 1475 | .form-custom hr{ |
| 1474 | 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 | 1515 | \ No newline at end of file | ... | ... |
src/main/resources/static/pages/control/line/index.html
| ... | ... | @@ -151,7 +151,7 @@ |
| 151 | 151 | </li> |
| 152 | 152 | <li class="menu-separator"></li> |
| 153 | 153 | <li class="menu-item" > |
| 154 | - <button type="button" class="menu-btn"> | |
| 154 | + <button type="button" class="menu-btn" data-method="directiveRepeat"> | |
| 155 | 155 | <i class="fa fa-bell-o"></i> |
| 156 | 156 | <span class="menu-text">指令重发</span> |
| 157 | 157 | </button> |
| ... | ... | @@ -171,9 +171,11 @@ |
| 171 | 171 | <script src="/pages/control/line/js/alone.js"></script> |
| 172 | 172 | <script src="/pages/control/line/js/main.js"></script> |
| 173 | 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 | 179 | $(function() { |
| 178 | 180 | //加载模板文件 |
| 179 | 181 | getTemp('temps/home_tp.html'); | ... | ... |
src/main/resources/static/pages/control/line/js/alone.js
| ... | ... | @@ -8,25 +8,34 @@ var _alone = (function(){ |
| 8 | 8 | ,downCode = '下行'; |
| 9 | 9 | |
| 10 | 10 | var aloneObject = { |
| 11 | - init: function(){ | |
| 11 | + init: function(cb){ | |
| 12 | 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 | 40 | $('.console-log .log-item-list').slimscroll({ |
| 32 | 41 | height: '100%' |
| ... | ... | @@ -40,36 +49,31 @@ var _alone = (function(){ |
| 40 | 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 | 58 | refreshSchedule: function(schedule){ |
| 53 | 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 | 79 | function splitDir(list){ |
| ... | ... | @@ -84,5 +88,9 @@ var _alone = (function(){ |
| 84 | 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 | 95 | return aloneObject; |
| 88 | 96 | })(); |
| 89 | 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 | 24 | getLineIds: function(){ |
| 25 | 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 | 42 | $get('/stationroute/all', {'line.lineCode_eq': lineId}, function(routes){ |
| 59 | 43 | var svgData = analyData(routes); |
| 60 | - | |
| 61 | - cb && cb(lineId, svgData, container); | |
| 44 | + cb && cb(lineId, svgData, container, width); | |
| 62 | 45 | }); |
| 63 | 46 | }, |
| 64 | 47 | //实时GPS定时刷新 |
| ... | ... | @@ -116,6 +99,7 @@ var _data = (function(){ |
| 116 | 99 | //初始化lineCodes |
| 117 | 100 | $.each(dataObject.getLines(), function(i, obj){ |
| 118 | 101 | lineCodes += (obj.lineCode + ','); |
| 102 | + lineMap[obj.lineCode] = obj; | |
| 119 | 103 | }); |
| 120 | 104 | lineCodes = lineCodes.substr(0, lineCodes.length - 1); |
| 121 | 105 | |
| ... | ... | @@ -130,11 +114,11 @@ var _data = (function(){ |
| 130 | 114 | }); |
| 131 | 115 | } |
| 132 | 116 | var upSort = function(a, b){ |
| 133 | - return a.outStationNmber - b.outStationNmber; | |
| 117 | + return a.stationRouteCode - b.stationRouteCode; | |
| 134 | 118 | } |
| 135 | 119 | |
| 136 | 120 | var downSort = function(a, b){ |
| 137 | - return b.outStationNmber - a.outStationNmber; | |
| 121 | + return b.stationRouteCode - a.stationRouteCode; | |
| 138 | 122 | } |
| 139 | 123 | |
| 140 | 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 | 8 | ,p = 112//上下行之间的间隔 132 |
| 9 | 9 | ,x = d3.scale.linear() |
| 10 | 10 | ,w |
| 11 | - ,lineSvgMapp = {} | |
| 11 | + ,homeSvgMapp = {} | |
| 12 | + ,aloneSvgMapp = {} | |
| 12 | 13 | ,lineStations = {} |
| 13 | 14 | ,seGps = {} //起终点gps信号; |
| 14 | 15 | |
| ... | ... | @@ -41,28 +42,39 @@ var drawSvg = (function(){ |
| 41 | 42 | var cutNbbm = function(nbbm){ |
| 42 | 43 | return nbbm.substr(nbbm.length - 3, nbbm.length); |
| 43 | 44 | } |
| 44 | - | |
| 45 | + | |
| 45 | 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 | 60 | if(!data || data.length == 0) |
| 48 | 61 | return; |
| 49 | 62 | |
| 63 | + mt = mtop; | |
| 50 | 64 | //起终点站 |
| 51 | 65 | $.each(data, function(){ |
| 52 | 66 | if(this.stationMark == 'B' || this.stationMark == 'E' ) |
| 53 | 67 | seGps[lineId + '_' + this.id[0]] = []; |
| 54 | 68 | }); |
| 55 | 69 | |
| 56 | - //w = $('.line_chart:first').width(); | |
| 57 | - w = $('#' + container).width(); | |
| 58 | 70 | var svg = d3.select('#' + container).append('svg') |
| 59 | 71 | .attr('width', w).attr('opacity', 0) |
| 60 | 72 | .attr('id', lineId); |
| 61 | 73 | |
| 62 | - lineSvgMapp[lineId] = svg; | |
| 74 | + | |
| 63 | 75 | lineStations[lineId] = data.slice(0); |
| 64 | 76 | //抽站 |
| 65 | - cleanStation(data); | |
| 77 | + cleanStation(w, data); | |
| 66 | 78 | var dLen = data.length; |
| 67 | 79 | |
| 68 | 80 | x.range([ 60 , w - 15]).domain([ 0, dLen]); |
| ... | ... | @@ -153,63 +165,15 @@ var drawSvg = (function(){ |
| 153 | 165 | return $(this).attr('class')?null:this; |
| 154 | 166 | }).remove(); |
| 155 | 167 | |
| 168 | + return svg; | |
| 156 | 169 | }, |
| 157 | 170 | |
| 158 | 171 | //画出GPS点 |
| 159 | 172 | drawVehicle: function(gpsArray){ |
| 160 | 173 | |
| 161 | 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 | 179 | //画出起终点GPS信号 |
| ... | ... | @@ -221,7 +185,7 @@ var drawSvg = (function(){ |
| 221 | 185 | ,x = parseInt(e.attr('cx')) |
| 222 | 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 | 190 | var gs = svg.append('g').classed({'start': e.attr('class').indexOf('start') != -1, 'park': true}) |
| 227 | 191 | .selectAll('g').data(seGps[eid]).enter().append('g'); |
| ... | ... | @@ -240,12 +204,14 @@ var drawSvg = (function(){ |
| 240 | 204 | return y + i * 27 + 17; |
| 241 | 205 | }) |
| 242 | 206 | .text(function(d){return cutNbbm(d.nbbm)}); |
| 207 | + | |
| 208 | + _tooltip.initStartAndEndGPS(gs); | |
| 243 | 209 | } |
| 244 | 210 | } |
| 245 | 211 | |
| 246 | 212 | /** |
| 247 | 213 | * 堆叠多个GPS信号 |
| 248 | - | |
| 214 | + */ | |
| 249 | 215 | $.each($('.station-gps-container'), function(i, multiGps){ |
| 250 | 216 | var tArray = $(multiGps).find('g') |
| 251 | 217 | ,updowm = $(multiGps).attr('updown') |
| ... | ... | @@ -268,7 +234,7 @@ var drawSvg = (function(){ |
| 268 | 234 | |
| 269 | 235 | $(tArray[1]).css('transform', 'translate(-15px, '+ translateY +'px)'); |
| 270 | 236 | } |
| 271 | - }); */ | |
| 237 | + }); | |
| 272 | 238 | |
| 273 | 239 | /* function drawNumber(multiGps, num, that, start, end){ |
| 274 | 240 | var circle = $('#' + $(multiGps).attr('for')) |
| ... | ... | @@ -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 | 311 | function drawPath(svg, data,updown, noclear){ |
| 293 | 312 | svg.append('g').selectAll('path') |
| 294 | 313 | .data(data.slice(0, data.length - 1)).enter().append('path') |
| ... | ... | @@ -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 | 354 | ,dLen = data.length; |
| 336 | 355 | if(ms < dLen){ |
| 337 | 356 | var end; | ... | ... |
src/main/resources/static/pages/control/line/js/main.js
| ... | ... | @@ -26,24 +26,16 @@ |
| 26 | 26 | |
| 27 | 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 | 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 | 41 | $('.line_chart .top .top-remark').slimscroll({ |
| ... | ... | @@ -52,11 +44,24 @@ |
| 52 | 44 | |
| 53 | 45 | //模拟图GPS刷新事件 |
| 54 | 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 | 65 | /* setTimeout(function(){ |
| 61 | 66 | homeObject.refreshGps(function(add, update){ |
| 62 | 67 | //将新增的点画到模拟图上 |
| ... | ... | @@ -80,14 +85,14 @@ setTimeout(function(){ |
| 80 | 85 | $('#top-tabs-wrap .nav-tabs').append(topTabs); |
| 81 | 86 | $('#top-tabs-wrap .tab-content').append(tabPanels); |
| 82 | 87 | |
| 83 | - //初始化主页 | |
| 84 | - homeObject.init(); | |
| 85 | - | |
| 86 | 88 | //加载地图页数据 |
| 87 | 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 | 97 | }, 200) |
| 93 | 98 | |
| ... | ... | @@ -99,4 +104,16 @@ setTimeout(function(){ |
| 99 | 104 | } |
| 100 | 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 | 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 | 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 | 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 | 45 | outgoAdjust: function(schedul){ |
| 46 | 46 | var index = layer.open({ |
| ... | ... | @@ -68,9 +68,9 @@ var _menu = (function() { |
| 68 | 68 | //计划烂班 |
| 69 | 69 | planDestroy: function(schedul){ |
| 70 | 70 | var data = {item: schedul, array : _data.getSchedulByVeh(schedul.clZbh)} |
| 71 | - layer.open({ | |
| 71 | + var index = layer.open({ | |
| 72 | 72 | type: 1, |
| 73 | - area: ['370px', '605px'], | |
| 73 | + area: ['370px', '645px'], | |
| 74 | 74 | maxmin: true, |
| 75 | 75 | skin:'layui-layer-molv', |
| 76 | 76 | content: template('plan_destroy_body_temp', data), |
| ... | ... | @@ -78,10 +78,17 @@ var _menu = (function() { |
| 78 | 78 | title: '计划烂班设置', |
| 79 | 79 | success: function(){ |
| 80 | 80 | var f = $('#planDestroyForm'); |
| 81 | + //红色 | |
| 81 | 82 | $('.icheck', f).iCheck({ |
| 82 | 83 | checkboxClass: 'icheckbox_square-red', |
| 83 | 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 | 93 | var cont = $('.custom-check-box', f) |
| 87 | 94 | ,checked = $('.icheck:checked', f); |
| ... | ... | @@ -91,13 +98,51 @@ var _menu = (function() { |
| 91 | 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+'] ' | |
| 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 | 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 | 12 | |
| 13 | 13 | var position = {}; |
| 14 | 14 | var lastDom; |
| 15 | - //toolTip hover | |
| 16 | 15 | tip.hover(function() { |
| 17 | 16 | clearTime(); |
| 18 | 17 | $(this).addClass('hover'); |
| ... | ... | @@ -55,18 +54,24 @@ var _tooltip = (function(){ |
| 55 | 54 | .addClass('tooltip-modal'); |
| 56 | 55 | } |
| 57 | 56 | |
| 57 | + var lineIds; | |
| 58 | + setTimeout(function(){ | |
| 59 | + lineIds = _data.getLineIds(); | |
| 60 | + }, 1000); | |
| 61 | + | |
| 58 | 62 | var tooltipObject = { |
| 59 | 63 | //正常 GPS toolTip |
| 60 | 64 | initGpsTip: function(e){ |
| 61 | - var lineIds = _data.getLineIds(); | |
| 62 | - | |
| 63 | 65 | e.on('mouseover', function(d){ |
| 64 | 66 | clearTime(); |
| 65 | 67 | var offset = $(this).offset() |
| 66 | 68 | ,y = $(this).attr('y'); |
| 67 | 69 | |
| 70 | + //获取线路名称 | |
| 68 | 71 | if(!d.lineName) |
| 69 | 72 | d.lineName = lineIds[d.lineId]; |
| 73 | + | |
| 74 | + d.fromNow = moment(d.timestamp).fromNow(); | |
| 70 | 75 | var html = template('tooltip_gps_temp', d); |
| 71 | 76 | showTip({ |
| 72 | 77 | top: offset.top - 45, |
| ... | ... | @@ -74,25 +79,55 @@ var _tooltip = (function(){ |
| 74 | 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 | 109 | function showTip(op){ |
| 92 | 110 | tip.css('top', op.top) |
| 93 | 111 | .css('left', op.left) |
| 94 | 112 | .html(op.container) |
| 95 | 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 | 133 | function clearTime(){ | ... | ... |
src/main/resources/static/pages/control/line/temps/alone_tp.html
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | <div class="col-md-6 panel-wrap"> |
| 7 | 7 | <div class="_panel"> |
| 8 | 8 | <div class="_head" style="color: #2765A7;"> |
| 9 | - 上行/上海火车站北广场 | |
| 9 | + 上行/{{startStationName}} | |
| 10 | 10 | </div> |
| 11 | 11 | <table class="table table-striped table-bordered table-advance pb-table head"> |
| 12 | 12 | <thead> |
| ... | ... | @@ -25,26 +25,11 @@ |
| 25 | 25 | </thead> |
| 26 | 26 | </table> |
| 27 | 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 | 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 | 32 | </tr> |
| 47 | - {{/each}} | |
| 48 | 33 | </tbody> |
| 49 | 34 | </table> |
| 50 | 35 | </div> |
| ... | ... | @@ -53,7 +38,7 @@ |
| 53 | 38 | <div class="col-md-6 panel-wrap"> |
| 54 | 39 | <div class="_panel"> |
| 55 | 40 | <div class="_head" style="color: #C92121;"> |
| 56 | - 下行/华戴路川环南路 | |
| 41 | + 下行/{{endStationName}} | |
| 57 | 42 | </div> |
| 58 | 43 | <table class="table table-striped table-bordered table-advance pb-table head"> |
| 59 | 44 | <thead> |
| ... | ... | @@ -72,26 +57,11 @@ |
| 72 | 57 | </thead> |
| 73 | 58 | </table> |
| 74 | 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 | 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 | 64 | </tr> |
| 94 | - {{/each}} | |
| 95 | 65 | </tbody> |
| 96 | 66 | </table> |
| 97 | 67 | </div> |
| ... | ... | @@ -102,16 +72,17 @@ |
| 102 | 72 | <div class="pic-panel"> |
| 103 | 73 | 图例: |
| 104 | 74 | <span class="tl-yzx"></span> |
| 105 | - <span class="tl-wzx"></span> | |
| 75 | + <!--<span class="tl-wzx"></span>--> | |
| 106 | 76 | <span class="tl-wd"></span> |
| 107 | 77 | <span class="tl-qrlb"></span> |
| 108 | 78 | <span class="tl-zzzx"></span> |
| 109 | - | |
| 110 | - <span class="tl-sf-f"></span> | |
| 79 | + <!-- <span class="tl-sf-f"></span> --> | |
| 80 | + | |
| 81 | + | |
| 111 | 82 | <span class="tl-xxfc"></span> |
| 112 | 83 | <span class="tl-xxsd"></span> |
| 113 | 84 | <span class="tl-xxrd"></span> |
| 114 | - <span class="tl-fcpqr"></span> | |
| 85 | + <!--<span class="tl-fcpqr"></span>--> | |
| 115 | 86 | </div> |
| 116 | 87 | </div> |
| 117 | 88 | |
| ... | ... | @@ -167,12 +138,39 @@ |
| 167 | 138 | </div> |
| 168 | 139 | |
| 169 | 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 | 143 | </div> |
| 173 | 144 | </div> |
| 174 | 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 | 175 | <script id="tg_question_info_temp" type="text/html"> |
| 178 | 176 | <table class="tg-question-table"> |
| ... | ... | @@ -313,7 +311,7 @@ |
| 313 | 311 | {{each array as obj i}} |
| 314 | 312 | <label> |
| 315 | 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 | 315 | </label> |
| 318 | 316 | {{/each}} |
| 319 | 317 | </div> |
| ... | ... | @@ -325,7 +323,7 @@ |
| 325 | 323 | <div class="item full"> |
| 326 | 324 | <span class="item-label" style="width: 80px;line-height: 32px;">调整说明:</span> |
| 327 | 325 | <br> |
| 328 | - <select class="form-control" style="width: 100%;"> | |
| 326 | + <select class="form-control" style="width: 100%;" name="reason"> | |
| 329 | 327 | <option value="配车">配车</option> |
| 330 | 328 | <option value="保养">保养</option> |
| 331 | 329 | <option value="故障">故障</option> |
| ... | ... | @@ -346,10 +344,22 @@ |
| 346 | 344 | |
| 347 | 345 | <div class="form-custom-row"> |
| 348 | 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 | 348 | </div> |
| 351 | 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 | + <i class="fa fa-question-circle" style="cursor: pointer;" data-toggle="tooltip" data-placement="left" title="当前首个烂班为起点,调整后续班次间隔"></i> | |
| 359 | + </div> | |
| 360 | + </div> | |
| 361 | + | |
| 362 | + | |
| 353 | 363 | <hr> |
| 354 | 364 | <div class="form-custom-footer"> |
| 355 | 365 | <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> 确 定 </button> | ... | ... |
src/main/resources/static/pages/control/line/temps/home_table_tp.html
| ... | ... | @@ -3,11 +3,22 @@ |
| 3 | 3 | {{each list as obj i}} |
| 4 | 4 | <tr> |
| 5 | 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 | 22 | </tr> |
| 12 | 23 | {{/each}} |
| 13 | 24 | </script> |
| 14 | 25 | \ No newline at end of file | ... | ... |
src/main/resources/static/pages/control/line/temps/home_tp.html
| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | <div class="col-lg-2 "> |
| 9 | 9 | |
| 10 | 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 | 12 | <div class="help_text dropdown"> |
| 13 | 13 | <span class=" blue dropdown-toggle col_hide_1440" |
| 14 | 14 | data-toggle="dropdown" aria-expanded="true" |
| ... | ... | @@ -30,21 +30,20 @@ |
| 30 | 30 | <table class="table table-striped table-bordered table-advance" |
| 31 | 31 | style="table-layout: fixed;"> |
| 32 | 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 | 39 | </colgroup> |
| 40 | 40 | <thead> |
| 41 | 41 | <tr> |
| 42 | 42 | <th>车辆编码</th> |
| 43 | - <th>终点距离</th> | |
| 44 | - <th class="col_hide_1680">终点时间</th> | |
| 45 | - <th>指令</th> | |
| 46 | - <th>速度</th> | |
| 47 | 43 | <th>路牌</th> |
| 44 | + <th>速度</th> | |
| 45 | + <th class="col_hide_1680">终点时间</th> | |
| 46 | + <th>下一班</th> | |
| 48 | 47 | </tr> |
| 49 | 48 | </thead> |
| 50 | 49 | </table> |
| ... | ... | @@ -53,12 +52,11 @@ |
| 53 | 52 | class="table table-striped table-bordered table-advance table-hover vehicDataTable" |
| 54 | 53 | style="table-layout: fixed;" id="tab_{{lineObj.lineCode}}_0"> |
| 55 | 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 | 60 | </colgroup> |
| 63 | 61 | <tbody></tbody> |
| 64 | 62 | </table> |
| ... | ... | @@ -75,7 +73,7 @@ |
| 75 | 73 | <div class="col-lg-2 down"> |
| 76 | 74 | |
| 77 | 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 | 77 | <div class="help_text dropdown"> |
| 80 | 78 | <span class=" blue dropdown-toggle col_hide_1440" |
| 81 | 79 | data-toggle="dropdown" aria-expanded="true" |
| ... | ... | @@ -93,21 +91,19 @@ |
| 93 | 91 | <table class="table table-striped table-bordered table-advance" |
| 94 | 92 | style="table-layout: fixed;"> |
| 95 | 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 | 99 | </colgroup> |
| 103 | 100 | <thead> |
| 104 | 101 | <tr> |
| 105 | 102 | <th>车辆编码</th> |
| 106 | - <th>终点距离</th> | |
| 107 | - <th class="col_hide_1680">终点时间</th> | |
| 108 | - <th>指令</th> | |
| 109 | - <th>速度</th> | |
| 110 | 103 | <th>路牌</th> |
| 104 | + <th>速度</th> | |
| 105 | + <th class="col_hide_1680">终点时间</th> | |
| 106 | + <th>下一班</th> | |
| 111 | 107 | </tr> |
| 112 | 108 | </thead> |
| 113 | 109 | </table> |
| ... | ... | @@ -116,11 +112,11 @@ |
| 116 | 112 | class="table table-striped table-bordered table-advance table-hover vehicDataTable" |
| 117 | 113 | style="table-layout: fixed;" id="tab_{{lineObj.lineCode}}_1"> |
| 118 | 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 | 121 | </colgroup> |
| 126 | 122 | <tbody> | ... | ... |
src/main/resources/static/pages/control/line/temps/tooltip_tp.html
| ... | ... | @@ -9,10 +9,41 @@ |
| 9 | 9 | <div><a href="javascript:;" data-for="station" class="tip_modal">{{stationName}}</a></div> |
| 10 | 10 | <div>速度:{{speed}}</div> |
| 11 | 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 | 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 | 47 | <div class="subtitle" style="margin-top: 8px;"> |
| 17 | 48 | <a href="javascript:;" data-for="map" class="tip_modal" data-lon={{lon}} data-lat={{lat}} data-nbbm={{nbbm}}> |
| 18 | 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 | 87 | |
| 88 | 88 | .mapRightWrap.vehicle{ |
| 89 | 89 | height: calc(100% - 110px); |
| 90 | + overflow: auto; | |
| 90 | 91 | } |
| 91 | 92 | |
| 92 | 93 | .mapRightWrap.search{ |
| ... | ... | @@ -567,4 +568,22 @@ html{ |
| 567 | 568 | background: #ddd; |
| 568 | 569 | color: #333333; |
| 569 | 570 | } |
| 570 | -/* GaoDe style end------- */ | |
| 571 | 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 | 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 | 20 | var REAL_BAIDU_TEXT = '百度地图', REAL_GAODE_TEXT = '高德地图'; |
| 16 | 21 | |
| 17 | 22 | // 中心点 (上海市浦东新区政府) |
| ... | ... | @@ -34,6 +39,14 @@ var realMap = (function() { |
| 34 | 39 | //百度API Key |
| 35 | 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 | 50 | var real_map = { |
| 38 | 51 | getMap: function(){ |
| 39 | 52 | return currentMap; |
| ... | ... | @@ -75,6 +88,10 @@ var realMap = (function() { |
| 75 | 88 | isVisible = true; |
| 76 | 89 | } |
| 77 | 90 | }); |
| 91 | + //百度路况控件自身关闭按钮 | |
| 92 | + $('.portlet-fullscreen').on('click', '.maplibTc .maplibTcClose', function(){ | |
| 93 | + isVisible = false; | |
| 94 | + }); | |
| 78 | 95 | |
| 79 | 96 | $('#tcWrap.maplibTc').addClass('animated bounceInLeft'); |
| 80 | 97 | $('.maplibTcBtn_deskTop.anchorTR').remove(); |
| ... | ... | @@ -143,9 +160,6 @@ var realMap = (function() { |
| 143 | 160 | cb && cb(); |
| 144 | 161 | }, |
| 145 | 162 | onPolylinesSet: function(pline){ |
| 146 | - //pline.setStrokeColor('#333'); | |
| 147 | - //console.log(pline.getStrokeColor()); | |
| 148 | - console.log(pline); | |
| 149 | 163 | cb && cb(); |
| 150 | 164 | }, |
| 151 | 165 | onGetBusLineComplete: function(line){ |
| ... | ... | @@ -156,19 +170,32 @@ var realMap = (function() { |
| 156 | 170 | }, |
| 157 | 171 | //将GPS信号画到地图上 |
| 158 | 172 | drawGpsMarker: function(gpsList){ |
| 173 | + markersMap = {}; | |
| 159 | 174 | var map = currentMap.map; |
| 175 | + var markerClusterer = new BMapLib.MarkerClusterer(map, {isAverangeCenter : true,minClusterSize : 3}); | |
| 160 | 176 | real_map.baidu.coordsConvert(gpsList, function(){ |
| 161 | - console.log(gpsList); | |
| 162 | 177 | //绘制车辆位置 |
| 163 | - var label; | |
| 178 | + var marker; | |
| 164 | 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 | 199 | coordsConvert: function(list, cb){ |
| 173 | 200 | if(list.length > 100) |
| 174 | 201 | list = list.slice(0, 100); |
| ... | ... | @@ -317,14 +344,6 @@ var realMap = (function() { |
| 317 | 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 | 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 | 396 | return real_map; |
| 352 | 397 | })(); |
| 353 | 398 | \ No newline at end of file | ... | ... |
src/main/resources/static/pages/mapmonitor/real/js/real.js
| ... | ... | @@ -39,8 +39,9 @@ |
| 39 | 39 | // 刷新 |
| 40 | 40 | return; |
| 41 | 41 | } |
| 42 | + var method = $(this).data('click'); | |
| 42 | 43 | |
| 43 | - if (playAnimation) | |
| 44 | + if (!method || playAnimation) | |
| 44 | 45 | return; |
| 45 | 46 | playAnimation = true; |
| 46 | 47 | |
| ... | ... | @@ -48,7 +49,7 @@ |
| 48 | 49 | $('.mapTools div.item.active').removeClass('active'); |
| 49 | 50 | $(this).addClass('active'); |
| 50 | 51 | |
| 51 | - toolsEvent[$(this).data('click')](); | |
| 52 | + toolsEvent[method](); | |
| 52 | 53 | }); |
| 53 | 54 | |
| 54 | 55 | var classzz = 'mapRightWrap z-depth-3 '; |
| ... | ... | @@ -65,8 +66,10 @@ |
| 65 | 66 | resetRotate(null, searchPanel.init); |
| 66 | 67 | }, |
| 67 | 68 | notice : function() { |
| 69 | + alert('notice'); | |
| 68 | 70 | }, |
| 69 | 71 | playBack : function() { |
| 72 | + alert('playBack'); | |
| 70 | 73 | }, |
| 71 | 74 | clearStyle : function() { |
| 72 | 75 | mrw.removeClass( | ... | ... |
src/main/resources/static/pages/mapmonitor/real/js/vehicle.js
| ... | ... | @@ -4,16 +4,15 @@ |
| 4 | 4 | |
| 5 | 5 | var vehiclePanel = (function() { |
| 6 | 6 | |
| 7 | - function getCurr(){ | |
| 7 | + function getCurrMap(){ | |
| 8 | 8 | return realMap[realMap.getMap().fName]; |
| 9 | 9 | } |
| 10 | 10 | var storage = window.localStorage; |
| 11 | 11 | |
| 12 | 12 | function closeAll(){ |
| 13 | - $('a[data-toggle=collapse]').collapse('hide'); | |
| 13 | + $('.mapRightWrap .collapse.in').collapse('hide'); | |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | - | |
| 17 | 16 | // 手风琴收拢 |
| 18 | 17 | $('.mapRightWrap').on('hide.bs.collapse', '.panel-collapse', function() { |
| 19 | 18 | $(this).prev().find('span.icon').addClass('rotate'); |
| ... | ... | @@ -23,27 +22,45 @@ var vehiclePanel = (function() { |
| 23 | 22 | $('.mapRightWrap').on('show.bs.collapse', '.panel-collapse', function() { |
| 24 | 23 | $(this).prev().find('span.icon').removeClass('rotate'); |
| 25 | 24 | var lineCode = $(this).data('line'); |
| 26 | - | |
| 27 | 25 | //收拢其他 |
| 28 | 26 | closeAll(); |
| 29 | - | |
| 30 | - //该线路的GPS点 | |
| 27 | + //过滤出该线路的GPS点 | |
| 31 | 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 | 35 | var htmlStr = template('vehicle_panel_collapse_temp', {list: showList}); |
| 44 | 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 | 64 | //GPS刷新事件 |
| 48 | 65 | var allGps = {}; |
| 49 | 66 | var lineGps = {}; |
| ... | ... | @@ -75,10 +92,10 @@ var vehiclePanel = (function() { |
| 75 | 92 | var htmlStr = template('vehicle_panel_temp', {list: lines}); |
| 76 | 93 | $('.mapRightWrap').html(htmlStr).addClass('vehicle'); |
| 77 | 94 | //滚动条 |
| 78 | - $('.gps-line-wrap').slimscroll({ | |
| 95 | + /*$('.gps-line-wrap').slimscroll({ | |
| 79 | 96 | height: '100%', |
| 80 | 97 | alwaysVisible: true |
| 81 | - }); | |
| 98 | + });*/ | |
| 82 | 99 | /*var line = {code: 10103, name: '119路'}; |
| 83 | 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 | 1041 | \ No newline at end of file | ... | ... |
src/main/resources/static/pages/mapmonitor/real/real.html
| ... | ... | @@ -31,10 +31,12 @@ |
| 31 | 31 | <div class="item" data-click="search"> |
| 32 | 32 | <i class="fa fa-search"></i> 搜索 |
| 33 | 33 | </div> |
| 34 | - <div class="item" data-click="notice"> | |
| 34 | + <!-- <div class="item" data-click="notice"> --> | |
| 35 | + <div class="item" > | |
| 35 | 36 | <i class="fa fa-bell-o"></i> 通知 |
| 36 | 37 | </div> |
| 37 | - <div class="item" data-click="playBack"> | |
| 38 | + <!-- <div class="item" data-click="playBack"> --> | |
| 39 | + <div class="item" > | |
| 38 | 40 | <i class="fa fa-history"></i> 回放 |
| 39 | 41 | </div> |
| 40 | 42 | </div> |
| ... | ... | @@ -44,6 +46,8 @@ |
| 44 | 46 | |
| 45 | 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 | 51 | <script src="/pages/mapmonitor/real/js/map_platform.js"></script> |
| 48 | 52 | <script src="/pages/mapmonitor/real/js/vehicle.js"></script> |
| 49 | 53 | <script src="/pages/mapmonitor/real/js/search.js"></script> | ... | ... |
src/main/resources/static/pages/mapmonitor/real/temps/vehicle.html
| 1 | 1 | <script id="vehicle_panel_temp" type="text/html"> |
| 2 | 2 | <div class="gps-line-wrap"> |
| 3 | 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 | 5 | <p class="head" > |
| 6 | 6 | {{line.name}} |
| 7 | 7 | <span class="icon rotate"> |
| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | <!-- |
| 15 | 15 | <div class="vehicle-item offline" > |
| 16 | 16 | <div class="text"> |
| 17 | - <span><i class="fa fa-circle"></i> W1B-397</span> | |
| 17 | + <span class="goto-marker" data-deviceId="{{deviceId}}"><i class="fa fa-circle"></i> W1B-397</span> | |
| 18 | 18 | |
| 19 | 19 | 已掉线10分钟 |
| 20 | 20 | </div> |
| ... | ... | @@ -31,7 +31,7 @@ |
| 31 | 31 | {{each list as gpsObj i}} |
| 32 | 32 | <div class="vehicle-item online" > |
| 33 | 33 | <div class="text"> |
| 34 | - <span class="nbbm"><i class="fa fa-circle"></i> {{gpsObj.nbbm}}</span> | |
| 34 | + <span class="nbbm goto-marker" data-deviceId="{{gpsObj.deviceId}}"><i class="fa fa-circle"></i> {{gpsObj.nbbm}}</span> | |
| 35 | 35 | |
| 36 | 36 | <span style="font-size: 13px;">{{gpsObj.stationName}}</span> |
| 37 | 37 | </div> |
| ... | ... | @@ -40,4 +40,56 @@ |
| 40 | 40 | </div> |
| 41 | 41 | </div> |
| 42 | 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 | 95 | </script> |
| 44 | 96 | \ No newline at end of file | ... | ... |