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