Commit 8c5746ae1b0c027599214326787bd51e93aa95fd

Authored by 徐烜
2 parents b1583c3e a327fcf1
Showing 51 changed files with 1767 additions and 355 deletions
src/main/java/com/bsth/StartCommand.java
1 1 package com.bsth;
2 2  
3 3  
  4 +import com.bsth.repository.schedule.CarConfigInfoRepository;
4 5 import com.bsth.security.SecurityMetadataSourceService;
5 6 import com.bsth.service.realcontrol.buffer.GetSchedulePlanThread;
6 7 import com.bsth.service.realcontrol.buffer.SchedulePersistenceThread;
7 8 import com.bsth.util.DateUtils;
8 9 import com.bsth.vehicle.common.CommonRefreshThread;
  10 +import com.bsth.vehicle.directive.service.DirectiveService;
9 11 import com.bsth.vehicle.directive.thread.DirectivePersistenceThread;
10 12 import com.bsth.vehicle.directive.thread.FirstScheduleIssuedThread;
11   -import com.bsth.vehicle.gpsdata.GpsArrivalStationThread;
  13 +import com.bsth.vehicle.gpsdata.GpsArrivalThread;
12 14 import com.bsth.vehicle.gpsdata.GpsRefreshThread;
  15 +
13 16 import org.slf4j.Logger;
14 17 import org.slf4j.LoggerFactory;
15 18 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -46,10 +49,17 @@ public class StartCommand implements CommandLineRunner{
46 49 @Autowired
47 50 SchedulePersistenceThread SchedulePersistenceThread;
48 51 @Autowired
49   - GpsArrivalStationThread gpsArrivalStationThread;
  52 + GpsArrivalThread gpsArrivalStationThread;
50 53 @Autowired
51 54 FirstScheduleIssuedThread firstScheduleIssuedThread;
52 55  
  56 + @Autowired
  57 + DirectiveService directiveService;
  58 + @Autowired
  59 + CarConfigInfoRepository carConfigInfoRepository;
  60 +
  61 + static Long hourTime = 1000 * 60 * 60L;
  62 +
53 63 @Override
54 64 public void run(String... arg0){
55 65  
... ... @@ -64,12 +74,12 @@ public class StartCommand implements CommandLineRunner{
64 74 scheduler.scheduleWithFixedDelay(gpsRefreshThread, 0, 8, TimeUnit.SECONDS);
65 75  
66 76 /**
67   - * 每天 0点 抓取当天实际排班
  77 + * 每天 凌晨 2 点 抓取当天实际排班
68 78 */
69 79 //启动时先run一次
70 80 getSchedulePlanThread.start();
71 81 scheduler.scheduleAtFixedRate(getSchedulePlanThread
72   - , DateUtils.getTimesnight() + 5 - System.currentTimeMillis() / 1000
  82 + , ((DateUtils.getTimesnight2() + hourTime * 2) - System.currentTimeMillis()) / 1000
73 83 , 60 * 60 * 24, TimeUnit.SECONDS);
74 84  
75 85 /**
... ... @@ -93,7 +103,7 @@ public class StartCommand implements CommandLineRunner{
93 103 * 每15秒从数据库抓取到离站信息和班次匹配
94 104 * (网关生成的到离站数据也是延迟批量入库,所以缩短该线程执行周期并不会提高 “实际到离站” 的实时性)
95 105 */
96   - scheduler.scheduleWithFixedDelay(gpsArrivalStationThread, 35, 1200, TimeUnit.SECONDS);
  106 + scheduler.scheduleWithFixedDelay(gpsArrivalStationThread, 15, 20, TimeUnit.SECONDS);
97 107  
98 108 /**
99 109 * 首个调度指令下发(2分钟运行一次)
... ... @@ -102,6 +112,86 @@ public class StartCommand implements CommandLineRunner{
102 112 */
103 113 scheduler.scheduleWithFixedDelay(firstScheduleIssuedThread, 60 , 60 * 2, TimeUnit.SECONDS);
104 114  
  115 + /**
  116 + * ######### 测试 ###############
  117 + */
  118 +/* new Timer().schedule(new TimerTask() {
  119 +
  120 + @Override
  121 + public void run() {
  122 + //根据班次模拟一份到离站数据
  123 + Set<String> set = ScheduleBuffer.vehSchListMap.keySet();
  124 + ArrivalInfo outArr, inArr;
  125 + List<ArrivalInfo> arrList = new ArrayList<>();
  126 + Date d = new Date();
  127 + for(String nbbm : set){
  128 +
  129 + for(ScheduleRealInfo sch : ScheduleBuffer.vehSchListMap.get(nbbm)){
  130 + //发出
  131 + outArr = new ArrivalInfo(CommonMapped.vehicDeviceBiMap.inverse().get(nbbm)
  132 + , sch.getFcsjT(), sch.getXlBm(), Integer.parseInt(sch.getXlDir()), sch.getQdzCode(), 1, d , 31);
  133 +
  134 + //到达
  135 + inArr = new ArrivalInfo(CommonMapped.vehicDeviceBiMap.inverse().get(nbbm)
  136 + , sch.getZdsjT(), sch.getXlBm(), Integer.parseInt(sch.getXlDir()), sch.getZdzCode(), 0, d , 31);
  137 +
  138 + arrList.add(outArr);
  139 + arrList.add(inArr);
  140 + }
  141 + }
  142 + try {
  143 + Connection conn = DBUtils_MS.getConnection();
  144 + String sql = "insert into bsth_c_arrival_info(device_id, line_id, stop_no, ts, up_down, in_out, weeks_year, create_date)"
  145 + + " values(?, ?, ?, ? , ?, ?,?, now())";
  146 +
  147 + conn.setAutoCommit(false);
  148 + java.sql.PreparedStatement ps = conn.prepareStatement(sql);
  149 +
  150 + for(ArrivalInfo arr : arrList){
  151 + ps.setString(1, arr.getDeviceId());
  152 + ps.setString(2, arr.getLineCode());
  153 + ps.setString(3, arr.getStopNo());
  154 + ps.setLong(4, arr.getTs() == null? 0: arr.getTs());
  155 + ps.setInt(5, arr.getUpDown());
  156 + ps.setInt(6, arr.getInOut());
  157 + ps.setInt(7, arr.getWeeksYear());
  158 +
  159 + ps.addBatch();
  160 + }
  161 +
  162 + ps.executeBatch();
  163 + conn.commit();
  164 + } catch (SQLException e) {
  165 + e.printStackTrace();
  166 + }
  167 +
  168 + //new BatchSaveUtils<ArrivalInfo>().saveList(arrList, ArrivalInfo.class);
  169 + }
  170 + }, 5000);*/
  171 +
  172 +/* //延迟一会
  173 + new Timer().schedule(new TimerTask() {
  174 +
  175 + @Override
  176 + public void run() {
  177 + //临时全量刷车辆线路
  178 + List<CarConfigInfo> ccis = carConfigInfoRepository.findAll();
  179 + Cars car;
  180 + Line line;
  181 + String lineCode;
  182 + int code;
  183 + for(CarConfigInfo cci : ccis){
  184 + car = cci.getCl();
  185 + line = cci.getXl();
  186 + lineCode = line.getLineCode();
  187 + System.out.println("车辆:" + car.getInsideCode() + "切换线路:" + line.getLineCode());
  188 + code = directiveService.lineChange(car.getInsideCode(), Integer.parseInt(lineCode));
  189 + //directiveService.send60Phrase(car.getInsideCode(), "");
  190 + System.out.println("返回值:" + code);
  191 + }
  192 + }
  193 + }, 1000 * 10);*/
  194 +
105 195 } catch (Exception e) {
106 196 e.printStackTrace();
107 197 }
... ...
src/main/java/com/bsth/controller/realcontrol/ScheduleRealInfoController.java
... ... @@ -273,7 +273,7 @@ public class ScheduleRealInfoController extends BaseController&lt;ScheduleRealInfo,
273 273 */
274 274 @RequestMapping(value = "/lineCode/{lineCode}")
275 275 public List<ScheduleRealInfo> findByLineCode(@PathVariable("lineCode") String lineCode){
276   - return ScheduleBuffer.schedulListMap.get(lineCode);
  276 + return ScheduleBuffer.realSchedulListMap.get(lineCode);
277 277 }
278 278  
279 279 @RequestMapping(value = "/queryUserInfo")
... ...
src/main/java/com/bsth/entity/realcontrol/ChildTaskPlan.java
... ... @@ -10,6 +10,9 @@ import javax.persistence.NamedEntityGraph;
10 10 import javax.persistence.NamedEntityGraphs;
11 11 import javax.persistence.Table;
12 12  
  13 +import com.fasterxml.jackson.annotation.JsonIgnore;
  14 +
  15 +
13 16 /**
14 17 *
15 18 * @ClassName: ChildTaskPlan
... ... @@ -95,7 +98,8 @@ public class ChildTaskPlan {
95 98 /**
96 99 * 主排班计划
97 100 */
98   - @ManyToOne
  101 + @JsonIgnore
  102 + @ManyToOne(fetch = FetchType.LAZY)
99 103 private ScheduleRealInfo schedule;
100 104  
101 105 private String remarks;
... ...
src/main/java/com/bsth/entity/realcontrol/ScheduleRealInfo.java
1 1 package com.bsth.entity.realcontrol;
2 2  
3 3 import com.bsth.entity.sys.SysUser;
  4 +import com.bsth.vehicle.gpsdata.arrival.entity.RealTimeModel;
  5 +import com.fasterxml.jackson.annotation.JsonIgnore;
4 6  
5 7 import javax.persistence.*;
6 8  
  9 +import org.apache.commons.lang3.StringUtils;
  10 +
7 11 import java.text.ParseException;
8 12 import java.text.SimpleDateFormat;
9 13 import java.util.Date;
  14 +import java.util.HashSet;
  15 +import java.util.Set;
10 16  
11 17 /**
12 18 * 实际排班计划明细。
13 19 */
14 20 @Entity
15 21 @Table(name = "bsth_c_s_sp_info_real")
  22 +@NamedEntityGraphs({
  23 + @NamedEntityGraph(name = "scheduleRealInfo_cTasks", attributeNodes = {
  24 + @NamedAttributeNode("cTasks"),
  25 + @NamedAttributeNode("sjfcModel"),
  26 + @NamedAttributeNode("sjddModel")
  27 + })
  28 +})
16 29 public class ScheduleRealInfo {
17 30 /** 主键Id */
18 31 @Id
... ... @@ -24,6 +37,10 @@ public class ScheduleRealInfo {
24 37  
25 38 /** 排班计划日期 */
26 39 private Date scheduleDate;
  40 + private String scheduleDateStr;
  41 +
  42 + /** 真实执行时间 yyyy-MM-dd */
  43 + private String realExecDate;
27 44  
28 45 /** 线路名称 */
29 46 private String xlName;
... ... @@ -87,18 +104,31 @@ public class ScheduleRealInfo {
87 104 * 班次类型 TODO:正常班次、出场、进场、加油、区间班次、放空班次、放大站班次、两点间空驶
88 105 */
89 106 private String bcType;
  107 +
  108 + /** 停车场既首发站 */
  109 + @Transient
  110 + private boolean parkIsFirstStation;
  111 + /** 首发站既停车场 */
  112 + @Transient
  113 + private boolean firstStationIsPark;
  114 + /** 与其共享发车时间的进出场班次 */
  115 + @JsonIgnore
  116 + @Transient
  117 + private ScheduleRealInfo twins;
90 118  
91 119 /** 创建人 */
  120 + @JsonIgnore
92 121 @ManyToOne(fetch = FetchType.LAZY)
93 122 private SysUser createBy;
94 123 /** 修改人 */
  124 + @JsonIgnore
95 125 @ManyToOne(fetch = FetchType.LAZY)
96 126 private SysUser updateBy;
97 127 /** 创建日期 */
98 128 @Column(updatable = false, name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
99 129 private Date createDate;
100 130 /** 修改日期 */
101   - @Column(name = "update_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
  131 + @Column(name = "update_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
102 132 private Date updateDate;
103 133  
104 134 /** 实际发车时间*/
... ... @@ -149,12 +179,28 @@ public class ScheduleRealInfo {
149 179 /** 起点站实际到达时间 */
150 180 private String qdzArrDatesj;
151 181  
  182 + /** 子任务 */
  183 + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  184 + private Set<ChildTaskPlan> cTasks = new HashSet<>();
  185 +
  186 + /** ---------------- */
  187 + /** 实际发出 */
  188 + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  189 + private RealTimeModel sjfcModel;
  190 + /** 实际到达 */
  191 + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  192 + private RealTimeModel sjddModel;
  193 +
152 194 public void addRemarks(String remark){
153   - String newRem = this.getRemarks();
154   - if(null == newRem || newRem.trim() == "")
  195 + if(StringUtils.isBlank(remark))
155 196 return;
156   - newRem += remark + ";";
157   - this.setRemarks(newRem);
  197 + String old = this.getRemarks();
  198 + if(StringUtils.isBlank(old))
  199 + old = "";
  200 +
  201 + old += remark + ";";
  202 + this.setRemarks(old);
  203 +
158 204 }
159 205  
160 206 public Long getId() {
... ... @@ -485,7 +531,7 @@ public class ScheduleRealInfo {
485 531 public void setDfsjAll(String dfsj) {
486 532  
487 533 try {
488   - String dfsjFull = sdfyyyyMMdd.format(this.scheduleDate) + " " + dfsj;
  534 + String dfsjFull = this.realExecDate + " " + dfsj;
489 535 this.dfsjT = sdfyyyyMMddHHmm.parse(dfsjFull).getTime();
490 536 this.dfsj = dfsj;
491 537 } catch (ParseException e) {
... ... @@ -504,7 +550,7 @@ public class ScheduleRealInfo {
504 550 * @throws ParseException
505 551 *
506 552 * @Title: syncTime
507   - * @Description: TODO(计算时间戳,待发时间为计发时间)
  553 + * @Description: TODO(根据计发时间,计算待发时间和终点时间)
508 554 * @param 设定文件
509 555 * @return void 返回类型
510 556 * @throws
... ... @@ -513,7 +559,7 @@ public class ScheduleRealInfo {
513 559 try{
514 560 this.setDfsj(this.getFcsj());
515 561 //发车时间戳
516   - this.setFcsjT(sdfyyyyMMddHHmm.parse(sdfyyyyMMdd.format(this.scheduleDate) + " " + this.getFcsj()).getTime());
  562 + this.setFcsjT(sdfyyyyMMddHHmm.parse(this.realExecDate + " " + this.getFcsj()).getTime());
517 563 //待发时间戳
518 564 this.setDfsjT(this.getFcsjT());
519 565  
... ... @@ -523,6 +569,12 @@ public class ScheduleRealInfo {
523 569 this.setZdsjT(zdDate.getTime());
524 570 this.setZdsj(sdfHHmm.format(zdDate));
525 571 }
  572 +
  573 + if(this.fcsjActual != null)
  574 + this.setFcsjActualAll(this.fcsjActual);
  575 +
  576 + if(this.zdsjActual != null)
  577 + this.setZdsjActualAll(this.zdsjActual);
526 578 }catch(Exception e){
527 579 e.printStackTrace();
528 580 }
... ... @@ -573,7 +625,7 @@ public class ScheduleRealInfo {
573 625 */
574 626 public void setFcsjAll(String fcsj){
575 627 try {
576   - this.fcsjT = sdfyyyyMMddHHmm.parse(sdfyyyyMMdd.format(this.scheduleDate) + " " + fcsj).getTime();
  628 + this.fcsjT = sdfyyyyMMddHHmm.parse(this.realExecDate + " " + fcsj).getTime();
577 629 this.fcsj = fcsj;
578 630 } catch (ParseException e) {
579 631 e.printStackTrace();
... ... @@ -582,14 +634,27 @@ public class ScheduleRealInfo {
582 634  
583 635 /**
584 636 *
  637 + * @Title: setFcsjAll
  638 + * @Description: TODO(设置计划发车时间)
  639 + * @throws
  640 + */
  641 + public void setFcsjAll(Long fcsjT){
  642 + this.fcsjT = fcsjT;
  643 + this.fcsj = sdfHHmm.format(new Date(fcsjT));
  644 + }
  645 +
  646 + /**
  647 + *
585 648 * @Title: setFcsjActualAll
586   - * @Description: TODO(设置实际发车时间)
  649 + * @Description: TODO(设置实际发车时间 字符串)
587 650 * @throws
588 651 */
589 652 public void setFcsjActualAll(String fcsjActual){
590 653 try {
591   - this.fcsjActualTime = sdfyyyyMMddHHmm.parse(sdfyyyyMMdd.format(this.scheduleDate) + " " + fcsjActual).getTime();
  654 + this.fcsjActualTime = sdfyyyyMMddHHmm.parse(this.realExecDate + " " + fcsjActual).getTime();
592 655 this.fcsjActual = fcsjActual;
  656 +
  657 + this.synchroFcsj();
593 658 } catch (ParseException e) {
594 659 e.printStackTrace();
595 660 }
... ... @@ -598,12 +663,29 @@ public class ScheduleRealInfo {
598 663 /**
599 664 *
600 665 * @Title: setFcsjActualAll
601   - * @Description: TODO(设置实际发车时间)
  666 + * @Description: TODO(设置实际发车时间 时间戳)
602 667 * @throws
603 668 */
604 669 public void setFcsjActualAll(Long t){
605 670 this.fcsjActualTime = t;
606 671 this.fcsjActual = sdfHHmm.format(new Date(t));
  672 +
  673 + this.synchroFcsj();
  674 + }
  675 +
  676 + //和依赖班次同步发车时间
  677 + public void synchroFcsj(){
  678 + if(this.isFirstStationIsPark() || this.isParkIsFirstStation()){
  679 + ScheduleRealInfo twinsSch = this.twins;
  680 + if(null != twinsSch){
  681 + //有关联的出场班次
  682 + twinsSch.setFcsjActual(this.fcsjActual);
  683 + twinsSch.setFcsjActualTime(this.fcsjActualTime);
  684 + if(null != twinsSch.getSjfcModel())
  685 + twinsSch.getSjfcModel().setPersonTime(this.fcsjActualTime);
  686 + twinsSch.calcStatus();
  687 + }
  688 + }
607 689 }
608 690  
609 691 /**
... ... @@ -615,6 +697,8 @@ public class ScheduleRealInfo {
615 697 public void setZdsjActualAll(Long t){
616 698 this.zdsjActualTime = t;
617 699 this.zdsjActual = sdfHHmm.format(new Date(t));
  700 +
  701 + this.synchroZdsj();
618 702 }
619 703  
620 704 /**
... ... @@ -627,10 +711,25 @@ public class ScheduleRealInfo {
627 711 try {
628 712 this.zdsjActualTime = sdfyyyyMMddHHmm.parse(sdfyyyyMMdd.format(this.scheduleDate) + " " + zdsjActual).getTime();
629 713 this.zdsjActual = zdsjActual;
  714 +
  715 + this.synchroZdsj();
630 716 } catch (ParseException e) {
631 717 e.printStackTrace();
632 718 }
633 719 }
  720 +
  721 + //和依赖的进场班次同步终点时间
  722 + public void synchroZdsj(){
  723 + if(this.isFirstStationIsPark()){
  724 + ScheduleRealInfo twinsSch = this.twins;
  725 + if(null != twinsSch && twinsSch.getBcType().equals("in")){
  726 + //有关联的进场班次
  727 + twinsSch.setFcsjActual(this.zdsjActual);
  728 + twinsSch.setFcsjActualTime(this.zdsjActualTime);
  729 + twinsSch.calcStatus();
  730 + }
  731 + }
  732 + }
634 733  
635 734 public Long getSpId() {
636 735 return spId;
... ... @@ -639,4 +738,140 @@ public class ScheduleRealInfo {
639 738 public void setSpId(Long spId) {
640 739 this.spId = spId;
641 740 }
  741 +
  742 + public String getRealExecDate() {
  743 + return realExecDate;
  744 + }
  745 +
  746 + public void setRealExecDate(String realExecDate) {
  747 + this.realExecDate = realExecDate;
  748 + }
  749 +
  750 + public void calcStatus() {
  751 + if(this.status == -1)
  752 + return;
  753 +
  754 + this.status = 0;
  755 + if(StringUtils.isNotBlank(this.fcsjActual)){
  756 + this.status = 1;
  757 +
  758 + //进出场班次并且没有终点时间的
  759 + if((this.bcType.equals("out") || this.bcType.equals("in"))
  760 + && this.zdsj == null){
  761 + this.status = 2;
  762 + }
  763 + }
  764 + if(StringUtils.isNotBlank(this.zdsjActual))
  765 + this.status = 2;
  766 + }
  767 +
  768 + public void destroy(){
  769 + this.status = -1;
  770 + }
  771 +
  772 + public boolean isDestroy(){
  773 + return this.status == -1;
  774 + }
  775 +
  776 + public boolean isNotDestroy(){
  777 + return this.status != -1;
  778 + }
  779 +
  780 + public RealTimeModel getSjfcModel() {
  781 + return sjfcModel;
  782 + }
  783 +
  784 + public void setSjfcModel(RealTimeModel sjfcModel) {
  785 + this.sjfcModel = sjfcModel;
  786 + }
  787 +
  788 + public RealTimeModel getSjddModel() {
  789 + return sjddModel;
  790 + }
  791 +
  792 + public void setSjddModel(RealTimeModel sjddModel) {
  793 + this.sjddModel = sjddModel;
  794 + }
  795 +
  796 + public Set<ChildTaskPlan> getcTasks() {
  797 + return cTasks;
  798 + }
  799 +
  800 + public void setcTasks(Set<ChildTaskPlan> cTasks) {
  801 + this.cTasks = cTasks;
  802 + }
  803 +
  804 + public String getScheduleDateStr() {
  805 + return scheduleDateStr;
  806 + }
  807 +
  808 + public void setScheduleDateStr(String scheduleDateStr) {
  809 + this.scheduleDateStr = scheduleDateStr;
  810 + }
  811 +
  812 + public boolean isParkIsFirstStation() {
  813 + return parkIsFirstStation;
  814 + }
  815 +
  816 + public void setParkIsFirstStation(boolean parkIsFirstStation) {
  817 + this.parkIsFirstStation = parkIsFirstStation;
  818 + }
  819 +
  820 + public ScheduleRealInfo getTwins() {
  821 + return twins;
  822 + }
  823 +
  824 + public void setTwins(ScheduleRealInfo twins) {
  825 + this.twins = twins;
  826 + }
  827 +
  828 + public boolean isFirstStationIsPark() {
  829 + return firstStationIsPark;
  830 + }
  831 +
  832 + public void setFirstStationIsPark(boolean firstStationIsPark) {
  833 + this.firstStationIsPark = firstStationIsPark;
  834 + }
  835 +
  836 +
  837 + public boolean statusTostart(){
  838 + return this.getFcsjActual() == null
  839 + && this.getSjfcModel().getTime() != null;
  840 + }
  841 +
  842 + public boolean statusToEnd(){
  843 + return this.getZdsjActual() == null
  844 + && this.getSjddModel().getTime() != null;
  845 + }
  846 +
  847 + public void revokeRealOutgo() {
  848 + //this.setStatus(0);
  849 + this.setFcsjActual(null);
  850 + this.setFcsjActualTime(null);
  851 + if(null != this.getSjfcModel())
  852 + this.getSjfcModel().resetNull();
  853 + this.calcStatus();
  854 + }
  855 +
  856 + public boolean existDependent() {
  857 + return this.isFirstStationIsPark() || this.parkIsFirstStation;
  858 + }
  859 +
  860 + //清除实际终点时间
  861 + public void clearZdsjActual(){
  862 + this.setZdsjActual(null);
  863 + this.setZdsjActualTime(null);
  864 + if(null != this.getSjddModel())
  865 + this.getSjddModel().resetNull();
  866 +
  867 + //依赖班次
  868 + if(this.existDependent()){
  869 + ScheduleRealInfo twins = this.getTwins();
  870 + twins.setZdsjActual(null);
  871 + twins.setZdsjActualTime(null);
  872 + if(null != twins.getSjddModel())
  873 + twins.getSjddModel().resetNull();
  874 +
  875 + }
  876 + }
642 877 }
... ...
src/main/java/com/bsth/repository/realcontrol/ScheduleRealInfoRepository.java
... ... @@ -4,6 +4,7 @@ import java.util.Date;
4 4 import java.util.List;
5 5 import java.util.Map;
6 6  
  7 +import org.springframework.data.jpa.repository.EntityGraph;
7 8 import org.springframework.data.jpa.repository.Query;
8 9 import org.springframework.stereotype.Repository;
9 10  
... ... @@ -20,7 +21,7 @@ public interface ScheduleRealInfoRepository extends BaseRepository&lt;ScheduleRealI
20 21 @Query(value="select s from ScheduleRealInfo s where s.xlBm = ?1 and DATE_FORMAT(s.scheduleDate,'%Y-%m-%d') = ?2 group by jName,clZbh,lpName")
21 22 List<ScheduleRealInfo> queryUserInfo(String line,String date);
22 23  
23   - @Query(value="select s from ScheduleRealInfo s where s.jName = ?1 and s.clZbh = ?2 and s.lpName = ?3")
  24 + @Query(value="select s from ScheduleRealInfo s where s.jName = ?1 and s.clZbh = ?2 and s.lpName = ?3 order by fcsj")
24 25 List<ScheduleRealInfo> exportWaybill(String jName,String clZbh,String lpName);
25 26  
26 27 @Query(value="select new map(clZbh as clZbh,jGh as jGh,jName as jName,sum(jhlc) as zgl,sum(addMileage) as ksgl,count(jName) as bcs) from ScheduleRealInfo s where s.xlBm = ?1 and DATE_FORMAT(s.scheduleDate,'%Y-%m-%d') = ?2 group by clZbh,jGh")
... ... @@ -32,11 +33,12 @@ public interface ScheduleRealInfoRepository extends BaseRepository&lt;ScheduleRealI
32 33 @Query(value = "select max(id) from ScheduleRealInfo")
33 34 Long getMaxId();
34 35  
35   - @Query(value = "select count(*) from ScheduleRealInfo s where s.scheduleDate = ?1")
36   - int countByDate(Date date);
  36 + @Query(value = "select count(*) from ScheduleRealInfo s where s.scheduleDateStr = ?1")
  37 + int countByDate(String date);
37 38  
38   - @Query(value = "select s from ScheduleRealInfo s where s.scheduleDate = ?1")
39   - List<ScheduleRealInfo> findByDate(Date date);
  39 + @EntityGraph(value = "scheduleRealInfo_cTasks", type = EntityGraph.EntityGraphType.FETCH)
  40 + @Query(value = "select s from ScheduleRealInfo s where s.scheduleDateStr = ?1")
  41 + List<ScheduleRealInfo> findByDate(String dateStr);
40 42  
41 43 @Query(value="select count(jName) from ScheduleRealInfo s where s.jName = ?1 and s.clZbh = ?2 and s.lpName = ?3 and s.status = -1")
42 44 int findCjbc(String jName,String clZbh,String lpName);
... ...
src/main/java/com/bsth/service/realcontrol/buffer/GetSchedulePlanThread.java
... ... @@ -46,6 +46,7 @@ public class GetSchedulePlanThread extends Thread{
46 46 @Override
47 47 public void run() {
48 48 try{
  49 + logger.info("从计划调度抓取排班数据...");
49 50 //清除缓存
50 51 ScheduleBuffer.clear();
51 52 //所有指令入库
... ... @@ -62,18 +63,18 @@ public class GetSchedulePlanThread extends Thread{
62 63 public void loaSchedule() throws ParseException{
63 64 List<ScheduleRealInfo> realList = null;
64 65 String dateStr = sdfyyyyMMdd.format(new Date());
65   - Date cDate = sdfyyyyMMdd.parse(dateStr);
  66 + //Date cDate = sdfyyyyMMdd.parse(dateStr);
66 67 //查询数据库是否有今日排班
67   - int size = scheduleRealInfoRepository.countByDate(cDate);
  68 + int size = scheduleRealInfoRepository.countByDate(dateStr);
68 69 if(size > 0){
69 70 //从数据库恢复当日排班
70   - realList = scheduleRealInfoRepository.findByDate(cDate);
  71 + realList = scheduleRealInfoRepository.findByDate(dateStr);
71 72 logger.info("从数据库恢复当日排班 " + realList.size());
72 73 //写入缓存
73 74 ScheduleBuffer.init(realList);
74 75 }
75 76 else{
76   - List<SchedulePlanInfo> list = schedulePlanInfoRepository.findByDate(cDate);
  77 + List<SchedulePlanInfo> list = schedulePlanInfoRepository.findByDate(sdfyyyyMMdd.parse(dateStr));
77 78  
78 79 for(SchedulePlanInfo sp : list){
79 80 sp.setSchedulePlan(null);
... ... @@ -90,6 +91,7 @@ public class GetSchedulePlanThread extends Thread{
90 91 for(ScheduleRealInfo item : realList){
91 92 item.setSpId(item.getId());
92 93 item.setId(id ++);//设置ID
  94 + item.setScheduleDateStr(sdfyyyyMMdd.format(item.getScheduleDate()));
93 95 }
94 96  
95 97 //写入缓存
... ...
src/main/java/com/bsth/service/realcontrol/buffer/ScheduleBuffer.java
1 1 package com.bsth.service.realcontrol.buffer;
2 2  
  3 +import java.text.SimpleDateFormat;
3 4 import java.util.ArrayList;
4 5 import java.util.Collections;
5 6 import java.util.Comparator;
  7 +import java.util.Date;
6 8 import java.util.HashMap;
7 9 import java.util.LinkedList;
8 10 import java.util.List;
... ... @@ -14,7 +16,6 @@ import org.slf4j.LoggerFactory;
14 16  
15 17 import com.bsth.entity.realcontrol.ScheduleRealInfo;
16 18 import com.google.common.collect.ArrayListMultimap;
17   -import com.google.common.collect.LinkedListMultimap;
18 19  
19 20 /**
20 21 *
... ... @@ -31,7 +32,7 @@ public class ScheduleBuffer {
31 32 /**
32 33 * 当天实际排班 K 线路编码 V 按时间升序的班次
33 34 */
34   - public static ArrayListMultimap<String, ScheduleRealInfo> schedulListMap;
  35 + public static ArrayListMultimap<String, ScheduleRealInfo> realSchedulListMap;
35 36  
36 37 /**
37 38 * K: 车辆自编号 V: 未完成班次链表
... ... @@ -41,7 +42,7 @@ public class ScheduleBuffer {
41 42 /**
42 43 * K: 车辆自编号 V: 班次链表
43 44 */
44   - public static ArrayListMultimap<String, ScheduleRealInfo> vehSchListMap;
  45 + public static ArrayListMultimap<String, ScheduleRealInfo> carSchListMap;
45 46 /*public static Map<String, LinkedList<ScheduleRealInfo>> vehSchLinkedMap;*/
46 47  
47 48  
... ... @@ -61,8 +62,8 @@ public class ScheduleBuffer {
61 62 */
62 63 public static LinkedList<ScheduleRealInfo> persistentList;
63 64  
64   - /** K: 线路编码_上下行 V: 班次平均间隔时间 */
65   - public static Map<String , Long> schSpaceMap;
  65 + /** K: 线路编码_上下行 V: 班次平均间隔时间
  66 + public static Map<String , Long> schSpaceMap; */
66 67  
67 68 /**
68 69 * 线路是否托管 K:线路编码 V:0 托管 1 非托管
... ... @@ -71,25 +72,30 @@ public class ScheduleBuffer {
71 72  
72 73 static ScheduleComparator scheduleComparator = new ScheduleComparator();
73 74  
  75 + static final Long DAY_TIME = 1000 * 60 * 60 * 24L;
  76 +
74 77 static{
75 78 clear();
76 79 }
77 80  
78 81 public static void clear(){
79   - schedulListMap = ArrayListMultimap.create();
  82 + realSchedulListMap = ArrayListMultimap.create();
80 83 pkSchedulMap = new HashMap<>();
81 84 persistentList = new LinkedList<>();
82 85 /*vehLinkedMap = new HashMap<>();
83 86 finishLinkedMap = LinkedListMultimap.create();*/
84   - vehSchListMap = ArrayListMultimap.create();
  87 + carSchListMap = ArrayListMultimap.create();
85 88 trustMap = new HashMap<>();
86 89 }
87 90  
88 91 public static int init(List<ScheduleRealInfo> list){
  92 + SimpleDateFormat sdfyyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
89 93  
90 94 try{
91 95 //计算时间戳
92 96 for(ScheduleRealInfo schedul : list){
  97 + //真实日期默认是排班日期
  98 + schedul.setRealExecDate(sdfyyyyMMdd.format(schedul.getScheduleDate()));
93 99 schedul.syncTime();
94 100 }
95 101  
... ... @@ -98,25 +104,33 @@ public class ScheduleBuffer {
98 104  
99 105 String zbh;
100 106 for(ScheduleRealInfo schedul : list){
101   - schedulListMap.put(schedul.getXlBm(), schedul);
  107 +
  108 + realSchedulListMap.put(schedul.getXlBm(), schedul);
102 109 pkSchedulMap.put(schedul.getId(), schedul);
103 110  
104 111 //初始化车辆和班次列表对照
105 112 zbh = schedul.getClZbh();
106   - vehSchListMap.put(zbh, schedul);
107   - /*if(!vehLinkedMap.containsKey(zbh))
108   - vehLinkedMap.put(zbh, new LinkedList<ScheduleRealInfo>());
109   -
110   - vehLinkedMap.get(zbh).add(schedul);*/
  113 + carSchListMap.put(zbh, schedul);
111 114 }
112 115  
  116 + //计算真实计划发车时间
  117 + calcRealOutTime();
  118 +
113 119 //计算起点应到时间
114   - Set<String> codes = schedulListMap.keySet();
115   - for(String code : codes)
116   - calcArrDateQd(code);
  120 + Set<String> lineCodes = realSchedulListMap.keySet();
  121 + for(String lineCode : lineCodes)
  122 + calcArrDateQd(lineCode);
  123 +
  124 + //标记停车场既是起点站的班次
  125 + Set<String> cars = carSchListMap.keySet();
  126 + for(String nbbm : cars)
  127 + markParkIsFirstStation(nbbm);
  128 +
  129 + //markParkIsFirstStation
117 130  
118 131 //计算班次平均间隔
119   - calcAvgSpace();
  132 + //calcAvgSpace();
  133 +
120 134 }catch(Exception e){
121 135 logger.error("缓存排班数据失败...", e);
122 136 return -1;
... ... @@ -124,16 +138,73 @@ public class ScheduleBuffer {
124 138 return 0;
125 139 }
126 140  
  141 + private static void calcRealOutTime() {
  142 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  143 + Set<String> keys = carSchListMap.keySet();
  144 +
  145 + List<ScheduleRealInfo> list;
  146 + ScheduleRealInfo schedule;
  147 + for(String key : keys){
  148 + list = carSchListMap.get(key);
  149 +
  150 + //发车顺序号排序
  151 + Collections.sort(list, scheduleComparator);
  152 + for(int i = 0; i < list.size(); i ++){
  153 + schedule = list.get(i);
  154 + if(i > 0 && schedule.getFcsjT() < list.get(i - 1).getFcsjT()){
  155 + //加一天
  156 + schedule.setFcsjAll(schedule.getFcsjT() + DAY_TIME);
  157 + schedule.setRealExecDate(sdf.format(new Date(schedule.getFcsjT())));
  158 + schedule.syncTime();
  159 + }
  160 + }
  161 + }
  162 + }
  163 +
  164 + /**
  165 + *
  166 + * @Title: markParkIsFirstStation
  167 + * @Description: TODO(标记停车场即首发站的班次)
  168 + * @throws
  169 + */
  170 + public static void markParkIsFirstStation(String nbbm){
  171 + List<ScheduleRealInfo> list = carSchListMap.get(nbbm);
  172 +
  173 + String type;
  174 + for(ScheduleRealInfo sch : list){
  175 + type = sch.getBcType();
  176 + if(!type.equals("out") && !type.equals("in"))
  177 + continue;
  178 +
  179 + for(ScheduleRealInfo sch2 : list){
  180 +
  181 + if(sch.getId() == sch2.getId())
  182 + continue;
  183 +
  184 + if(sch.getFcsjT().equals(sch2.getFcsjT())//出场,发车时间一致
  185 + || sch.getFcsjT().equals(sch2.getZdsjT())//进场,上一班次站点时间为进场起点时间
  186 + ){
  187 + sch.setParkIsFirstStation(true);
  188 + sch2.setFirstStationIsPark(true);
  189 + //做双休关联
  190 + sch2.setTwins(sch);
  191 + sch.setTwins(sch2);
  192 + break;
  193 + }
  194 + }
  195 + }
  196 + }
  197 +
127 198 //计算平均间隔
128   - public static void calcAvgSpace(){
  199 +/* public static void calcAvgSpace(){
129 200 schSpaceMap = new HashMap<>();
130   - Set<String> set = schedulListMap.keySet();
  201 + Set<String> set = realSchedulListMap.keySet();
131 202  
132 203 List<ScheduleRealInfo> list = null
133 204 ,upList = null
134 205 ,downList = null;
135 206 for(String lineCode : set){
136   - list = schedulListMap.get(lineCode);
  207 + list = realSchedulListMap.get(lineCode);
137 208 Long sumUp = 0L, sumDown = 0L;
138 209  
139 210 upList = new ArrayList<>();
... ... @@ -156,14 +227,14 @@ public class ScheduleBuffer {
156 227 schSpaceMap.put(lineCode + "_0", sumUp / upList.size());
157 228 schSpaceMap.put(lineCode + "_1", sumDown / downList.size());
158 229 }
159   - }
  230 + }*/
160 231  
161 232 public static int put(ScheduleRealInfo sch){
162   - schedulListMap.put(sch.getXlBm(), sch);
  233 + realSchedulListMap.put(sch.getXlBm(), sch);
163 234  
164 235 pkSchedulMap.put(sch.getId(), sch);
165 236 String zbh = sch.getClZbh();
166   - vehSchListMap.put(zbh, sch);
  237 + carSchListMap.put(zbh, sch);
167 238  
168 239 //List<ScheduleRealInfo> list = vehSchListMap.get(sch.getClZbh());
169 240  
... ... @@ -172,11 +243,11 @@ public class ScheduleBuffer {
172 243 vehLinkedMap.get(zbh).add(sch);*/
173 244  
174 245 //重新排序
175   - Collections.sort(schedulListMap.get(sch.getXlBm()), scheduleComparator);
  246 + Collections.sort(realSchedulListMap.get(sch.getXlBm()), scheduleComparator);
  247 + //Collections.sort(vehSchListMap.get(zbh), scheduleComparator);
176 248  
177 249 //重新计算应到时间
178   - //calcArrDateQd(vehLinkedMap.get(zbh));
179   - calcArrDateQd(vehSchListMap.get(zbh));
  250 + calcArrDateQd(carSchListMap.get(zbh));
180 251 return 0;
181 252 }
182 253  
... ... @@ -205,7 +276,8 @@ public class ScheduleBuffer {
205 276  
206 277 //下一个班次
207 278 ScheduleRealInfo next = getNext(sch);
208   - next.setQdzArrDateSJ(sch.getZdsjActual());
  279 + if(next != null)
  280 + next.setQdzArrDateSJ(sch.getZdsjActual());
209 281 /*ScheduleRealInfo temp;
210 282 int len = list.size();
211 283 for(int i = 0; i < len; i ++){
... ... @@ -222,7 +294,7 @@ public class ScheduleBuffer {
222 294 }
223 295  
224 296 public static ScheduleRealInfo getNext(ScheduleRealInfo sch){
225   - List<ScheduleRealInfo> list = vehSchListMap.get(sch.getClZbh());
  297 + List<ScheduleRealInfo> list = carSchListMap.get(sch.getClZbh());
226 298  
227 299 boolean flag = false;
228 300 ScheduleRealInfo next = null;
... ... @@ -262,7 +334,7 @@ public class ScheduleBuffer {
262 334 * @throws
263 335 */
264 336 public static int getFinishSchNo(String nbbm){
265   - List<ScheduleRealInfo> list = vehSchListMap.get(nbbm);
  337 + List<ScheduleRealInfo> list = carSchListMap.get(nbbm);
266 338 int no = 0;
267 339 for(ScheduleRealInfo sch : list){
268 340 if(sch.getStatus() == 2)
... ... @@ -280,7 +352,7 @@ public class ScheduleBuffer {
280 352 * @throws
281 353 */
282 354 public static ScheduleRealInfo findCurrent(String nbbm){
283   - List<ScheduleRealInfo> list = ScheduleBuffer.vehSchListMap.get(nbbm);
  355 + List<ScheduleRealInfo> list = ScheduleBuffer.carSchListMap.get(nbbm);
284 356  
285 357 int size = list.size();
286 358 ScheduleRealInfo sch;
... ... @@ -301,7 +373,7 @@ public class ScheduleBuffer {
301 373 * @throws
302 374 */
303 375 public static List<ScheduleRealInfo> findNextList(ScheduleRealInfo sch){
304   - List<ScheduleRealInfo> list = vehSchListMap.get(sch.getClZbh()),
  376 + List<ScheduleRealInfo> list = carSchListMap.get(sch.getClZbh()),
305 377 rs = null;
306 378  
307 379 for(ScheduleRealInfo temp : list){
... ... @@ -338,7 +410,7 @@ public class ScheduleBuffer {
338 410 * @throws
339 411 */
340 412 public static void calcArrDateQd(String lineCode){
341   - List<ScheduleRealInfo> list = schedulListMap.get(lineCode);
  413 + List<ScheduleRealInfo> list = realSchedulListMap.get(lineCode);
342 414 //按车辆分组
343 415 ArrayListMultimap<String, ScheduleRealInfo> map = ArrayListMultimap.create();
344 416 for(ScheduleRealInfo sch : list){
... ... @@ -357,7 +429,7 @@ public class ScheduleBuffer {
357 429 }
358 430  
359 431 public static List<ScheduleRealInfo> findByLineAndUpDown(Integer lineCode, Integer upDown){
360   - List<ScheduleRealInfo> list = schedulListMap.get(String.valueOf(lineCode))
  432 + List<ScheduleRealInfo> list = realSchedulListMap.get(String.valueOf(lineCode))
361 433 ,subList = new ArrayList<>();
362 434 //按走向过滤
363 435 for(ScheduleRealInfo sch : list){
... ... @@ -367,4 +439,12 @@ public class ScheduleBuffer {
367 439 }
368 440 return subList;
369 441 }
  442 +
  443 + public static ScheduleRealInfo getFirst(String nbbm){
  444 + List<ScheduleRealInfo> list = carSchListMap.get(nbbm);
  445 + if(list.size() > 0)
  446 + return list.get(0);
  447 + else
  448 + return null;
  449 + }
370 450 }
... ...
src/main/java/com/bsth/service/realcontrol/buffer/SchedulePersistenceThread.java
... ... @@ -34,6 +34,10 @@ public class SchedulePersistenceThread extends Thread {
34 34 break;
35 35  
36 36 scheduleRepository.save(schedule);
  37 + if(schedule.existDependent()){
  38 + //关联班次也持久化
  39 + scheduleRepository.save(schedule.getTwins());
  40 + }
37 41 }
38 42 }
39 43 }
... ...
src/main/java/com/bsth/service/realcontrol/impl/ChildTaskPlanServiceImpl.java
... ... @@ -2,25 +2,41 @@ package com.bsth.service.realcontrol.impl;
2 2  
3 3 import java.util.Map;
4 4  
  5 +import javax.transaction.Transactional;
  6 +
  7 +import org.springframework.beans.factory.annotation.Autowired;
5 8 import org.springframework.stereotype.Service;
6 9  
7 10 import com.bsth.entity.realcontrol.ChildTaskPlan;
  11 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
8 12 import com.bsth.service.impl.BaseServiceImpl;
9 13 import com.bsth.service.realcontrol.ChildTaskPlanService;
  14 +import com.bsth.service.realcontrol.buffer.ScheduleBuffer;
10 15 import com.bsth.vehicle.common.CommonMapped;
11 16  
12 17 @Service
13 18 public class ChildTaskPlanServiceImpl extends BaseServiceImpl<ChildTaskPlan, Long> implements ChildTaskPlanService{
14 19  
  20 + @Autowired
  21 + ScheduleRealInfoServiceImpl scheduleRealInfoService;
15 22  
  23 + @Transactional
16 24 @Override
17 25 public Map<String, Object> save(ChildTaskPlan t) {
  26 + Map<String, Object> rs;
18 27 //保存起终点名称
19 28 Map<String, String> map = CommonMapped.stationCodeMap;
20 29  
21 30 t.setStartStationName(map.get(t.getStartStation()));
22 31 t.setEndStationName(map.get(t.getEndStation()));
23   - return super.save(t);
  32 +
  33 + //rs = super.save(t);
  34 +
  35 + ScheduleRealInfo sch = ScheduleBuffer.findOne(t.getSchedule().getId());
  36 + sch.getcTasks().add(t);
  37 + rs = scheduleRealInfoService.save(sch);
  38 +
  39 + return rs;
24 40 }
25 41  
26 42 }
... ...
src/main/java/com/bsth/service/realcontrol/impl/ScheduleRealInfoServiceImpl.java
1 1 package com.bsth.service.realcontrol.impl;
2 2  
3   -import java.io.File;
4 3 import java.text.DecimalFormat;
5 4 import java.text.ParseException;
6 5 import java.text.SimpleDateFormat;
... ... @@ -88,7 +87,7 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
88 87 Multimap<String, ScheduleRealInfo> mMap = ArrayListMultimap.create();
89 88  
90 89 for (String lineCode : lineList) {
91   - mMap.putAll(lineCode, ScheduleBuffer.schedulListMap.get(lineCode));
  90 + mMap.putAll(lineCode, ScheduleBuffer.realSchedulListMap.get(lineCode));
92 91 }
93 92 return mMap.asMap();
94 93 }
... ... @@ -99,9 +98,9 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
99 98 try {
100 99  
101 100 ScheduleRealInfo schedule = ScheduleBuffer.pkSchedulMap.get(id);
102   - schedule.setDfsjT(sdfMinute.parse(sdfMonth.format(new Date()) + " " + dfsj).getTime());
  101 + schedule.setDfsjT(sdfMinute.parse(schedule.getRealExecDate() + " " + dfsj).getTime());
103 102 schedule.setDfsj(dfsj);
104   - schedule.addRemarks(remarks + ";");
  103 + schedule.addRemarks(remarks);
105 104 schedule.setClZbh(nbbm);
106 105 if(jsy != null && jsy.indexOf("/") != -1){
107 106 String[] jsyArray = jsy.split("/");
... ... @@ -139,16 +138,15 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
139 138 ScheduleRealInfo schedule = null;
140 139 for (String id : idList) {
141 140 schedule = ScheduleBuffer.pkSchedulMap.get(Long.parseLong(id));
142   - /*if(schedule.getStatus() == -1){
  141 + if(schedule.isDestroy()){
143 142 map.put("status", ResponseCode.ERROR);
144   - map.put("msg", value)
145   - }*/
146   - if (null != schedule) {
147   - schedule.setStatus(-1);
148   - schedule.addRemarks(remarks);
149   -
150   - rsList.add(schedule);
  143 + map.put("msg", "不必要的重复烂班!");
  144 + return map;
151 145 }
  146 +
  147 + schedule.destroy();
  148 + schedule.addRemarks(remarks);
  149 + rsList.add(schedule);
152 150 }
153 151  
154 152 // 调整间隔
... ... @@ -158,7 +156,7 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
158 156 String lineCode = first.getXlBm();
159 157 String upDown = first.getXlDir();
160 158  
161   - List<ScheduleRealInfo> schList = ScheduleBuffer.schedulListMap.get(lineCode),
  159 + List<ScheduleRealInfo> schList = ScheduleBuffer.realSchedulListMap.get(lineCode),
162 160 dirList = new ArrayList<>();
163 161 // 筛选走向
164 162 for (ScheduleRealInfo s : schList) {
... ... @@ -276,8 +274,10 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
276 274 @Override
277 275 public Map<String, Object> save(ScheduleRealInfo t) {
278 276 SysUser user = SecurityUtils.getCurrentUser();
279   -
280   - t.setScheduleDate(new Date());
  277 + Date d = new Date();
  278 +
  279 + t.setScheduleDate(d);
  280 + t.setRealExecDate(sdfMonth.format(d));
281 281 t.setCreateBy(user);
282 282 t.syncTime();
283 283 t.setSflj(true);
... ... @@ -411,12 +411,39 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
411 411 ReportUtils ee = new ReportUtils();
412 412 List<Iterator<?>> list = new ArrayList<Iterator<?>>();
413 413 List<ScheduleRealInfo> scheduleRealInfos = scheduleRealInfoRepository.exportWaybill(jName, clZbh, lpName);
414   - ScheduleRealInfo scheduleRealInfo = scheduleRealInfoRepository.findOne(scheduleRealInfos.get(0).getId());
  414 + ScheduleRealInfo scheduleReal = scheduleRealInfoRepository.findOne(scheduleRealInfos.get(0).getId());
  415 +
  416 + DecimalFormat format = new DecimalFormat("0.00");
  417 + int cjbc = scheduleRealInfoRepository.findCjbc(jName, clZbh, lpName);
  418 + int ljbc = scheduleRealInfoRepository.findLjbc(jName, clZbh, lpName);
  419 + int jhbc = 0;
  420 + double jhlc = 0;
  421 + float realMileage = 0l,addMileage = 0l,remMileage = 0l;
  422 + Map<String,Object> map = new HashMap<String, Object>();
  423 + for(ScheduleRealInfo scheduleRealInfo : scheduleRealInfos){
  424 + if(scheduleRealInfo != null){
  425 + jhlc += scheduleRealInfo.getJhlc()==null?0:scheduleRealInfo.getJhlc();
  426 + realMileage += scheduleRealInfo.getRealMileage()==null?0:scheduleRealInfo.getRealMileage();
  427 + addMileage += scheduleRealInfo.getAddMileage()==null?0:scheduleRealInfo.getAddMileage();
  428 + remMileage += scheduleRealInfo.getRemMileage()==null?0:scheduleRealInfo.getRemMileage();
  429 + jhbc++;
  430 + }
  431 + }
  432 + map.put("jhlc", format.format(jhlc));
  433 + map.put("remMileage", format.format(remMileage));
  434 + map.put("addMileage", format.format(addMileage));
  435 + map.put("yygl", format.format(realMileage-addMileage));
  436 + map.put("ksgl", format.format(realMileage-addMileage));
  437 + map.put("realMileage", format.format(realMileage));
  438 + map.put("jhbc", jhbc);
  439 + map.put("cjbc", cjbc);
  440 + map.put("ljbc", ljbc);
  441 + map.put("sjbc", jhbc-cjbc+ljbc);
415 442  
416 443 String path = this.getClass().getResource("/").getPath()+"static\\pages\\forms\\";
417 444  
418 445 list.add(scheduleRealInfos.iterator());
419   - ee.excelReplace(list, new Object[] { scheduleRealInfo }, path+"mould\\waybill.xls",
  446 + ee.excelReplace(list, new Object[] { scheduleReal,map }, path+"mould\\waybill.xls",
420 447 path+"export\\" + jName + ".xls");
421 448 return scheduleRealInfos;
422 449 }
... ... @@ -463,20 +490,33 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
463 490 @Override
464 491 public Map<String, Object> realOutAdjust(Long id, String fcsjActual, String remarks) {
465 492 Map<String, Object> rs = new HashMap<>();
  493 + List<ScheduleRealInfo> ts = new ArrayList<>();
466 494 try {
467 495 ScheduleRealInfo sch = ScheduleBuffer.findOne(id);
468   - String rq = sdfMonth.format(sch.getScheduleDate());
469 496  
470   - sch.setFcsjActualTime(sdfMinute.parse(rq + " " + fcsjActual).getTime());
471   - sch.setFcsjActual(fcsjActual);
  497 + Long t = sdfMinute.parse(sch.getRealExecDate() + " " + fcsjActual).getTime();
  498 + /*sch.setFcsjActualTime(sdfMinute.parse(sch.getRealExecDate() + " " + fcsjActual).getTime());
  499 + sch.setFcsjActual(fcsjActual);*/
  500 + if(null != sch.getSjfcModel())
  501 + sch.getSjfcModel().setPersonTime(t);
  502 +
  503 + sch.setFcsjActualAll(t);
472 504 sch.addRemarks(remarks);
473   - //改变状态
  505 + sch.calcStatus();
  506 + /*//改变状态
474 507 if(sch.getZdsjActual() == null)
475   - sch.setStatus(1);
  508 + sch.setStatus(1);*/
476 509  
477 510 ScheduleBuffer.persistentList.add(sch);
  511 +
  512 + ts.add(sch);
  513 + //关联班次
  514 + if(sch.existDependent())
  515 + ts.add(sch.getTwins());
  516 +
478 517 rs.put("status", ResponseCode.SUCCESS);
479   - rs.put("t", sch);
  518 + //rs.put("t", sch);
  519 + rs.put("ts", ts);
480 520 } catch (Exception e) {
481 521 logger.error("", e);
482 522 rs.put("status", ResponseCode.ERROR);
... ... @@ -498,7 +538,6 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
498 538 rs.put("status", ResponseCode.SUCCESS);
499 539 rs.put("t", sch);
500 540  
501   - // 将班次状态还原,并由子线程去匹配到离站
502 541 }
503 542 } catch (Exception e) {
504 543 logger.error("", e);
... ... @@ -510,19 +549,26 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
510 549 @Override
511 550 public Map<String, Object> revokeRealOutgo(Long id) {
512 551 Map<String, Object> rs = new HashMap<>();
  552 + List<ScheduleRealInfo> ts = new ArrayList<>();
  553 +
513 554 try {
514 555 ScheduleRealInfo sch = ScheduleBuffer.findOne(id);
515 556 if (sch.getFcsjActual() == null) {
516 557 rs.put("status", ResponseCode.ERROR);
517 558 rs.put("msg", "无实发时间,无法撤销!");
518 559 } else {
519   - sch.setStatus(0);
520   - sch.setFcsjActual(null);
521   - sch.setFcsjActualTime(null);
  560 + sch.revokeRealOutgo();
522 561 rs.put("status", ResponseCode.SUCCESS);
523   - rs.put("t", sch);
  562 +
  563 + ts.add(sch);
  564 + if(sch.existDependent()){
  565 + //关联班次也撤销
  566 + sch.getTwins().revokeRealOutgo();
  567 + ts.add(sch.getTwins());
  568 + }
  569 +
  570 + rs.put("ts", ts);
524 571  
525   - // 将班次状态还原,并由子线程去匹配到离站
526 572 }
527 573 } catch (Exception e) {
528 574 logger.error("", e);
... ... @@ -579,6 +625,7 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
579 625 @Override
580 626 public Map<String, Object> schInfoFineTune(Map<String, String> map) {
581 627 Map<String, Object> rs = new HashMap<>();
  628 + List<ScheduleRealInfo> ts = new ArrayList<>();
582 629 try {
583 630 Long id = Long.parseLong(map.get("id"));
584 631 //班次类型
... ... @@ -614,37 +661,64 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
614 661 sch.setBcType(bcType);
615 662 sch.setClZbh(clZbh);
616 663 sch.setFcsjAll(fcsj);
  664 +
617 665 if(StringUtils.isNotBlank(fcsjActual)){
618   - //调整实发
619   - sch.setFcsjActualAll(fcsjActual);
620   - sch.setStatus(1);
  666 +
  667 + if(!fcsjActual.equals(sch.getFcsjActual())){
  668 + //调整实发
  669 + sch.setFcsjActualAll(fcsjActual);
  670 + if(null != sch.getSjfcModel())
  671 + sch.getSjfcModel().setPersonTime(sch.getFcsjActualTime());
  672 + }
621 673 }
622 674 else{
623   - sch.setFcsjActual(null);
  675 + /*sch.setFcsjActual(null);
624 676 sch.setFcsjActualTime(null);
  677 + if(null != sch.getSjfcModel())
  678 + sch.getSjfcModel().resetNull();*/
  679 + //撤销实发
  680 + revokeRealOutgo(sch.getId());
625 681 }
626 682  
  683 + //实达时间
627 684 if(StringUtils.isNotBlank(zdsjActual)){
628   - //调整实达
629   - sch.setZdsjActualAll(zdsjActual);
630   - sch.setStatus(2);
631   - //下一班次起点到达
632   - ScheduleRealInfo next = ScheduleBuffer.getNext(sch);
633   - next.setQdzArrDateSJ(zdsjActual);
634   - rs.put("nextSch", next);
  685 + if(!zdsjActual.equals(sch.getZdsjActual())){
  686 + //调整实达
  687 + sch.setZdsjActualAll(zdsjActual);
  688 + //下一班次起点到达时间
  689 + ScheduleRealInfo next = ScheduleBuffer.getNext(sch);
  690 + next.setQdzArrDateSJ(zdsjActual);
  691 + ts.add(next);
  692 + }
635 693 }
636   - else{
637   - sch.setZdsjActual(null);
  694 + else {
  695 + //清除实达时间
  696 + sch.clearZdsjActual();
  697 + /*sch.setZdsjActual(null);
638 698 sch.setZdsjActualTime(null);
  699 + if(null != sch.getSjddModel())
  700 + sch.getSjddModel().resetNull();*/
  701 +
  702 + //清除下一班次起点到达时间
  703 + ScheduleRealInfo next = ScheduleBuffer.getNext(sch);
  704 + next.setQdzArrDateSJ(null);
  705 + ts.add(next);
639 706 }
640 707  
641 708 sch.setRemarks(remarks);
642 709 }
643 710  
  711 + //班次状态
  712 + sch.calcStatus();
644 713 ScheduleBuffer.persistentList.add(sch);
  714 + //页面需要更新的班次信息
  715 + ts.add(sch);
  716 + if(sch.existDependent())
  717 + ts.add(sch.getTwins());
645 718  
646 719 rs.put("status", ResponseCode.SUCCESS);
647   - rs.put("t", sch);
  720 + rs.put("ts", ts);
  721 + //rs.put("t", sch);
648 722 } catch (Exception e) {
649 723 logger.error("", e);
650 724 rs.put("status", ResponseCode.ERROR);
... ...
src/main/java/com/bsth/util/BatchSaveUtils.java
... ... @@ -8,6 +8,10 @@ import java.sql.ResultSet;
8 8 import java.util.ArrayList;
9 9 import java.util.List;
10 10  
  11 +import javax.persistence.ManyToMany;
  12 +import javax.persistence.ManyToOne;
  13 +import javax.persistence.OneToMany;
  14 +import javax.persistence.OneToOne;
11 15 import javax.persistence.Table;
12 16 import javax.persistence.Transient;
13 17  
... ... @@ -138,6 +142,12 @@ public class BatchSaveUtils&lt;T&gt; {
138 142 //忽略 Transient 字段
139 143 if(field.getAnnotation(Transient.class) != null)
140 144 continue;
  145 + //忽略关联
  146 + if(field.getAnnotation(OneToMany.class) != null
  147 + || field.getAnnotation(OneToOne.class) != null
  148 + || field.getAnnotation(ManyToOne.class) != null
  149 + || field.getAnnotation(ManyToMany.class) != null)
  150 + continue;
141 151 fs.add(field);
142 152 }
143 153 return fs;
... ...
src/main/java/com/bsth/util/DateUtils.java
... ... @@ -32,6 +32,16 @@ public class DateUtils {
32 32 return (int) (cal.getTimeInMillis() / 1000);
33 33 }
34 34  
  35 + // 获得当天24点时间 毫秒
  36 + public static Long getTimesnight2() {
  37 + Calendar cal = Calendar.getInstance();
  38 + cal.set(Calendar.HOUR_OF_DAY, 24);
  39 + cal.set(Calendar.SECOND, 0);
  40 + cal.set(Calendar.MINUTE, 0);
  41 + cal.set(Calendar.MILLISECOND, 0);
  42 + return cal.getTimeInMillis();
  43 + }
  44 +
35 45 public static Long getTimesnight(Calendar cal) {
36 46 cal.set(Calendar.HOUR_OF_DAY, 24);
37 47 cal.set(Calendar.SECOND, 0);
... ...
src/main/java/com/bsth/util/ReportUtils.java
... ... @@ -4,8 +4,12 @@ import java.io.File;
4 4 import java.io.FileInputStream;
5 5 import java.io.FileOutputStream;
6 6 import java.util.ArrayList;
  7 +import java.util.HashMap;
7 8 import java.util.Iterator;
8 9 import java.util.List;
  10 +import java.util.Map;
  11 +import java.util.regex.Matcher;
  12 +import java.util.regex.Pattern;
9 13  
10 14 import org.apache.poi.hssf.usermodel.HSSFCell;
11 15 import org.apache.poi.hssf.usermodel.HSSFCellStyle;
... ... @@ -65,8 +69,8 @@ public class ReportUtils {
65 69 continue;
66 70 }
67 71 // 取得每列的内容,如果列内容是$key$格式,则替换内容
68   - key = cell.getStringCellValue();
69   - if (key.indexOf("$") != -1 || key.indexOf("#list#") != -1) {
  72 + key = getCellValue(cell);
  73 + if (key != null && (key.indexOf("$") != -1 || key.indexOf("#list#") != -1)) {
70 74 // * 列中内容有#list#,则表示该行为模板行,需要以该行为模板
71 75 // * 例如:模板行格式 #list#0_0 $Car.id$
72 76 // * 第一个0表示需要在list中取iterator的索引值
... ... @@ -86,8 +90,8 @@ public class ReportUtils {
86 90 i += rowCount;
87 91 break;
88 92 } else {
89   - // 直接填充数据的列,从对象数组中取得值
90   - getValueAndSetCellValue(cell, key, tArray);
  93 + // 直接填充数据的列,从对象数组中取得值,这里的数组不传值
  94 + getValueAndSetCellValue(cell, key, tArray, new String[]{""});
91 95 }
92 96 }
93 97  
... ... @@ -104,6 +108,47 @@ public class ReportUtils {
104 108 }
105 109 }
106 110  
  111 + public String getCellValue(HSSFCell cell) {
  112 + int cellType = 0;
  113 + String result = "";
  114 + double d;
  115 + if(cell != null) {
  116 + // 获取列数据类型
  117 + cellType = cell.getCellType();
  118 + // 不同列数据类型,取值方法不同
  119 + switch(cellType) {
  120 + // String
  121 + case HSSFCell.CELL_TYPE_STRING:
  122 + result = cell.getStringCellValue().toString();
  123 + break;
  124 + // numeric类型,excel中,日期格式会转成数字格式存储
  125 + case HSSFCell.CELL_TYPE_NUMERIC:
  126 + result = cell.getNumericCellValue()+"";
  127 + break;
  128 + // 公式类型
  129 + case HSSFCell.CELL_TYPE_FORMULA:
  130 + result = cell.getCellFormula() + "";
  131 + break;
  132 + // boolean类型
  133 + case HSSFCell.CELL_TYPE_BOOLEAN:
  134 + result = cell.getBooleanCellValue() + "";
  135 + break;
  136 + // 空格
  137 + case HSSFCell.CELL_TYPE_BLANK:
  138 + result = null;
  139 + break;
  140 + // 错误值
  141 + case HSSFCell.CELL_TYPE_ERROR:
  142 + result = null;
  143 + break;
  144 + default :
  145 + System.out.println("其它");
  146 + break;
  147 + }
  148 + }
  149 + return result;
  150 + }
  151 +
107 152 /**
108 153 * 根据iterator,以及模板中的标识,填充模板
109 154 *
... ... @@ -130,6 +175,7 @@ public class ReportUtils {
130 175 HSSFRow newRow = null;
131 176 int tmpCellNum = 0;
132 177 int k = 0;
  178 + int listIndex = 0;
133 179 // 取得模板行
134 180 HSSFRow orgRow = sheet.getRow(index);
135 181 try {
... ... @@ -152,7 +198,7 @@ public class ReportUtils {
152 198 tmpCellNum = newRow.getLastCellNum();
153 199 for (int l = 0; l < tmpCellNum; l++) {
154 200 cell = newRow.getCell(l);
155   - key = cell.getStringCellValue();
  201 + key = getCellValue(cell);
156 202 /**
157 203 * 如果单无格内容为#list#,表示该行是模板行 #list#0_0
158 204 * 第一个0表示需要在list中取iterator的索引值
... ... @@ -168,8 +214,10 @@ public class ReportUtils {
168 214 if (key.trim().indexOf(" ") != -1) {
169 215 key = key.split(" ")[1];
170 216 }
171   - getValueAndSetCellValue(cell, key, obj);
  217 + getValueAndSetCellValue(cell, key, obj,new String[]{listIndex+""});
172 218 }
  219 + // list的数量
  220 + listIndex ++;
173 221 }
174 222 } catch (Exception e) {
175 223 e.printStackTrace();
... ... @@ -180,42 +228,58 @@ public class ReportUtils {
180 228 /**
181 229 * 取到相应的值并填入相应的列中
182 230 *
183   - * @param cell
184   - * 列
185   - * @param key
186   - * 列内容
187   - * @param obj
188   - * 数据源对象
  231 + * @param cell 列
  232 + * @param key 列内容
  233 + * @param obj 数据源对象
  234 + * @param args 其他参数 数组
  235 + * 数组内容:
  236 + * 0位:在list中的第几条数据
189 237 */
190   - private void getValueAndSetCellValue(HSSFCell cell, String key, Object obj) {
  238 + private void getValueAndSetCellValue(HSSFCell cell, String key, Object obj, String[] args) {
191 239 try {
192 240 // 保有存单元格的内容
193 241 String cellValue = key = key.replace("\\n", "");
194 242 String tmpKey;
195   - // 循环截取两个$中间的内容,反射出值
196   - while (key.indexOf("$") != -1) {
197   - key = key.substring(key.indexOf("$") + 1);
198   - // 取两个$中间的内容
199   - tmpKey = key.substring(0, key.indexOf("$"));
200   - key = key.substring(key.indexOf("$") + 1);
201   - // 如果内容是如下格式Cars.id,则从obj中值得相应的对象的值
202   - if (tmpKey.indexOf(".") != -1) {
203   - String className = tmpKey.substring(0, tmpKey.indexOf("."));
204   - // 取得类的全限定名
205   - String classWholeName = packaegName + className;
206   - String fieldName = tmpKey.substring(tmpKey.indexOf(".") + 1);
207   - // 如果obj是数组,循环判断哪个对象是对应的
208   - if (obj instanceof Object[]) {
209   - Object[] objs = (Object[]) obj;
210   - for (int k = 0; k < objs.length; k++) {
211   - if (objs[k].getClass().getName().equals(classWholeName)) {
212   - cellValue = cellValue.replace("$" + tmpKey
213   - + "$", getKeyValue(objs[k], fieldName)
214   - + "");
  243 + // 判断单元格内容是否是公式
  244 + if(cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA){
  245 + Pattern p=Pattern.compile("(\\d+)"); //
  246 + Matcher m=p.matcher(key);
  247 + if(m.find()){
  248 + cellValue = key.replace(m.group(1),
  249 + Integer.valueOf(m.group(1))+Integer.valueOf(args[0])+"");
  250 + cell.setCellFormula(cellValue);
  251 + return;
  252 + }
  253 + }else{//其他格式
  254 +
  255 + // 循环截取两个$中间的内容,反射出值
  256 + while (key.indexOf("$") != -1) {
  257 + key = key.substring(key.indexOf("$") + 1);
  258 + // 取两个$中间的内容
  259 + tmpKey = key.substring(0, key.indexOf("$"));
  260 + key = key.substring(key.indexOf("$") + 1);
  261 + // 如果内容是如下格式Cars.id,则从obj中值得相应的对象的值
  262 + if (tmpKey.indexOf(".") != -1) {
  263 + String className = tmpKey.substring(0, tmpKey.indexOf("."));
  264 + // 取得类的全限定名
  265 + String classWholeName = packaegName + className;
  266 + String fieldName = tmpKey.substring(tmpKey.indexOf(".") + 1);
  267 + // 如果obj是数组,循环判断哪个对象是对应的
  268 + if (obj instanceof Object[]) {
  269 + Object[] objs = (Object[]) obj;
  270 + for (int k = 0; k < objs.length; k++) {
  271 + if (objs[k].getClass().getName().equals(classWholeName)) {
  272 + cellValue = cellValue.replace("$" + tmpKey
  273 + + "$", getKeyValue(objs[k], fieldName)
  274 + + "");
  275 + } else if(objs[k].getClass().getName().equals("java.util.HashMap")){
  276 + Map<String,Object> map = (HashMap<String,Object>)objs[k];
  277 + cellValue = cellValue.replace("$" + tmpKey + "$",map.get(fieldName)+"");
  278 + }
215 279 }
  280 + } else if (obj.getClass().getName().equals(classWholeName)) {
  281 + cellValue = cellValue.replace("$" + tmpKey + "$",getKeyValue(obj, fieldName) + "");
216 282 }
217   - } else if (obj.getClass().getName().equals(classWholeName)) {
218   - cellValue = cellValue.replace("$" + tmpKey + "$",getKeyValue(obj, fieldName) + "");
219 283 }
220 284 }
221 285 }
... ... @@ -266,16 +330,16 @@ public class ReportUtils {
266 330 srr.setXlName("abc11");
267 331  
268 332 ScheduleRealInfo sr = new ScheduleRealInfo();
269   - sr.setId((long) 22);
270   - sr.setXlName("abc22");
  333 + sr.setZdsj("06:10");
  334 + sr.setZdsjActual("06:25");
271 335 dataList.add(sr);
272 336 sr = new ScheduleRealInfo();
273   - sr.setId((long) 33);
274   - sr.setXlName("abc33");
  337 + sr.setZdsj("06:20");
  338 + sr.setZdsjActual("");
275 339 dataList.add(sr);
276 340 list.add(dataList.iterator());
277 341  
278   - ee.excelReplace(list, new Object[] { srr }, "D:\\55.xls",
  342 + ee.excelReplace(list, new Object[] { srr }, "D:\\waybill.xls",
279 343 "D:\\22.xls");
280 344 System.out.println("ok");
281 345 } catch (Exception e) {
... ...
src/main/java/com/bsth/vehicle/directive/buffer/DirectiveBuffer.java
... ... @@ -14,6 +14,7 @@ import org.springframework.stereotype.Component;
14 14  
15 15 import com.alibaba.fastjson.JSON;
16 16 import com.alibaba.fastjson.JSONObject;
  17 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
17 18 import com.bsth.service.realcontrol.buffer.ScheduleBuffer;
18 19 import com.bsth.vehicle.common.CommonMapped;
19 20 import com.bsth.vehicle.directive.entity.Directive60;
... ... @@ -25,6 +26,7 @@ import com.bsth.vehicle.directive.entity.LineChange;
25 26 import com.bsth.vehicle.directive.repository.Directive60Repository;
26 27 import com.bsth.vehicle.directive.repository.Directive80Repository;
27 28 import com.bsth.vehicle.directive.repository.LineChangeRepository;
  29 +import com.bsth.vehicle.directive.service.DirectiveService;
28 30 import com.bsth.vehicle.directive.util.HttpUtils;
29 31 import com.bsth.websocket.handler.RealControlSocketHandler;
30 32 import com.google.common.collect.ArrayListMultimap;
... ... @@ -49,6 +51,9 @@ public class DirectiveBuffer {
49 51 @Autowired
50 52 LineChangeRepository lineChangeRepository;
51 53  
  54 + @Autowired
  55 + DirectiveService directiveService;
  56 +
52 57  
53 58 /**
54 59 * 等待入库的调度指令
... ... @@ -123,7 +128,11 @@ public class DirectiveBuffer {
123 128  
124 129 if(directive.isDispatch()){
125 130 //更新班次状态
126   - directive.getSch().setDirectiveState(reply.getStatus() * 100);
  131 + ScheduleRealInfo sch = directive.getSch();
  132 + sch.setDirectiveState(reply.getStatus() * 100);
  133 + ScheduleBuffer.persistentList.add(sch);
  134 + //通知页面
  135 + directiveService.sendDirectiveToPage(sch);
127 136 }
128 137 transientList.add(directive);
129 138 }
... ...
src/main/java/com/bsth/vehicle/directive/entity/Directive60.java
... ... @@ -59,12 +59,12 @@ public class Directive60 {
59 59 /**
60 60 * 46上行
61 61 */
62   - private Short reply46;
  62 + private Short reply46 = -1;
63 63  
64 64 /**
65 65 * 47上行
66 66 */
67   - private Short reply47;
  67 + private Short reply47 = -1;
68 68  
69 69 /**
70 70 * 是否是调度指令
... ...
src/main/java/com/bsth/vehicle/directive/service/DirectiveService.java
... ... @@ -59,4 +59,12 @@ public interface DirectiveService extends BaseService&lt;Directive60, Integer&gt;{
59 59 * @throws
60 60 */
61 61 int upDownChange(String nbbm, Integer upDown);
  62 +
  63 + /**
  64 + *
  65 + * @Title: sendDirectiveState
  66 + * @Description: TODO(向页面推送班次指令状态)
  67 + * @throws
  68 + */
  69 + void sendDirectiveToPage(ScheduleRealInfo sch);
62 70 }
... ...
src/main/java/com/bsth/vehicle/directive/service/DirectiveServiceImpl.java
... ... @@ -85,7 +85,7 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive60, Integer&gt;
85 85 try {
86 86 //如果发车时间距当前时间较远,则不发送
87 87 if(Math.abs(sch.getFcsjT() - System.currentTimeMillis()) > schDiff){
88   - return 0;
  88 + return -2;
89 89 }
90 90  
91 91 String text = "已完成" + finish + "个班次,下一发车时间" + sdfHHmm.format(new Date(sch.getFcsjT()))
... ... @@ -111,7 +111,7 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive60, Integer&gt;
111 111 directive.setSch(sch);
112 112 DirectiveBuffer.put(directive);
113 113 //通知页面,消息已发出
114   - sendDirectiveState(sch);
  114 + sendDirectiveToPage(sch);
115 115 }else{
116 116 logger.error("send60Phrase error, code: " + code);
117 117 }
... ... @@ -124,7 +124,8 @@ public class DirectiveServiceImpl extends BaseServiceImpl&lt;Directive60, Integer&gt;
124 124 * @Description: TODO(向页面推送班次指令状态)
125 125 * @throws
126 126 */
127   - public void sendDirectiveState(ScheduleRealInfo sch){
  127 + @Override
  128 + public void sendDirectiveToPage(ScheduleRealInfo sch){
128 129 JSONObject json = new JSONObject();
129 130 json.put("fn", "directive");
130 131 json.put("t", sch);
... ...
src/main/java/com/bsth/vehicle/directive/thread/FirstScheduleIssuedThread.java
... ... @@ -27,13 +27,13 @@ public class FirstScheduleIssuedThread extends Thread{
27 27 @Override
28 28 public void run() {
29 29  
30   - Set<String> keys = ScheduleBuffer.vehSchListMap.keySet();
  30 + Set<String> keys = ScheduleBuffer.carSchListMap.keySet();
31 31 List<ScheduleRealInfo> list;
32 32  
33 33 Long t = System.currentTimeMillis();
34 34 ScheduleRealInfo sch;
35 35 for(String nbbm : keys){
36   - list = ScheduleBuffer.vehSchListMap.get(nbbm);
  36 + list = ScheduleBuffer.carSchListMap.get(nbbm);
37 37  
38 38 if(list.size() == 0)
39 39 continue;
... ...
src/main/java/com/bsth/vehicle/gpsdata/GpsArrivalStationThread_old.java
... ... @@ -64,7 +64,7 @@ public class GpsArrivalStationThread_old extends Thread{
64 64 System.out.println("开始...");
65 65 List<ScheduleRealInfo> schList;
66 66 for(String key : keySet){
67   - schList = extractSched(ScheduleBuffer.vehSchListMap.get(key));
  67 + schList = extractSched(ScheduleBuffer.carSchListMap.get(key));
68 68 if(null != schList)
69 69 match(GpsArrivalDataBuffer.allMap.get(key), schList);
70 70 }
... ...
src/main/java/com/bsth/vehicle/gpsdata/GpsArrivalStationThread.java renamed to src/main/java/com/bsth/vehicle/gpsdata/GpsArrivalThread.java
... ... @@ -7,7 +7,6 @@ import java.text.ParseException;
7 7 import java.text.SimpleDateFormat;
8 8 import java.util.ArrayList;
9 9 import java.util.Calendar;
10   -import java.util.Date;
11 10 import java.util.HashSet;
12 11 import java.util.List;
13 12 import java.util.Set;
... ... @@ -17,13 +16,11 @@ import org.slf4j.LoggerFactory;
17 16 import org.springframework.beans.factory.annotation.Autowired;
18 17 import org.springframework.stereotype.Component;
19 18  
20   -import com.alibaba.fastjson.JSONObject;
21 19 import com.bsth.entity.realcontrol.ScheduleRealInfo;
22   -import com.bsth.service.realcontrol.buffer.ScheduleBuffer;
23 20 import com.bsth.util.DateUtils;
24 21 import com.bsth.util.db.DBUtils_MS;
25   -import com.bsth.vehicle.common.CommonMapped;
26 22 import com.bsth.vehicle.directive.service.DirectiveService;
  23 +import com.bsth.vehicle.gpsdata.arrival.MatchService;
27 24 import com.bsth.vehicle.gpsdata.buffer.GpsArrivalDataBuffer;
28 25 import com.bsth.vehicle.gpsdata.entity.ArrivalInfo;
29 26 import com.bsth.websocket.handler.RealControlSocketHandler;
... ... @@ -31,13 +28,13 @@ import com.bsth.websocket.handler.RealControlSocketHandler;
31 28 /**
32 29 *
33 30 * @ClassName: GpsArrivalStationThread
34   - * @Description: TODO(GPS到离站)
  31 + * @Description: TODO(定时从数据库加载到离站数据)
35 32 * @author PanZhao
36 33 * @date 2016年6月27日 上午10:58:13
37 34 *
38 35 */
39 36 @Component
40   -public class GpsArrivalStationThread extends Thread{
  37 +public class GpsArrivalThread extends Thread{
41 38  
42 39 Logger logger = LoggerFactory.getLogger(this.getClass());
43 40 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
... ... @@ -60,8 +57,26 @@ public class GpsArrivalStationThread extends Thread{
60 57 }
61 58 //缓存
62 59 GpsArrivalDataBuffer.putAll(list);
  60 +
  61 + //有新到离站数据的线路
  62 + Set<String> newSet = new HashSet<>();
  63 + for(ArrivalInfo arr : list)
  64 + newSet.add(arr.getLineCode());
  65 +
  66 + //启动对应的匹配线程
  67 + for(String lineCode : newSet){
  68 + MatchService.addService(lineCode);
  69 + }
  70 +
  71 +
  72 + /*try {
  73 + Bootstrap bs = Bootstrap.instance();
  74 + bs.start();
  75 + } catch (Exception e) {
  76 + e.printStackTrace();
  77 + }*/
63 78  
64   - //车辆
  79 + /*//车辆
65 80 Set<String> set = new HashSet<>();
66 81 for(ArrivalInfo arr : list)
67 82 set.add(CommonMapped.vehicDeviceBiMap.get(arr.getDeviceId()));
... ... @@ -109,10 +124,10 @@ public class GpsArrivalStationThread extends Thread{
109 124 }catch(Exception e){
110 125 e.printStackTrace();
111 126 }
112   - }
  127 + }*/
113 128 }
114 129  
115   - public ArrivalInfo[] match(List<ArrivalInfo> arrList, ScheduleRealInfo sch){
  130 +/* public ArrivalInfo[] match(List<ArrivalInfo> arrList, ScheduleRealInfo sch){
116 131 //进出分组
117 132 List<ArrivalInfo> in = new ArrayList<>(), out = new ArrayList<>();
118 133 for(ArrivalInfo arr : arrList){
... ... @@ -134,7 +149,7 @@ public class GpsArrivalStationThread extends Thread{
134 149 }
135 150  
136 151 public ArrivalInfo matchOut(List<ArrivalInfo> arrList, ScheduleRealInfo sch){
137   - Long space = /*ScheduleBuffer.schSpaceMap.get(sch.getXlBm() + "_" + sch.getXlDir())*/diff;
  152 + Long space = ScheduleBuffer.schSpaceMap.get(sch.getXlBm() + "_" + sch.getXlDir())diff;
138 153 for(ArrivalInfo arr : arrList){
139 154 if(arr.getStopNo().equals(sch.getQdzCode())
140 155 && Math.abs((arr.getTs() - sch.getFcsjT())) < space){
... ... @@ -148,7 +163,7 @@ public class GpsArrivalStationThread extends Thread{
148 163 }
149 164  
150 165 public ArrivalInfo matchIn(List<ArrivalInfo> arrList, ScheduleRealInfo sch){
151   - Long space = /*ScheduleBuffer.schSpaceMap.get(sch.getXlBm() + "_" + sch.getXlDir())*/diff;
  166 + Long space = ScheduleBuffer.schSpaceMap.get(sch.getXlBm() + "_" + sch.getXlDir())diff;
152 167 for(ArrivalInfo arr : arrList){
153 168 if(arr.getStopNo().equals(sch.getZdzCode())
154 169 && Math.abs((arr.getTs() - sch.getZdsjT())) < space){
... ... @@ -158,7 +173,7 @@ public class GpsArrivalStationThread extends Thread{
158 173 }
159 174 }
160 175 return null;
161   - }
  176 + }*/
162 177  
163 178  
164 179 /**
... ... @@ -167,7 +182,7 @@ public class GpsArrivalStationThread extends Thread{
167 182 * @param @param schedule 班次
168 183 * @throws
169 184 */
170   - public void sendFcsj(ScheduleRealInfo schedule){
  185 +/* public void sendFcsj(ScheduleRealInfo schedule){
171 186 JSONObject json = new JSONObject();
172 187 json.put("fn", "faChe");
173 188 json.put("t", schedule);
... ... @@ -175,12 +190,12 @@ public class GpsArrivalStationThread extends Thread{
175 190 socketHandler.sendMessageToLine(Integer.parseInt(schedule.getXlBm()), json.toJSONString());
176 191 }
177 192  
178   - /**
  193 + *//**
179 194 * @Title: sendFcsj
180 195 * @Description: TODO(推送到达终点时间)
181 196 * @param @param schedule 班次
182 197 * @throws
183   - */
  198 + *//*
184 199 public void sendZdsj(ScheduleRealInfo schedule,ScheduleRealInfo nextSch, int finish){
185 200 JSONObject json = new JSONObject();
186 201 json.put("fn", "zhongDian");
... ... @@ -190,7 +205,7 @@ public class GpsArrivalStationThread extends Thread{
190 205 json.put("dataStr", sdf.format(new Date()));
191 206  
192 207 socketHandler.sendMessageToLine(Integer.parseInt(schedule.getXlBm()), json.toJSONString());
193   - }
  208 + }*/
194 209  
195 210 /**
196 211 * @throws ParseException
... ... @@ -210,7 +225,7 @@ public class GpsArrivalStationThread extends Thread{
210 225 GpsArrivalDataBuffer.markTime = DateUtils.getTimesmorning() * 1000L;
211 226 }
212 227  
213   - String sql = "select * from bsth_c_arrival_info where weeks_year=? and create_date > ? order by ts";
  228 + String sql = "select * from bsth_c_arrival_info where weeks_year=? and ts > ? order by ts";
214 229  
215 230 List<ArrivalInfo> list = new ArrayList<>();
216 231 Connection conn = null;
... ... @@ -219,8 +234,8 @@ public class GpsArrivalStationThread extends Thread{
219 234 try {
220 235 conn = DBUtils_MS.getConnection();
221 236 ps = conn.prepareStatement(sql);
222   - ps.setInt(1, weeks_year/*28*/);
223   - ps.setLong(2, GpsArrivalDataBuffer.markTime/*1467853749000L*/);
  237 + ps.setInt(1, weeks_year/*30*/);
  238 + ps.setLong(2, GpsArrivalDataBuffer.markTime/*1461361377000L*/);
224 239  
225 240 Long t = System.currentTimeMillis();
226 241 rs = ps.executeQuery();
... ... @@ -230,6 +245,7 @@ public class GpsArrivalStationThread extends Thread{
230 245 , rs.getInt("up_down"), rs.getString("stop_no"), rs.getInt("in_out"), rs.getDate("create_date"), rs.getInt("weeks_year")));
231 246 }
232 247  
  248 + System.out.println("数量:" + list.size() + " ,markTime:" + GpsArrivalDataBuffer.markTime);
233 249 //重新打时间标记
234 250 GpsArrivalDataBuffer.markTime = t;
235 251  
... ...
src/main/java/com/bsth/vehicle/gpsdata/arrival/MatchService.java 0 → 100644
  1 +package com.bsth.vehicle.gpsdata.arrival;
  2 +
  3 +import java.util.concurrent.ArrayBlockingQueue;
  4 +import java.util.concurrent.ThreadPoolExecutor;
  5 +import java.util.concurrent.TimeUnit;
  6 +
  7 +public class MatchService {
  8 +
  9 + static MatchService bs;
  10 + static ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 20, 1, TimeUnit.SECONDS,
  11 + new ArrayBlockingQueue<Runnable>(3));
  12 +
  13 + /**
  14 + *
  15 + * @Title: addService
  16 + * @Description: TODO(添加一个任务)
  17 + * @throws
  18 + */
  19 + public static void addService(String lineCode) {
  20 + pool.execute(new ThreadPoolTask(lineCode));
  21 + }
  22 +}
... ...
src/main/java/com/bsth/vehicle/gpsdata/arrival/ThreadPoolTask.java 0 → 100644
  1 +package com.bsth.vehicle.gpsdata.arrival;
  2 +
  3 +import java.util.List;
  4 +import java.util.Set;
  5 +
  6 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  7 +import com.bsth.service.realcontrol.buffer.ScheduleBuffer;
  8 +import com.bsth.vehicle.gpsdata.arrival.match.ScheduleRealMatcher;
  9 +import com.bsth.vehicle.gpsdata.buffer.GpsArrivalDataBuffer;
  10 +import com.google.common.collect.ArrayListMultimap;
  11 +
  12 +public class ThreadPoolTask implements Runnable {
  13 +
  14 + String lineCode;
  15 +
  16 + public ThreadPoolTask(String lineCode) {
  17 + this.lineCode = lineCode;
  18 + }
  19 +
  20 + @Override
  21 + public void run() {
  22 + List<ScheduleRealInfo> allList = ScheduleBuffer.realSchedulListMap.get(lineCode);
  23 + //按车辆分组班次
  24 + ArrayListMultimap<String, ScheduleRealInfo> alMap = ArrayListMultimap.create();
  25 +
  26 + for(ScheduleRealInfo sch : allList){
  27 + //停车场即起点站的进出场班次不参与匹配
  28 + if(!sch.isParkIsFirstStation())
  29 + alMap.put(sch.getClZbh(), sch);
  30 + }
  31 +
  32 + //开始匹配
  33 + ScheduleRealMatcher srMatcher;
  34 + Set<String> ks = alMap.keySet();
  35 +
  36 + for(String nbbm : ks){
  37 +
  38 + srMatcher = new ScheduleRealMatcher(alMap.get(nbbm), GpsArrivalDataBuffer.pops(nbbm));
  39 +
  40 + //在这里应用各种匹配规则
  41 + srMatcher
  42 + .timeClosest()
  43 + .matchEnd();
  44 +
  45 + }
  46 + }
  47 +}
... ...
src/main/java/com/bsth/vehicle/gpsdata/arrival/entity/RealTimeModel.java 0 → 100644
  1 +package com.bsth.vehicle.gpsdata.arrival.entity;
  2 +
  3 +import javax.persistence.Entity;
  4 +import javax.persistence.GeneratedValue;
  5 +import javax.persistence.Id;
  6 +import javax.persistence.Table;
  7 +
  8 +
  9 +/**
  10 + *
  11 + * @ClassName: RealTimeModel
  12 + * @author PanZhao
  13 + * @date 2016年7月24日 下午5:00:26
  14 + *
  15 + */
  16 +@Entity
  17 +@Table(name = "bsth_s_real_time")
  18 +public class RealTimeModel {
  19 +
  20 + public RealTimeModel() {
  21 + }
  22 +
  23 + public RealTimeModel(String stationCode, int type) {
  24 + this.station = stationCode;
  25 + this.type = type;
  26 + }
  27 +
  28 + @Id
  29 + @GeneratedValue
  30 + private Integer id;
  31 +
  32 + /** 站点编码 */
  33 + private String station;
  34 +
  35 + /** GPS时间 */
  36 + private Long gpsTime;
  37 +
  38 + /** 0:GPS正常到离站,1:GPS信号丢失,通过定时定距预测 */
  39 + private Integer gpsStatus;
  40 +
  41 + /** 如gpsStatus 为1 ,则表示预测的GPS点和站点直线距离 */
  42 + private Double distance;
  43 +
  44 + /** GPS定时定距关联, 格式为:设备号_时间戳 */
  45 + private String gps;
  46 +
  47 + /** 人工录入的实际时间 */
  48 + private Long personTime;
  49 +
  50 + /** RFID 时间 */
  51 + private Long rfidTime;
  52 +
  53 + /** 0: 进, 1:出 */
  54 + private int type;
  55 +
  56 + /** 晚点时间 */
  57 + private Long late;
  58 +
  59 + public Integer getId() {
  60 + return id;
  61 + }
  62 +
  63 + public void setId(Integer id) {
  64 + this.id = id;
  65 + }
  66 +
  67 + public Long getGpsTime() {
  68 + return gpsTime;
  69 + }
  70 +
  71 + public RealTimeModel setGpsTime(Long gpsTime) {
  72 + this.gpsTime = gpsTime;
  73 + return this;
  74 + }
  75 +
  76 + public Integer getGpsStatus() {
  77 + return gpsStatus;
  78 + }
  79 +
  80 + public void setGpsStatus(Integer gpsStatus) {
  81 + this.gpsStatus = gpsStatus;
  82 + }
  83 +
  84 + public Double getDistance() {
  85 + return distance;
  86 + }
  87 +
  88 + public void setDistance(Double distance) {
  89 + this.distance = distance;
  90 + }
  91 +
  92 + public String getGps() {
  93 + return gps;
  94 + }
  95 +
  96 + public void setGps(String gps) {
  97 + this.gps = gps;
  98 + }
  99 +
  100 + public Long getPersonTime() {
  101 + return personTime;
  102 + }
  103 +
  104 + public void setPersonTime(Long personTime) {
  105 + this.personTime = personTime;
  106 + }
  107 +
  108 + public Long getRfidTime() {
  109 + return rfidTime;
  110 + }
  111 +
  112 + public void setRfidTime(Long rfidTime) {
  113 + this.rfidTime = rfidTime;
  114 + }
  115 +
  116 + public int getType() {
  117 + return type;
  118 + }
  119 +
  120 + public void setType(int type) {
  121 + this.type = type;
  122 + }
  123 +
  124 + public Long getLate() {
  125 + return late;
  126 + }
  127 +
  128 + public void setLate(Long late) {
  129 + this.late = late;
  130 + }
  131 +
  132 + public String getStation() {
  133 + return station;
  134 + }
  135 +
  136 + public void setStation(String station) {
  137 + this.station = station;
  138 + }
  139 +
  140 + public Long getTime(){
  141 + //人工录入优先级最高
  142 + if(personTime != null)
  143 + return personTime;
  144 +
  145 + //GPS其次
  146 + if(gpsTime != null)
  147 + return gpsTime;
  148 +
  149 + return null;
  150 + }
  151 +
  152 + public void resetNull(){
  153 + this.setGpsTime(null);
  154 + this.setPersonTime(null);
  155 + this.setRfidTime(null);
  156 + }
  157 +}
... ...
src/main/java/com/bsth/vehicle/gpsdata/arrival/match/ScheduleRealMatcher.java 0 → 100644
  1 +package com.bsth.vehicle.gpsdata.arrival.match;
  2 +
  3 +import java.text.SimpleDateFormat;
  4 +import java.util.ArrayList;
  5 +import java.util.Collections;
  6 +import java.util.Comparator;
  7 +import java.util.Date;
  8 +import java.util.HashMap;
  9 +import java.util.HashSet;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +import java.util.Set;
  13 +
  14 +import org.springframework.beans.BeansException;
  15 +import org.springframework.context.ApplicationContext;
  16 +import org.springframework.context.ApplicationContextAware;
  17 +import org.springframework.stereotype.Component;
  18 +
  19 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  20 +import com.bsth.service.realcontrol.buffer.ScheduleBuffer;
  21 +import com.bsth.vehicle.directive.service.DirectiveService;
  22 +import com.bsth.vehicle.gpsdata.arrival.entity.RealTimeModel;
  23 +import com.bsth.vehicle.gpsdata.entity.ArrivalInfo;
  24 +import com.bsth.websocket.handler.RealControlSocketHandler;
  25 +import com.fasterxml.jackson.core.JsonProcessingException;
  26 +import com.fasterxml.jackson.databind.ObjectMapper;
  27 +
  28 +/**
  29 + *
  30 + * @ClassName: ScheduleRealMatch
  31 + * @author PanZhao
  32 + * @date 2016年7月24日 下午5:19:04
  33 + *
  34 + */
  35 +@Component
  36 +public class ScheduleRealMatcher implements ApplicationContextAware{
  37 +
  38 + // Spring应用上下文环境
  39 + private static ApplicationContext applicationContext;
  40 +
  41 + /** 班次列表 */
  42 + List<ScheduleRealInfo> schs;
  43 +
  44 + /** 到离站列表 */
  45 + List<ArrivalInfo> arrivals;
  46 +
  47 + /** 出站数据 */
  48 + List<ArrivalInfo> outArrivals = new ArrayList<>();
  49 +
  50 + /** 进站数据 */
  51 + List<ArrivalInfo> inArrivals = new ArrayList<>();
  52 +
  53 + private static RealControlSocketHandler socketHandler;
  54 +
  55 + private static DirectiveService directiveService;
  56 +
  57 + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
  58 +
  59 + //最大班次间隔
  60 + int maxBcsj = 0;
  61 +
  62 + public ScheduleRealMatcher(){}
  63 +
  64 + public ScheduleRealMatcher(List<ScheduleRealInfo> schs, List<ArrivalInfo> arrivals) {
  65 + this.schs = schs;
  66 + this.arrivals = arrivals;
  67 + //排序
  68 + Collections.sort(schs, new Comparator<ScheduleRealInfo>() {
  69 + @Override
  70 + public int compare(ScheduleRealInfo s1, ScheduleRealInfo s2) {
  71 + return (int) (s1.getFcsjT() - s2.getFcsjT());
  72 + }
  73 + });
  74 +
  75 + Collections.sort(arrivals, new Comparator<ArrivalInfo>() {
  76 +
  77 + @Override
  78 + public int compare(ArrivalInfo a1, ArrivalInfo a2) {
  79 + return (int) (a1.getTs() - a2.getTs());
  80 + }
  81 + });
  82 +
  83 + //将进出数据拆分成2个集合
  84 + for(ArrivalInfo arr : arrivals){
  85 + if(arr.getInOut() == 0)
  86 + inArrivals.add(arr);
  87 + else if(arr.getInOut() == 1)
  88 + outArrivals.add(arr);
  89 + }
  90 +
  91 + for(ScheduleRealInfo sch : schs){
  92 + if(sch.getBcsj() != null && sch.getBcsj() > maxBcsj){
  93 + maxBcsj = sch.getBcsj();
  94 + }
  95 +
  96 + if(sch.getSjfcModel() == null)
  97 + sch.setSjfcModel(new RealTimeModel(sch.getQdzCode(), 1));
  98 + if(sch.getSjddModel() == null)
  99 + sch.setSjddModel(new RealTimeModel(sch.getZdzCode(), 0));
  100 + }
  101 + }
  102 +
  103 + /**
  104 + *
  105 + * @Title: timeClosest
  106 + * @Description: TODO(按照时间距离进行匹配)
  107 + * @throws
  108 + */
  109 + public ScheduleRealMatcher timeClosest(){
  110 + TimeClosestGPS.match(schs, inArrivals, outArrivals, maxBcsj);
  111 + return this;
  112 + }
  113 +
  114 + /**
  115 + *
  116 + * @Title: matchEnd
  117 + * @Description: TODO(匹配结束后做上发信使和下发调度指令)
  118 + * @throws
  119 + */
  120 + public void matchEnd(){
  121 +
  122 + for(ScheduleRealInfo sch : schs){
  123 + //按 RealTimeModel 的优先级赋予班次实际时间
  124 + //起点发出
  125 + if(sch.statusTostart()){
  126 +
  127 + //设置班次的实际发车时间
  128 + sch.setFcsjActualAll(sch.getSjfcModel().getTime());
  129 + //班次状态改为正在执行
  130 + sch.calcStatus();
  131 + ScheduleBuffer.persistentList.add(sch);
  132 +
  133 + if(sch.isFirstStationIsPark()){
  134 + ScheduleBuffer.persistentList.add(sch.getTwins());
  135 + sendFcsj(sch.getTwins());//推送到页面
  136 + }
  137 +
  138 + sendFcsj(sch);//推送到页面
  139 + }
  140 +
  141 + //终点到达
  142 + if(sch.statusToEnd()){
  143 +
  144 + //设置班次的实际终点时间
  145 + sch.setZdsjActualAll(sch.getSjddModel().getTime());
  146 + //完成当前班次
  147 + ScheduleRealInfo nextSch = ScheduleBuffer.finishSch(sch);
  148 +
  149 + if(sch.isFirstStationIsPark()){
  150 + ScheduleBuffer.persistentList.add(sch.getTwins());
  151 + sendFcsj(sch.getTwins());//推送到页面
  152 + }
  153 +
  154 + int finish = ScheduleBuffer.getFinishSchNo(sch.getClZbh());
  155 + if(nextSch != null){
  156 + //发送下一班次的调度指令
  157 + directiveService.send60Dispatch(nextSch, finish);
  158 + }
  159 +
  160 + sendZdsj(sch, nextSch, finish);//推送到页面
  161 + }
  162 + }
  163 + }
  164 +
  165 + /**
  166 + * @throws JsonProcessingException
  167 + * @throws NumberFormatException
  168 + * @Title: sendFcsj
  169 + * @Description: TODO(推送发车信息)
  170 + * @param @param schedule 班次
  171 + * @throws
  172 + */
  173 + public void sendFcsj(ScheduleRealInfo schedule) {
  174 + /*JSONObject json = new JSONObject();
  175 + json.put("fn", "faChe");
  176 + json.put("t", schedule);
  177 + json.put("dataStr", sdf.format(new Date()));*/
  178 +
  179 + Map<String, Object> map = new HashMap<>();
  180 + map.put("fn", "faChe");
  181 + map.put("t", schedule);
  182 + map.put("dataStr", sdf.format(new Date()));
  183 +
  184 + ObjectMapper mapper = new ObjectMapper();
  185 +
  186 + try{
  187 + socketHandler.sendMessageToLine(Integer.parseInt(schedule.getXlBm()), mapper.writeValueAsString(map));
  188 + }catch(Exception e){
  189 + e.printStackTrace();
  190 + }
  191 + }
  192 +
  193 + /**
  194 + * @throws JsonProcessingException
  195 + * @throws NumberFormatException
  196 + * @Title: sendFcsj
  197 + * @Description: TODO(推送到达终点时间)
  198 + * @param @param schedule 班次
  199 + * @throws
  200 + */
  201 + public void sendZdsj(ScheduleRealInfo schedule,ScheduleRealInfo nextSch, int finish) {
  202 + /*JSONObject json = new JSONObject();
  203 + json.put("fn", "zhongDian");
  204 + json.put("t", schedule);
  205 + json.put("nt", nextSch);
  206 + json.put("finish", finish);
  207 + json.put("dataStr", sdf.format(new Date()));*/
  208 +
  209 + Map<String, Object> map = new HashMap<>();
  210 + map.put("fn", "zhongDian");
  211 + map.put("t", schedule);
  212 + map.put("nt", nextSch);
  213 + map.put("finish", finish);
  214 + map.put("dataStr", sdf.format(new Date()));
  215 +
  216 + ObjectMapper mapper = new ObjectMapper();
  217 +
  218 + try{
  219 + socketHandler.sendMessageToLine(Integer.parseInt(schedule.getXlBm()), mapper.writeValueAsString(map));
  220 + }catch(Exception e){
  221 + e.printStackTrace();
  222 + }
  223 + }
  224 +
  225 + @Override
  226 + public void setApplicationContext(ApplicationContext arg0) throws BeansException {
  227 + applicationContext = arg0;
  228 +
  229 + socketHandler = applicationContext.getBean(RealControlSocketHandler.class);
  230 + directiveService = applicationContext.getBean(DirectiveService.class);
  231 + }
  232 +}
... ...
src/main/java/com/bsth/vehicle/gpsdata/arrival/match/TimeClosestGPS.java 0 → 100644
  1 +package com.bsth.vehicle.gpsdata.arrival.match;
  2 +
  3 +import java.text.SimpleDateFormat;
  4 +import java.util.List;
  5 +
  6 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  7 +import com.bsth.vehicle.gpsdata.arrival.entity.RealTimeModel;
  8 +import com.bsth.vehicle.gpsdata.entity.ArrivalInfo;
  9 +import com.google.common.collect.BiMap;
  10 +import com.google.common.collect.HashBiMap;
  11 +
  12 +/**
  13 + *
  14 + * @ClassName: TimeClosest
  15 + * @Description: TODO(按时间距离最近进行匹配)
  16 + * @author PanZhao
  17 + * @date 2016年7月24日 下午5:27:27
  18 + *
  19 + */
  20 +public class TimeClosestGPS {
  21 +
  22 + static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
  23 +
  24 + public static void match(List<ScheduleRealInfo> schs,
  25 + List<ArrivalInfo> inList, List<ArrivalInfo> outList, int maxBcsj) {
  26 +
  27 + //班次ID 和 离站数据 一对一映射
  28 + BiMap<Long, String> outBiMap = HashBiMap.create();
  29 + //班次ID 和 到站数据 一对一映射
  30 + BiMap<Long, String> inBiMap = HashBiMap.create();
  31 +
  32 + Long spaceTime = maxBcsj * 60 * 1000 * 2L;
  33 +
  34 + RealTimeModel sjfcModel, sjddModel;
  35 + for(ScheduleRealInfo sch : schs){
  36 +
  37 + sjfcModel = sch.getSjfcModel();
  38 + sjddModel = sch.getSjddModel();
  39 +
  40 + //起点发出
  41 + for(ArrivalInfo outArr : outList){
  42 + if(sjfcModel.getStation().equals(outArr.getStopNo())
  43 + && Math.abs(sch.getFcsjT() - outArr.getTs()) < spaceTime){
  44 +
  45 + //如果这个实际发车已经被之前班次关联
  46 + if(outBiMap.inverse().get(outArr.getId()) != null)
  47 + continue;
  48 +
  49 + //System.out.println("实际起点发出,计划时间:" + sch.getFcsj() + " -实际时间:" + sdf.format(new Date(outArr.getTs())) + " -" + outArr.getTs());
  50 + sjfcModel.setGpsTime(outArr.getTs());
  51 + outBiMap.put(sch.getId(), outArr.getId());
  52 + }
  53 + }
  54 +
  55 + //有些班次没有历时,也就没有计划终点时间
  56 + if(sch.getZdsjT() == null)
  57 + continue;
  58 + //终点到达
  59 + for(ArrivalInfo inArr : inList){
  60 + if(sjddModel.getStation().equals(inArr.getStopNo())
  61 + && Math.abs(sch.getZdsjT() - inArr.getTs()) < spaceTime){
  62 + //如果这个实际发车已经被之前班次关联
  63 + if(inBiMap.inverse().get(inArr.getId()) != null)
  64 + continue;
  65 +
  66 + //System.out.println("实际到达终点,计划时间:" + sch.getZdsj() + " -实际时间:" + sdf.format(new Date(inArr.getTs())) + " -" + inArr.getTs());
  67 + sjddModel.setGpsTime(inArr.getTs());
  68 + inBiMap.put(sch.getId(), inArr.getId());
  69 + }
  70 + }
  71 + }
  72 + }
  73 +}
... ...
src/main/java/com/bsth/vehicle/gpsdata/buffer/GpsArrivalDataBuffer.java
1 1 package com.bsth.vehicle.gpsdata.buffer;
2 2  
  3 +import java.util.ArrayList;
3 4 import java.util.Collections;
4 5 import java.util.Comparator;
5 6 import java.util.HashMap;
... ... @@ -8,7 +9,7 @@ import java.util.Map;
8 9  
9 10 import com.bsth.vehicle.common.CommonMapped;
10 11 import com.bsth.vehicle.gpsdata.entity.ArrivalInfo;
11   -import com.google.common.collect.LinkedListMultimap;
  12 +import com.google.common.collect.ArrayListMultimap;
12 13  
13 14 /**
14 15 *
... ... @@ -21,9 +22,10 @@ import com.google.common.collect.LinkedListMultimap;
21 22 public class GpsArrivalDataBuffer {
22 23  
23 24 /**
24   - * 车辆 时间戳排序的进出站链表
  25 + * 车辆 时间戳排序的实际进出站
25 26 */
26   - public static LinkedListMultimap<String, ArrivalInfo> allMap;
  27 + public static ArrayListMultimap<String, ArrivalInfo> allMap;
  28 +
27 29  
28 30 /**
29 31 * 车辆 和 进出站链表索引
... ... @@ -45,16 +47,15 @@ public class GpsArrivalDataBuffer {
45 47 List<ArrivalInfo> all = allMap.get(nbbm);
46 48 int size = all.size();
47 49 if(size == 0)
48   - return null;
  50 + return new ArrayList<>(0);
49 51  
50 52 List<ArrivalInfo> rs = all.subList(mark, size);
51   -
52 53 markMap.put(nbbm, size);
53 54 return rs;
54 55 }
55 56  
56 57 static {
57   - allMap = LinkedListMultimap.create();
  58 + allMap = ArrayListMultimap.create();
58 59 markMap = new HashMap<>();
59 60 }
60 61  
... ...
src/main/java/com/bsth/vehicle/gpsdata/buffer/GpsRealDataBuffer.java
... ... @@ -143,7 +143,11 @@ public class GpsRealDataBuffer {
143 143 gpsData.setStationName(CommonMapped.stationCodeMap.get(gpsData.getStopNo()));
144 144  
145 145 current = ScheduleBuffer.findCurrent(nbbm);
146   - next = ScheduleBuffer.getNext(current);
  146 + if(null == current){
  147 + next = ScheduleBuffer.getFirst(nbbm);
  148 + }
  149 + else
  150 + next = ScheduleBuffer.getNext(current);
147 151  
148 152 if(current != null)
149 153 gpsData.setCurrSchId(current.getId());
... ...
src/main/java/com/bsth/vehicle/gpsdata/entity/ArrivalInfo.java
... ... @@ -16,14 +16,20 @@ import javax.persistence.Transient;
16 16 public class ArrivalInfo {
17 17  
18 18 @Transient
19   - static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm")
20   - ,sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
  19 + static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss")
  20 + ,sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
21 21  
22 22  
23 23 public ArrivalInfo(String deviceId, Long ts, String lineCode, Integer upDown, String stopNo, Integer inOut,
24 24 Date createDate, Integer weeksYear) {
25 25 this.deviceId = deviceId;
26 26  
  27 + //gps是2014年的数据,临时将ts拉到今天
  28 + /*try {
  29 + this.ts = sdf2.parse("2016-07-25 " + sdf.format(new Date(ts))).getTime();
  30 + } catch (ParseException e) {
  31 + e.printStackTrace();
  32 + }*/
27 33 this.ts = ts;
28 34  
29 35 this.lineCode = lineCode;
... ... @@ -162,4 +168,8 @@ public class ArrivalInfo {
162 168 public void setStopName(String stopName) {
163 169 this.stopName = stopName;
164 170 }
  171 +
  172 + public String getId(){
  173 + return this.deviceId + "_" + this.ts;
  174 + }
165 175 }
... ...
src/main/java/com/bsth/vehicle/gpsdata/service/GpsDataServiceImpl.java
... ... @@ -139,7 +139,7 @@ public class GpsDataServiceImpl implements GpsDataService{
139 139  
140 140 //如果是同一天
141 141 if(sDayOfYear == eDayOfYear){
142   - weekCal.setTimeInMillis(st);
  142 + weekCal.setTimeInMillis(st * 1000);
143 143 list = findByTs(weekCal.get(Calendar.WEEK_OF_YEAR), sDayOfYear, st, et, devices);
144 144 }
145 145 else{
... ... @@ -160,7 +160,7 @@ public class GpsDataServiceImpl implements GpsDataService{
160 160 tempEt = DateUtils.getTimesnight(sCal);
161 161 }
162 162  
163   - weekCal.setTimeInMillis(tempSt);
  163 + weekCal.setTimeInMillis(tempSt * 1000);
164 164 list.addAll(findByTs(weekCal.get(Calendar.WEEK_OF_YEAR), i, tempSt, tempEt, devices));
165 165 //加一天
166 166 sCal.add(Calendar.DATE, 1);
... ... @@ -244,6 +244,7 @@ public class GpsDataServiceImpl implements GpsDataService{
244 244 return list;
245 245 }
246 246  
  247 + //weekOfYear 算错了
247 248 public Map<String, ArrivalInfo> findArrivalByTs(int weekOfYear, Long st, Long et, String devicesInSql){
248 249 Map<String, ArrivalInfo> map = new HashMap<>();
249 250  
... ... @@ -275,4 +276,10 @@ public class GpsDataServiceImpl implements GpsDataService{
275 276 }
276 277 return map;
277 278 }
  279 +
  280 + public static void main(String[] args) {
  281 + Calendar weekCal = Calendar.getInstance();
  282 + weekCal.setTime(new Date());
  283 + System.out.println(weekCal.get(Calendar.WEEK_OF_YEAR));
  284 + }
278 285 }
... ...
src/main/resources/static/pages/control/line/child_pages/vehicAndper_adjust.html renamed to src/main/resources/static/pages/control/line/child_pages/car_and_persion.html
... ... @@ -253,7 +253,7 @@
253 253 syncSubmit(idArray, params ,function(){
254 254 layer.closeAll();
255 255 layer.msg('操作完成!');
256   - //刷新表格
  256 + //刷新弹出层表格
257 257 refreshMainList();
258 258 });
259 259 });
... ... @@ -274,7 +274,7 @@
274 274 $.post('/realSchedule/adjust', data, function(rs){
275 275 //更新前端缓存
276 276 if(rs.status == 200){
277   - _data.updateSchedule(rs.t);
  277 + _alone.refreshSchedule(rs.t);
278 278 }
279 279  
280 280 i ++;
... ...
src/main/resources/static/pages/control/line/child_pages/child_task.html
... ... @@ -436,13 +436,16 @@ $(function(){
436 436 $('.confirm', schAddPanel).on('click', function(){
437 437 var f = $('form', schAddPanel);
438 438 var param = f.serializeJSON();
439   - /** 页面组装数据 */
440 439 //线路
441 440 param.xlBm = lineSelect.val();
442 441 param.xlName = _data.getLineIds()[param.xlBm];
443 442 //路牌
444 443 param.lpName = lpSelect.val();
445 444 //拆分驾驶员工号和姓名
  445 + if(!param.jGh){
  446 + layer.alert('驾驶员不能为空!', {icon: 2, title: '提交失败'});
  447 + return;
  448 + }
446 449 param.jName = param.jGh.split('/')[1];
447 450 param.jGh = param.jGh.split('/')[0];
448 451  
... ... @@ -497,12 +500,18 @@ function refreshChildTasks(){
497 500 //主任务id
498 501 var id = $mainTab.find('tr._active').data('id');
499 502  
500   - $.get('/childTask/all', {'schedule.id_eq': id}, function(rs){
  503 +
  504 + var htmlStr = template('child_task_sub_table_temp', {list: _data.getSchedulById(id).cTasks});
  505 +
  506 + dictionaryUtils.transformDom(
  507 + $subTab.find('tbody').html(htmlStr).find('.nt-dictionary')
  508 + );
  509 +/* $.get('/childTask/all', {'schedule.id_eq': id}, function(rs){
501 510 var htmlStr = template('child_task_sub_table_temp', {list: rs});
502 511  
503 512 dictionaryUtils.transformDom(
504 513 $subTab.find('tbody').html(htmlStr).find('.nt-dictionary')
505 514 );
506   - });
  515 + }); */
507 516 }
508 517 </script>
... ...
src/main/resources/static/pages/control/line/child_pages/outgo_adjust_all.html renamed to src/main/resources/static/pages/control/line/child_pages/dfsj_batch.html
src/main/resources/static/pages/control/line/child_pages/js/child_task.js
... ... @@ -335,12 +335,15 @@ var childTaskCase = {
335 335 };
336 336  
337 337 function childTaskSubmit(fs, layerIndex){
338   - syncSubmit(fs, function(){
  338 + syncSubmit(fs, function(rs){
339 339 layer.msg('子任务添加成功');
340 340 setTimeout(function(){
341 341 layer.close(layerIndex);
342 342 //刷新子任务列表
343   - refreshChildTasks();
  343 + if(rs.status == 'SUCCESS'){
  344 + _alone.refreshSchedule(rs.t);
  345 + refreshChildTasks();
  346 + }
344 347 }, 700);
345 348 });
346 349 }
... ... @@ -353,10 +356,11 @@ function syncSubmit(fs, cb){
353 356 if(fs.length == 0) return;
354 357 //备注
355 358 var remarks = $(fs[0]).parents('.custom-anim-modal').find('textarea[name=remarks]').val();
356   - var i = 0, len = fs.length;
  359 + var i = 0, len = fs.length, cbRs;
357 360 (function(){
  361 +
358 362 if(i == len){
359   - cb && cb();
  363 + cb && cb(cbRs);
360 364 return;
361 365 }
362 366  
... ... @@ -365,12 +369,15 @@ function syncSubmit(fs, cb){
365 369 ,params = $(form).serializeJSON();
366 370  
367 371 params.remarks = remarks;
368   - $post('/childTask', params, function(){
  372 + $post('/childTask', params, function(rs){
  373 + console.log('item rs: ' ,rs);
369 374 $(form).parent().find('.task-item-close').replaceWith('<a class="task-item-success"><i class="fa fa-check-circle" ></i></a>');
370 375 i ++;
371 376 //做一层防护,防止缺心眼出现无限循环提交
372 377 if(i == 0)
373 378 return;
  379 +
  380 + cbRs = rs;
374 381 f();
375 382 });
376 383 })();
... ...
src/main/resources/static/pages/control/line/css/lineControl.css
... ... @@ -2166,45 +2166,56 @@ tr._active .blue-badge{
2166 2166 color: #afafaf !important;
2167 2167 }
2168 2168  
  2169 +.pb-table tr.selected.next-sch a{
  2170 + color: white !important;
  2171 +}
  2172 +
2169 2173 .tab_line .pb-table tr._tr_active.active-line-no a.remarks-popover{
2170 2174 color: #bebebe;
2171 2175 }
2172 2176  
2173 2177 .tab_line .pb-table tr._tr_active.active-line-no td.tl-qrlb,
2174 2178 .pb-table tr.selected.dir_0 td.tl-qrlb,
2175   -.pb-table tr.selected.dir_1 td.tl-qrlb{
  2179 +.pb-table tr.selected.dir_1 td.tl-qrlb,
  2180 +.pb-table tr.selected.next-sch td.tl-qrlb{
2176 2181 background: none;
2177 2182 color: #ff796a;
2178 2183 }
2179 2184 .tab_line .pb-table tr._tr_active.active-line-no td.tl-zzzx,
2180 2185 .pb-table tr.selected.dir_0 td.tl-zzzx,
2181   -.pb-table tr.selected.dir_1 td.tl-zzzx{
  2186 +.pb-table tr.selected.dir_1 td.tl-zzzx,
  2187 +.pb-table tr.selected.next-sch td.tl-zzzx{
2182 2188 background: none;
2183 2189 color: #5ae35a;
2184 2190 }
2185 2191 .tab_line .pb-table tr._tr_active.active-line-no td.tl-yzx,
2186 2192 .pb-table tr.selected.dir_0 td.tl-yzx,
2187   -.pb-table tr.selected.dir_1 td.tl-yzx{
  2193 +.pb-table tr.selected.dir_1 td.tl-yzx,
  2194 +.pb-table tr.selected.next-sch td.tl-yzx{
2188 2195 background: none;
2189 2196 color: #80c8fa;
2190 2197 }
2191 2198 .tab_line .pb-table tr._tr_active.active-line-no td.tl-xxfc,
2192 2199 .pb-table tr.selected.dir_0 td.tl-xxfc,
2193   -.pb-table tr.selected.dir_1 td.tl-xxfc{
  2200 +.pb-table tr.selected.dir_1 td.tl-xxfc,
  2201 +.pb-table tr.selected.next-sch td.tl-xxfc{
2194 2202 background: none;
2195 2203 color: #a16dff;
2196 2204 }
2197 2205  
2198 2206 .tab_line .pb-table tr._tr_active.active-line-no td.tl-xxsd,
2199 2207 .pb-table tr.selected.dir_0 td.tl-xxsd,
2200   -.pb-table tr.selected.dir_1 td.tl-xxsd{
  2208 +.pb-table tr.selected.dir_1 td.tl-xxsd,
  2209 +.pb-table tr.selected.next-sch td.tl-xxsd{
2201 2210 background: none;
2202 2211 color: #ffb193;
2203 2212 }
2204 2213  
  2214 +
2205 2215 .tab_line .pb-table tr._tr_active.active-line-no td.tl-xxrd,
2206 2216 .pb-table tr.selected.dir_0 td.tl-xxrd,
2207   -.pb-table tr.selected.dir_1 td.tl-xxrd{
  2217 +.pb-table tr.selected.dir_1 td.tl-xxrd,
  2218 +.pb-table tr.selected.next-sch td.tl-xxrd{
2208 2219 background: none;
2209 2220 color: #5cb0e9;
2210 2221 }
... ...
src/main/resources/static/pages/control/line/index.html
... ... @@ -69,7 +69,7 @@
69 69 </div>
70 70 </div>
71 71 <div class="portlet-body" id="top-tabs-wrap" >
72   - <ul class="nav nav-tabs" >
  72 + <ul class="nav nav-tabs top-nav" >
73 73 <li class="active">
74 74 <a href="#tab_home" data-toggle="tab" aria-expanded="false" style="padding: 10px 15px;">
75 75 <i class="fa fa-home"></i> 主页
... ... @@ -139,11 +139,11 @@
139 139 <span class="menu-text">间隔调整</span>
140 140 </button>
141 141 </li>
142   - <li class="menu-item disabled" >
  142 + <!-- <li class="menu-item disabled" >
143 143 <button type="button" class="menu-btn">
144 144 <span class="menu-text">误点调整</span>
145 145 </button>
146   - </li>
  146 + </li> -->
147 147 <li class="menu-item" >
148 148 <button type="button" class="menu-btn" data-method="schInfoFineTune">
149 149 <span class="menu-text">发车信息微调</span>
... ... @@ -156,13 +156,12 @@
156 156 <span class="menu-text">临加/子任务</span>
157 157 </button>
158 158 </li>
159   - <li class="menu-separator"></li>
160   - <li class="menu-item disabled" >
  159 +<!-- <li class="menu-item disabled" >
161 160 <button type="button" class="menu-btn">
162 161 <i class="fa fa-reply-all"></i>
163 162 <span class="menu-text">撤销执行</span>
164 163 </button>
165   - </li>
  164 + </li> -->
166 165 <li class="menu-separator"></li>
167 166 <li class="menu-item" >
168 167 <button type="button" class="menu-btn" data-method="vehicAndPerAdjust">
... ...
src/main/resources/static/pages/control/line/js/alone.js
... ... @@ -49,7 +49,7 @@ var _alone = (function(){
49 49 });
50 50 },
51 51 //刷新单个班次
52   - refreshSchedule: function(schedule){
  52 + refreshSchedule: function(schedule, isBatch){
53 53 //更新 _data
54 54 _data.updateSchedule(schedule);
55 55 var tab = '#tab_line_' + schedule.xlBm;
... ... @@ -62,16 +62,20 @@ var _alone = (function(){
62 62  
63 63 var type = schedule.xlDir==0?'up':'down';
64 64 calculateLineNo($('.pb-table[data-type='+type+']', tab)[0]);
  65 +
  66 + if(!isBatch)
  67 + goToSch(schedule);
65 68 },
66 69 //刷新多个班次,刷新完数据再统一计算行号
67 70 refreshScheduleArray: function(array){
68 71 if(!array || array.length == 0)
69 72 return;
70 73 $.each(array, function(){
71   - aloneObject.refreshSchedule(this);
  74 + aloneObject.refreshSchedule(this, 1);
72 75 });
73 76 var table = $('tr[data-id='+array[0].id+']').parents('table')[0];
74 77 calculateLineNo(table);
  78 + initRemarksPop();
75 79 },
76 80 //将班次所在的表格做全量更新
77 81 updateTableBySch: function(schedule){
... ... @@ -83,24 +87,24 @@ var _alone = (function(){
83 87 _data.pushSchedule(this);
84 88 });
85 89  
86   - var upDown = xlDir==0?'up':'down';
  90 + /*var upDown = xlDir==0?'up':'down';
87 91 var tab = $('#tab_line_' + xlBm);
88 92 //重新渲染表格
89   - var table = tab.find('.pb-table[data-type='+upDown+']');
  93 + var table = tab.find('.pb-table[data-type='+upDown+']');*/
  94 + var table = getTableBySch(sch);
90 95 var schArray = _data.findSchByLine(xlBm, xlDir);
91 96 calculateLineNo(
92 97 table.find('tbody').html(template('alone_plan_table_temp', {list: schArray}))[0]
93 98 );
94 99  
95   - var half = tab.find('._body').height() / 2;
96   -
97 100 //定位到新添加的班次
98   - var currTr = table.find('tr[data-id='+schedule.id+']')
  101 + goToSch(schedule);
  102 + /*var currTr = table.find('tr[data-id='+schedule.id+']')
99 103 ,top = parseInt(currTr.find('td[name=lineNo]').text()) * 37 - half;
100 104  
101 105 top = top>0?top:0;
102 106 currTr.addClass('anim-delay animated flash');
103   - currTr.parents('._body').slimScroll({ scrollTo: top + 'px' });
  107 + currTr.parents('._body').slimScroll({ scrollTo: top + 'px' });*/
104 108 });
105 109 },
106 110 update2Table: function(xlBm, schedule){
... ... @@ -113,7 +117,7 @@ var _alone = (function(){
113 117  
114 118 var rs = splitDir(array)
115 119 ,tab = $('#tab_line_' + xlBm)
116   - ,half = tab.find('._body').height() / 2;
  120 + /*,half = tab.find('._body').height() / 2*/;
117 121 //填充表格数据
118 122 calculateLineNo(
119 123 //上行
... ... @@ -123,23 +127,47 @@ var _alone = (function(){
123 127 //下行
124 128 tab.find('table[data-type=down] tbody').html(template('alone_plan_table_temp', {list: rs.down}))[0]
125 129 );
  130 +
126 131 //定位到指定的班次
127   - var currTr = tab.find('tr[data-id='+schedule.id+']')
  132 + goToSch(schedule);
  133 + /*var currTr = tab.find('tr[data-id='+schedule.id+']')
128 134 ,top = parseInt(currTr.find('td[name=lineNo]').text()) * 37 - half;
129 135  
130 136 top = top>0?top:0;
131 137 currTr.addClass('anim-delay animated flash');
132   - currTr.parents('._body').slimScroll({ scrollTo: top + 'px' });
  138 + currTr.parents('._body').slimScroll({ scrollTo: top + 'px' });*/
133 139 });
134 140 },
135 141 //重新计算行号
136 142 calculateLineNo: calculateLineNo
137 143 }
138 144  
  145 + //获取班次所在table
  146 + function getTableBySch(sch){
  147 + var upDown = sch.xlDir==0?'up':'down';
  148 + var tab = $('#tab_line_' + sch.xlBm);
  149 + return tab.find('.pb-table[data-type='+upDown+']');
  150 + }
  151 +
  152 + //定位到班次所在的行
  153 + function goToSch(sch){
  154 + var table = getTableBySch(sch)
  155 + ,half = table.parents('._body').height() / 2
  156 + ,currTr = table.find('tr[data-id='+sch.id+']')
  157 + ,top = parseInt(currTr.find('td[name=lineNo]').text()) * 37 - half;
  158 +
  159 + top = top>0?top:0;
  160 + currTr.addClass('anim-delay animated flash');
  161 + currTr.parents('._body').slimScroll({ scrollTo: top + 'px' });
  162 + }
  163 +
139 164 //计算行号
140 165 function calculateLineNo(table){
141 166 var rows = table.rows;
142 167 $.each(rows,function(i, r){
  168 + if($(r).hasClass('child-task-list'))
  169 + return true;
  170 +
143 171 var cells = r.cells;
144 172 $(cells[0]).text(i + 1);
145 173  
... ... @@ -148,6 +176,9 @@ var _alone = (function(){
148 176 }
149 177  
150 178 function splitDir(list){
  179 + /*list.sort(function(a, b){
  180 + return a.fcno - b.fcno;
  181 + });*/
151 182 var rs = {up: [], down: []};
152 183 $.each(list, function(){
153 184 if(this.xlDir == upCode)
... ...
src/main/resources/static/pages/control/line/js/data.js
... ... @@ -8,8 +8,8 @@ var _data = (function(){
8 8  
9 9 //实时GPS数据
10 10 var allGps = {};
11   - //300秒刷新一次实时GPS
12   - var realGpsT = 1000 * 300;
  11 + //10秒刷新一次实时GPS
  12 + var realGpsT = 1000 * 10;
13 13  
14 14 var dateStr = moment().format('YYYY-MM-DD');
15 15 //实际排班
... ... @@ -29,8 +29,7 @@ var _data = (function(){
29 29 var carDeviceIdMapp = {};
30 30  
31 31 var fcsjSort = function(a, b){
32   - //return a.fcsjT - b.fcsjT;
33   - return a.fcno - b.fcno;
  32 + return (a.fcno - b.fcno) + (a.fcsjT - b.fcsjT);
34 33 }
35 34  
36 35 var dataObject = {
... ... @@ -289,23 +288,22 @@ var _data = (function(){
289 288 for(var i = 0, gps; gps=gpsList[i++];){
290 289 oldGps = prve[gps.deviceId];
291 290 if(!oldGps){
292   - //添加
293   - prve[gps.deviceId] = gps;
294 291 addArray.push(gps);
295 292 }
296 293 else if(gps.timestamp > oldGps.timestamp){
297 294 //更新
298 295 upArray.push(gps);
299 296 }
  297 + allGps[gps.deviceId] = gps;
300 298 }
301 299 cb && cb(addArray, upArray);
302 300 }
303 301  
304 302 function getGpsError(jqXHR, textStatus){
305   - if(textStatus === 'error'){}
306   - //layer.alert('获取GPS数据时,服务器出现异常', {icon: 2});
307   - else if(textStatus === 'timeout'){}
308   - //layer.alert('连接服务器超时', {icon: 2});
  303 + if(textStatus === 'error')
  304 + layer.alert('获取GPS数据时出现异常,请尝试刷新页面!', {icon: 2});
  305 + else if(textStatus === 'timeout')
  306 + layer.alert('连接服务器超时', {icon: 2});
309 307  
310 308 //停止gps刷新
311 309 clearTimeout(gpsTimer);
... ...
src/main/resources/static/pages/control/line/js/drawSvg.js
... ... @@ -62,6 +62,10 @@ var drawSvg = (function(){
62 62 //线路编码 和 单线路SVG对照
63 63 aloneSvgMapp[lineId] = svg;
64 64 },
  65 + clear: function(){
  66 + for(var k in seGps)
  67 + seGps[k] = [];
  68 + },
65 69 init: function(lineId, data, container, w, mtop){
66 70 if(!data || data.length == 0)
67 71 return;
... ... @@ -176,12 +180,34 @@ var drawSvg = (function(){
176 180  
177 181 //画出GPS点
178 182 drawVehicle: function(gpsArray){
  183 + if(!gpsArray || gpsArray.length == 0)
  184 + return;
  185 +
  186 + //console.log('len', gpsArray.length);
  187 + //暂时先清空重新画
  188 + var fGps = gpsArray[0];
  189 + var hSvg = homeSvgMapp[fGps.lineId]
  190 + ,aSvg = aloneSvgMapp[fGps.lineId];
  191 + //svg.selectAll('.vehci-g').remove();
  192 + if(fGps.upDown == 0){
  193 + hSvg.selectAll('.vehci-g.up').remove();
  194 + hSvg.selectAll('.start.park').remove();
  195 +
  196 + aSvg.selectAll('.vehci-g.up').remove();
  197 + aSvg.selectAll('.start.park').remove();
  198 + }
  199 + else if(fGps.upDown == 1){
  200 + hSvg.selectAll('.vehci-g.down').remove();
  201 + hSvg.selectAll('.end.park').remove();
  202 +
  203 + aSvg.selectAll('.vehci-g.down').remove();
  204 + aSvg.selectAll('.end.park').remove();
  205 + }
  206 +
179 207 for(var i = 0, gps; gps = gpsArray[i ++];){
180   - //drawGpsToSvg(gps, aloneSvgMapp[gps.lineId]);
  208 + drawGpsToSvg(gps, hSvg);
181 209  
182   - //暂时先清空重新画
183   - homeSvgMapp[gps.lineId].select('g.gps-g-wrap').html('');
184   - drawGpsToSvg(gps, homeSvgMapp[gps.lineId]);
  210 + drawGpsToSvg(gps, aSvg, true);
185 211 }
186 212  
187 213 //画出起终点GPS信号
... ... @@ -189,34 +215,42 @@ var drawSvg = (function(){
189 215 for(var eid in seGps){
190 216 len = seGps[eid].length;
191 217 if(len > 0){
192   - var e = $('#' + eid)
193   - ,x = parseInt(e.attr('cx'))
194   - ,y = parseInt(e.attr('cy'));
  218 + var a_e = $('#' + eid, aSvg[0])
  219 + ,a_x = parseInt(a_e.attr('cx'))
  220 + ,a_y = parseInt(a_e.attr('cy'));
  221 + tempStartAndStop(aSvg, eid, a_e, a_x, a_y);
195 222  
196   - var svg = homeSvgMapp[seGps[eid][0].lineId];
197   -
198   - var gs = svg.append('g').classed({'start': e.attr('class').indexOf('start') != -1, 'park': true})
199   - .selectAll('g').data(seGps[eid]).enter().append('g');
200   - //Y轴居中
201   - y = (y + 66) - len * 13;
202   - gs.append('rect')
203   - .attr('x', x + 15)
204   - .attr('y', function(d, i){
205   - return y + i * 27;
206   - })
207   - .classed({'gps-rect': true});
208   -
209   - gs.append('text')
210   - .attr('x', x + 18)
211   - .attr('y', function(d, i){
212   - return y + i * 27 + 17;
213   - })
214   - .text(function(d){return cutNbbm(d.nbbm)});
215   -
216   - _tooltip.initStartAndEndGPS(gs);
  223 + var h_e = $('#' + eid, hSvg[0])
  224 + ,h_x = parseInt(h_e.attr('cx'))
  225 + ,h_y = parseInt(h_e.attr('cy'));
  226 + tempStartAndStop(hSvg, eid ,h_e , h_x, h_y);
217 227 }
218 228 }
219 229  
  230 + function tempStartAndStop(svg, eid, e, x, y){
  231 +
  232 + var gs = svg.append('g').classed({'start': e.attr('class').indexOf('start') != -1, 'park': true})
  233 + .selectAll('g').data(seGps[eid]).enter().append('g');
  234 +
  235 + //Y轴居中
  236 + y = (y + 66) - len * 13;
  237 + gs.append('rect')
  238 + .attr('x', x + 15)
  239 + .attr('y', function(d, i){
  240 + return y + i * 27;
  241 + })
  242 + .classed({'gps-rect': true});
  243 +
  244 + gs.append('text')
  245 + .attr('x', x + 18)
  246 + .attr('y', function(d, i){
  247 + return y + i * 27 + 17;
  248 + })
  249 + .text(function(d){return cutNbbm(d.nbbm)});
  250 +
  251 + _tooltip.initStartAndEndGPS(gs);
  252 + }
  253 +
220 254 /**
221 255 * 堆叠多个GPS信号
222 256 */
... ... @@ -245,7 +279,7 @@ var drawSvg = (function(){
245 279 });
246 280  
247 281 function drawNumber(multiGps, num, that, start, end){
248   - var circle = $('#' + $(multiGps).attr('for'))
  282 + /*var circle = $('#' + $(multiGps).attr('for'))
249 283 ,x = circle.attr('cx')
250 284 ,y = circle.attr('cy');
251 285  
... ... @@ -258,23 +292,24 @@ var drawSvg = (function(){
258 292 numberG.classed({'end': true});//终点站
259 293  
260 294 numberG.append('rect').attr('x', x).attr('y', y);
261   - numberG.append('text').attr('x', x).attr('y', y).text(num);
  295 + numberG.append('text').attr('x', x).attr('y', y).text(num);*/
262 296 }
263 297 }
264 298 };
265 299  
266   - function drawGpsToSvg(gps, svg){
  300 + function drawGpsToSvg(gps, svg, flag){
267 301 var stionId = gps.lineId + '_' + gps.stopNo
268   - ,station = $('#' + stionId)
  302 + ,station = $('#' + stionId, svg[0])/*
269 303 ,c = station.attr('class')||""
270 304 ,start = c.indexOf('start') != -1
271   - ,end = c.indexOf('end') != -1;
  305 + ,end = c.indexOf('end') != -1*/;
272 306  
  307 + //console.log(stionId, station);
273 308 if(station.length == 0)
274 309 return;
275 310  
276 311 //起终点站GPS信号
277   - if(seGps[stionId]){
  312 + if(flag && seGps[stionId]){
278 313 seGps[stionId].push(gps);
279 314 return;
280 315 }
... ... @@ -285,7 +320,7 @@ var drawSvg = (function(){
285 320 ,gpsGWrap = svg.select('.gps-g-wrap')
286 321 ,gpscont;
287 322  
288   - if($('g[for='+stionId+']').length == 0){
  323 + if($('g[for='+stionId+']', svg[0]).length == 0){
289 324 gpscont = gpsGWrap.append('g')
290 325 .attr('class', 'station-gps-container')
291 326 .attr('updown', updown)
... ... @@ -338,8 +373,9 @@ var drawSvg = (function(){
338 373 .attr('cx', cx)
339 374 .attr('cy', updown=='up'?mt:mt + p)
340 375 .attr('id',function(d){
341   - if(d.id[0] != -1)
342   - return lineId + '_' + d.id[0];
  376 + var i = updown=='up'?0:1;
  377 + if(d.id[i] != -1)
  378 + return lineId + '_' + d.id[i];
343 379 })
344 380 .attr('updown', updown=='up'?0:1)
345 381 .attr('class', function(d, i){
... ...
src/main/resources/static/pages/control/line/js/keyboardListen.js
... ... @@ -24,22 +24,41 @@ $(document.body).on(&#39;keydown&#39;, function(e){
24 24 success: function(){
25 25 createVehSearch($('#ctrlFSearchSelect'))
26 26 .on('change', function(){
27   - var array = _data.findByCl($(this).val());
  27 + var nbbm = $(this).val();
  28 + var array = _data.findByCl(nbbm);
28 29 if(!array || array.length == 0)
29 30 layer.msg('没有找到相关班次信息!');
30 31 else{
31   - //定位到当前正在执行的班次
32   - var sch;
  32 + var tab = $('#tab_line_' + array[0].xlBm);
  33 + //清除对应tab 的样式
  34 + $('.pb-table tr.selected', tab).removeClass('selected,dir_0,dir_1');
  35 +
  36 + //console.log(tab, array[0].xlBm, array);
  37 + var runingSch,nearestSch;
  38 + //当前时间戳,忽略毫秒
  39 + var t = Date.parse(new Date());
  40 + var sch;//要定位到的班次
33 41 $.each(array, function(){
  42 + //正在执行的班次
34 43 if(this.status == 1)
35 44 sch = this;
  45 +
  46 + //距离当前时间最近的班次
  47 + if(!nearestSch
  48 + || Math.abs(this.fcsjT - t) < Math.abs(nearestSch.fcsjT - t))
  49 + nearestSch = this;
  50 +
  51 + //高亮所有班次
  52 + $('.pb-table tr[data-id='+this.id+']', tab).addClass('selected dir_' + this.xlDir);
36 53 });
  54 +
37 55 if(!sch)
38   - sch = array[0];
  56 + sch = nearestSch;
39 57  
40 58 var delay;
41 59 //当前选中的选项卡
42   - var activeTab = $('#top-tabs-wrap ul li.active a');
  60 + var activeTab = $('#top-tabs-wrap ul.top-nav li.active a');
  61 +
43 62 if(activeTab.data('id') == sch.xlBm){
44 63 //搜索的班次就在当前页面
45 64 delay = 0;
... ... @@ -52,7 +71,6 @@ $(document.body).on(&#39;keydown&#39;, function(e){
52 71 }
53 72  
54 73 setTimeout(function(){
55   - $('.pb-table tr.selected').removeClass('selected');
56 74 var tr = $('tr[data-id='+sch.id+']', tab)
57 75 .addClass('selected search');
58 76  
... ... @@ -65,9 +83,16 @@ $(document.body).on(&#39;keydown&#39;, function(e){
65 83 $(this).removeClass('animated flash');
66 84 });
67 85 }, delay);
  86 +
  87 + msg_ct('高亮车辆 ' + nbbm);
68 88 }
69 89 }).select2("open");
70 90 }
71 91 });
72 92 }
  93 +
  94 +
  95 + function msg_ct(t){
  96 + layer.msg(t,{offset: 'ct', shift : 5});
  97 + }
73 98 });
74 99 \ No newline at end of file
... ...
src/main/resources/static/pages/control/line/js/main.js
... ... @@ -42,7 +42,6 @@
42 42 $('#tab_home').html(homeHtmlStr);
43 43 //计算高度 40 页脚
44 44 var ah = $('#top-tabs-wrap .tab-content').height() - 40 - 5;
45   - console.log(ah);
46 45 $('.card_wrap').css('height', ah / 3);
47 46  
48 47 //滚动条
... ... @@ -67,28 +66,27 @@
67 66 var list = _data.findAllGps();
68 67 _data.attachSchedulInfo(list);
69 68  
70   - drawSvg.drawVehicle(list);
71   -
  69 + //drawSvg.drawVehicle(list);
72 70 //按线路分组
73 71 var listMap = groupByLine(list);
74   - console.log('listMap', listMap);
  72 +
75 73 for(var key in listMap){
76 74 var htmlStr = template('home_table_temp', {list: listMap[key]});
77 75 $('#tab_' + key).find('tbody').html(htmlStr);
78 76 //更新badge
79 77 $('#'+key+'_badge').text('( ' + listMap[key].length + ' )');
  78 +
  79 + drawSvg.clear();
  80 + drawSvg.drawVehicle(listMap[key]);
80 81 }
81 82 });
82 83  
83 84 setTimeout(function(){
84 85 //打开GPS定时刷新
85 86 _data.startRefreshGpsTimer();
86   -
87   - setTimeout(function(){
88   - //去掉loading
89   - $('.load-anim').fadeOut();
90   - $('menu.menu').show();
91   - }, 100);
  87 + //去掉loading
  88 + $('.load-anim').fadeOut();
  89 + $('menu.menu').show();
92 90 }, 400);
93 91  
94 92 }
... ...
src/main/resources/static/pages/control/line/js/rightMenu.js
... ... @@ -83,11 +83,15 @@ var _menu = (function() {
83 83  
84 84 });
85 85  
  86 + function msg_ct(t){
  87 + layer.msg(t,{offset: 'ct', shift : 5});
  88 + }
  89 +
86 90 //点击路牌
87 91 var lps = '.pb-table.data tr td[data-name=lpName]';
88 92 $('.portlet-fullscreen').on('click', lps, function(e){
89 93 var lp = $(this).text();
90   - layer.msg('高亮路牌:' + lp + '',{offset: 'ct', shift : 5});
  94 + msg_ct('高亮路牌:' + lp);
91 95 var lineCode = $(this).parents('.tab-pane').data('id');
92 96 var schArray = _data.getLineLpMap()[lineCode][lp];
93 97  
... ... @@ -124,7 +128,7 @@ var _menu = (function() {
124 128 ,sch = _data.getSchedulById(schId);
125 129  
126 130 var scroll = false;
127   - console.log(_data.findByCl(clnbbm));
  131 +
128 132 $.each(_data.findByCl(clnbbm), function(){
129 133 if(scroll){
130 134 var nextTr = $('tr[data-id='+this.id+']');
... ... @@ -235,7 +239,7 @@ var _menu = (function() {
235 239 $post('/realSchedule/outgoAdjust', params, function(rs){
236 240 layer.close(index);
237 241 if(rs.t){
238   - layer.msg('调整成功!');
  242 + msg_ct('调整成功!');
239 243 _alone.refreshSchedule(rs.t);
240 244 }
241 245 });
... ... @@ -245,10 +249,10 @@ var _menu = (function() {
245 249 },
246 250 //计划烂班
247 251 planDestroy: function(schedul){
248   - /*if(schedul.status == -1){
249   - layer.alert('不能重复烂班!', {icon: 2, title: '提示', shift: 5});
  252 + if(schedul.status == -1){
  253 + layer.alert('没必要做重复烂班!', {icon: 2, title: '提示', shift: 5});
250 254 return;
251   - }*/
  255 + }
252 256 var array = [];
253 257 //获取未烂班的班次
254 258 $.each(_data.getSchedulByVeh(schedul.clZbh),function(){
... ... @@ -325,7 +329,7 @@ var _menu = (function() {
325 329 layer.close(index);
326 330 //刷新数据
327 331 _alone.refreshScheduleArray(rs.list);
328   - layer.msg('计划烂班成功!');
  332 + msg_ct('计划烂班成功!');
329 333 });
330 334 });
331 335 return false;
... ... @@ -353,10 +357,10 @@ var _menu = (function() {
353 357 layer.close(index);
354 358 $post('/realSchedule/realOutAdjust', params
355 359 ,function(rs){
356   - if(rs.t){
357   - layer.msg('实发调整成功!');
  360 + if(rs.ts){
  361 + msg_ct('实发调整成功!');
358 362 //更新前端数据
359   - _alone.refreshSchedule(rs.t);
  363 + _alone.refreshScheduleArray(rs.ts);
360 364 }
361 365 });
362 366 });
... ... @@ -371,10 +375,11 @@ var _menu = (function() {
371 375 shift :5,
372 376 }, function(){
373 377 $post('/realSchedule/revokeRealOutgo', {id: schedul.id}, function(rs){
374   - if(rs.t){
375   - layer.msg('撤销实发成功!');
  378 + console.log(rs);
  379 + if(rs.ts){
  380 + msg_ct('撤销实发成功!');
376 381 //更新前端数据
377   - _alone.refreshSchedule(rs.t);
  382 + _alone.refreshScheduleArray(rs.ts);
378 383 }
379 384 });
380 385 });
... ... @@ -388,7 +393,7 @@ var _menu = (function() {
388 393 }, function(){
389 394 $post('/realSchedule/revokeDestroy', {id: schedul.id}, function(rs){
390 395 if(rs.t){
391   - layer.msg('撤销烂班成功!');
  396 + msg_ct('撤销烂班成功!');
392 397 //更新前端数据
393 398 _alone.refreshSchedule(rs.t);
394 399 }
... ... @@ -415,7 +420,7 @@ var _menu = (function() {
415 420 || rs.status == 200){
416 421 //刷新数据
417 422 _alone.refreshScheduleArray(rs.list);
418   - layer.msg('调整间隔成功!');
  423 + msg_ct('调整间隔成功!');
419 424 }
420 425 },
421 426 error: errorHandle
... ... @@ -451,7 +456,7 @@ var _menu = (function() {
451 456 },
452 457 //调整人车
453 458 vehicAndPerAdjust: function(schedul){
454   - $.get('/pages/control/line/child_pages/vehicAndper_adjust.html', function(content){
  459 + $.get('/pages/control/line/child_pages/car_and_persion.html', function(content){
455 460 layer.open({
456 461 type: 1,
457 462 area: '730px',
... ... @@ -483,7 +488,10 @@ var _menu = (function() {
483 488 $.post('/directive/dispatch', {id: schedul.id},
484 489 function(code){
485 490 if(code == 0){
486   - layer.msg('发送成功');
  491 + msg_ct('发送成功');
  492 + }
  493 + else if(code == -2){
  494 + layer.alert('该班次发车时间距离当前时间较远,系统阻止了该调度指令的下发。', {icon: 2, title: '被拦截的指令'});
487 495 }
488 496 else
489 497 layer.alert('发送调度指令失败', {icon: 2, title: '操作失败'});
... ... @@ -494,7 +502,7 @@ var _menu = (function() {
494 502 schInfoFineTune: function(schedul){
495 503 var index = layer.open({
496 504 type: 1,
497   - area: '630px',
  505 + area: '680px',
498 506 maxmin: true,
499 507 content: template('schinfo_fine_tune_temp', schedul),
500 508 shift: 5,
... ... @@ -538,11 +546,11 @@ var _menu = (function() {
538 546  
539 547 $post('/realSchedule/schInfoFineTune', params, function(rs){
540 548 layer.close(index);
541   - if(rs.t)
542   - _alone.refreshSchedule(rs.t);
  549 + if(rs.ts)
  550 + _alone.refreshScheduleArray(rs.ts);
543 551  
544   - if(rs.nextSch)
545   - _alone.refreshSchedule(rs.nextSch);
  552 + /*if(rs.nextSch)
  553 + _alone.refreshSchedule(rs.nextSch);*/
546 554 });
547 555 });
548 556 }
... ... @@ -550,7 +558,7 @@ var _menu = (function() {
550 558 },
551 559 //基于车辆的待发调整
552 560 outgoAdjustAll: function(schedul){
553   - $.get('/pages/control/line/child_pages/outgo_adjust_all.html', function(content){
  561 + $.get('/pages/control/line/child_pages/dfsj_batch.html', function(content){
554 562 layer.open({
555 563 type: 1,
556 564 area: '830px',
... ...
src/main/resources/static/pages/control/line/temps/alone_tp.html
... ... @@ -20,7 +20,6 @@
20 20 <td>待发</td>
21 21 <td>实发</td>
22 22 <td class="hide-lt-1080">原因</td>
23   - <!--<td>类型</td>-->
24 23 </tr>
25 24 </thead>
26 25 </table>
... ... @@ -52,7 +51,6 @@
52 51 <td>待发</td>
53 52 <td>实发</td>
54 53 <td class="hide-lt-1080">原因</td>
55   - <!--<td>类型</td>-->
56 54 </tr>
57 55 </thead>
58 56 </table>
... ... @@ -136,7 +134,7 @@
136 134 <td data-name="dfsj" data-time="{{item.zdsjT}}">{{item.dfsj}}</td>
137 135  
138 136 {{if item.status == -1}}
139   - <td class="tl-qrlb sfsj-item">烂班</td>
  137 + <td class="tl-qrlb sfsj-item" >烂班</td>
140 138  
141 139 {{else if item.status == 2}}
142 140 <td data-name="sjfcsj" class="tl-yzx sfsj-item">{{item.fcsjActual == null?"?":item.fcsjActual}}<span class="fcsj-diff">{{item.fcsj_diff}}</span></td>
... ... @@ -148,13 +146,35 @@
148 146 <td data-name="sjfcsj" class="sfsj-item">{{item.fcsjActual}}<span class="fcsj-diff">{{item.fcsj_diff}}</span></td>
149 147 {{/if}}
150 148  
151   - <td class="hide-lt-1080" data-name="remarks">
152   - {{if item.remarks != null && item.length > 0}}
153   - <a class="remarks-popover" href="javascript:;" data-toggle="popover" data-content="{{item.remarks}}" >备注...</a>
  149 +<td class="hide-lt-1080" data-name="remarks">
  150 + {{if item.remarks != null && item.remarks.length > 0}}
  151 + <a class="remarks-popover" href="javascript:;" data-toggle="popover" data-content="{{item.remarks}}" >查看...</a>
154 152 {{/if}}
155 153 </td>
156   - <!--<td><a href="javascript:;">主</a></td>-->
157   - </tr>
  154 +</tr>
  155 +
  156 +{{if item.cTasks.length > 0}}
  157 +<!-- 子任务列表
  158 +<tr class="child-task-list">
  159 +<td></td>
  160 +<td colspan=9>
  161 +<div>
  162 +{{each item.cTasks as task j}}
  163 + <div>
  164 + <span>{{task.startStationName}}</span>
  165 + <span>{{task.endStationName}}</span>
  166 + <span>{{task.startDate}}</span>
  167 + <span>{{task.endDate}}</span>
  168 + <span>{{task.mileageType}}</span>
  169 + </div>
  170 +{{/each}}
  171 +</div>
  172 +</td>
  173 +</tr>
  174 +-->
  175 +{{/if}}
  176 +
  177 +
158 178 {{/each}}
159 179 </script>
160 180  
... ... @@ -267,7 +287,7 @@
267 287 </div>
268 288 <hr>
269 289 <div class="form-custom-footer">
270   - <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;确&nbsp;&nbsp;定 </button>
  290 + <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;定 </button>
271 291 <button type="button" class="btn layui-layer-close"> 取消 </button>
272 292 </div>
273 293 </div>
... ... @@ -345,7 +365,7 @@
345 365  
346 366 <hr>
347 367 <div class="form-custom-footer">
348   - <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;确&nbsp;&nbsp;定 </button>
  368 + <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;定 </button>
349 369 <button type="button" class="btn layui-layer-close"> 取消 </button>
350 370 </div>
351 371 </form>
... ... @@ -442,7 +462,7 @@
442 462  
443 463 <hr>
444 464 <div class="form-custom-footer">
445   - <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;确&nbsp;&nbsp;定 </button>
  465 + <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;定 </button>
446 466 <button type="button" class="btn layui-layer-close"> 取消 </button>
447 467 </div>
448 468 </div>
... ... @@ -491,7 +511,7 @@
491 511 </div>
492 512 <hr>
493 513 <div class="form-custom-footer">
494   - <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;确&nbsp;&nbsp;定 </button>
  514 + <button type="button" class="btn blue-madison confirm"> <i class="fa fa-check"></i> &nbsp;&nbsp;定 </button>
495 515 <button type="button" class="btn layui-layer-close"> 取消 </button>
496 516 </div>
497 517 </form>
... ...
src/main/resources/static/pages/forms/mould/waybill.xls
No preview for this file type
src/main/resources/static/pages/mapmonitor/real/css/real.css
... ... @@ -503,7 +503,7 @@ html{
503 503  
504 504 .mapRightWrap .search_result .item_vehicle_list{
505 505 margin-bottom: 20px;
506   - border-bottom: 1px solid #F3F5F5;
  506 + /* border-bottom: 1px solid #F3F5F5; */
507 507 }
508 508  
509 509 .mapRightWrap .search_result .item_vehicle{
... ... @@ -696,7 +696,7 @@ display: none;
696 696 .play-back-btns{
697 697 display: none;
698 698 background: rgb(255, 255, 255);
699   - width: 206px;
  699 + width: 216px;
700 700 height: 44px;
701 701 position: absolute;
702 702 right: 320px;
... ... @@ -776,7 +776,7 @@ display: none;
776 776 font-size: 15px;
777 777 vertical-align: middle;
778 778 font-weight: 600;
779   - margin-right: 12px;
  779 + margin-right: 5px;
780 780 color: #565555;
781 781 padding: 4px 8px 4px 13px;
782 782 cursor: pointer;
... ...
src/main/resources/static/pages/mapmonitor/real/js/map_platform.js
... ... @@ -51,6 +51,8 @@ var realMap = (function() {
51 51 //百度 -轨迹回放点聚合
52 52 //var historyClusterer;
53 53  
  54 + var markerClusterer;
  55 +
54 56 //设备号和marker对照
55 57 var markersMap;
56 58 var real_map = {
... ... @@ -125,6 +127,8 @@ var realMap = (function() {
125 127 },
126 128 clear: function(){
127 129 currentMap.map.clearOverlays();
  130 + markerClusterer && markerClusterer.clearMarkers();
  131 +
128 132 },
129 133 change : function() {
130 134 if(currentMap.mapName == REAL_BAIDU_TEXT)
... ... @@ -212,7 +216,9 @@ var realMap = (function() {
212 216 drawGpsMarker: function(gpsList){
213 217 markersMap = {};
214 218 var map = currentMap.map;
215   - var markerClusterer = new BMapLib.MarkerClusterer(map, {isAverangeCenter : true,minClusterSize : 3});
  219 +
  220 + markerClusterer && markerClusterer.clearMarkers();
  221 + markerClusterer = new BMapLib.MarkerClusterer(map, {isAverangeCenter : true,minClusterSize : 3});
216 222 real_map.baidu.coordsConvert(gpsList, function(){
217 223 //绘制车辆位置
218 224 var marker;
... ...
src/main/resources/static/pages/mapmonitor/real/js/playBack.js
... ... @@ -102,8 +102,11 @@ var playBack = (function() {
102 102 marker = markerMap[gps.nbbm];
103 103 if(marker)
104 104 getCurrMap().moveMarker(marker, gps);//移动marker
105   - else
  105 + else{
106 106 markerMap[gps.nbbm] = getCurrMap().addHistoryMarker(gps);//添加marker
  107 + //定位到marker
  108 + getCurrMap().markerToCenter(markerMap[gps.nbbm]);
  109 + }
107 110  
108 111 if(gps.inout_stop != -1){
109 112 //到离站信息
... ... @@ -123,6 +126,8 @@ var playBack = (function() {
123 126 function addInOutText(gps){
124 127 var info = gps.inout_stop_info
125 128 ,date = moment(gps.ts).format('HH:mm.ss');
  129 + if(!info)
  130 + return;
126 131 var html = '<div class="pback-logs-item">'+
127 132 gps.nbbm + ' '+ (info.inOut==1?'出':'进') +'站 '+info.stopName+' '+
128 133 '<span class="pback-logs-item-date">'+ date +'</span>'+
... ...
src/main/resources/static/pages/mapmonitor/real/js/real.js
... ... @@ -41,9 +41,9 @@
41 41 }
42 42 var method = $(this).data('click');
43 43  
44   - /*if (!method || playAnimation)
  44 + if (!method /*|| playAnimation*/)
45 45 return;
46   - playAnimation = true;*/
  46 + //playAnimation = true;
47 47  
48 48 $('.mapTools').addClass('disable');
49 49 $('.mapTools div.item.active').removeClass('active');
... ...
src/main/resources/static/pages/mapmonitor/real/js/search.js
... ... @@ -8,25 +8,64 @@ var searchPanel = (function() {
8 8 return realMap[realMap.getMap().fName];
9 9 }
10 10  
  11 + var allGps;
  12 +
11 13 var exports = {
12 14 init : function() {
13 15 var htmlStr = template('search_panel_temp', {});
14 16 $('.mapRightWrap').html(htmlStr);
15 17  
16   - // 建立一个自动完成的对象
  18 + //focus
  19 + //焦点时获取所有的gps
  20 + $('#realSearchInput').on('focus', function(){
  21 + allGps = vehiclePanel.getAllGps();
  22 + console.log('focus', allGps);
  23 + })
  24 + .on('keyup', function(){
  25 + var t = $(this).val()
  26 + ,list = [];
  27 +
  28 + $.each(allGps, function(){
  29 + if(this.nbbm.indexOf(t) == -1)
  30 + return true;
  31 +
  32 + this.fromNow = moment(this.timestamp).fromNow();
  33 + list.push(this);
  34 + });
  35 +
  36 + var resultHtml = template('search_result_temp', {list: list});
  37 + $('.mapRightWrap .search_result').html(resultHtml);
  38 + });
17 39  
18   - getCurr().autocomplete('realSearchInput', function(json){
19   - console.log(json);
  40 + $('.search_result').on('click', '.result_item' ,function(){
  41 + console.log($(this).data('device'));
  42 + });
  43 +
  44 + //var allGps = vehiclePanel.getAllCars();
  45 + /*$('#realSearchInput').on('keyup', function(){
  46 + var t = $(this).val()
  47 + ,array = [];
  48 + $.each(allCars, function(i, nbbm){
  49 + if(nbbm.indexOf(t) != -1)
  50 + array.push(nbbm);
  51 + });
  52 + });*/
  53 + // 建立一个自动完成的对象
  54 + /*getCurr().autocomplete('realSearchInput', function(json){
  55 +
20 56 var resultHtml = template('search_result_temp', json);
21 57 $('.mapRightWrap .search_result').html(resultHtml);
  58 + //搜索车辆
  59 + //console.log(json);
22 60 });
23 61  
24 62 //查询结果选中事件
25 63 $('.search_result').on('click', '.result_item'
26 64 ,function(){
27 65  
28   - getCurr().setPlace($(this).data('title'));
29   - });
  66 + console.log(this);
  67 + //getCurr().setPlace($(this).data('title'));
  68 + });*/
30 69 }
31 70 };
32 71  
... ...
src/main/resources/static/pages/mapmonitor/real/js/vehicle.js
... ... @@ -4,6 +4,10 @@
4 4  
5 5 var vehiclePanel = (function() {
6 6  
  7 + //设备号和marker映射
  8 + var gpsMarker = {}
  9 + ,cLineCode;// 当前线路编码
  10 +
7 11 function getCurrMap(){
8 12 return realMap[realMap.getMap().fName];
9 13 }
... ... @@ -16,6 +20,7 @@ var vehiclePanel = (function() {
16 20 // 手风琴收拢
17 21 $('.mapRightWrap').on('hide.bs.collapse', '.panel-collapse', function() {
18 22 $(this).prev().find('span.icon').addClass('rotate');
  23 + cLineCode = null;
19 24 });
20 25  
21 26 // 手风琴展开
... ... @@ -24,18 +29,31 @@ var vehiclePanel = (function() {
24 29 var lineCode = $(this).data('line');
25 30 //收拢其他
26 31 closeAll();
27   - drawLineAndGps(lineCode);
  32 + cLineCode = lineCode;
  33 + drawLineAndGps(lineCode, function(){
  34 + //从storage里获取路由数据
  35 + var route = JSON.parse(storage.getItem(lineCode + '_route'));
  36 + //在地图上画出线路
  37 + getCurrMap().drawLine(route);
  38 + });
28 39 });
29 40  
30 41 //绘制线路和GPS
31   - function drawLineAndGps(lineCode){
  42 + function drawLineAndGps(lineCode, callFun){
32 43 //过滤出该线路的GPS点
33   - var showList = [];
34   - if(lineGps[lineCode]){
  44 + var showList = [], gps;
  45 + /*if(lineGps[lineCode]){
35 46 $.each(lineGps[lineCode], function(){
36   - showList.push(allGps[this]);
  47 + gps = allGps[this];
  48 + showList.push(gps);
  49 + gpsMarker[gps.deviceId] = gps;
37 50 });
  51 + }*/
  52 + for(var dId in allGps){
  53 + if(allGps[dId].lineId == lineCode)
  54 + showList.push(allGps[dId]);
38 55 }
  56 +
39 57 //显示车辆列表
40 58 var htmlStr = template('vehicle_panel_collapse_temp', {list: showList});
41 59 $('#collapse_' + lineCode).html(htmlStr);
... ... @@ -45,13 +63,10 @@ var vehiclePanel = (function() {
45 63 */
46 64 var that = $(this);
47 65 setTimeout(function(){
48   - //在地图上画出线路
49   - var mapObj = getCurrMap();
50   - //从storage里获取路由数据
51   - var route = JSON.parse(storage.getItem(lineCode + '_route'));
52   - mapObj.drawLine(route);
  66 + callFun && callFun();
53 67 //画GPS
54   - mapObj.drawGpsMarker(showList);
  68 + getCurrMap().drawGpsMarker(showList);
  69 +
55 70 }, 500);
56 71 }
57 72  
... ... @@ -70,23 +85,36 @@ var vehiclePanel = (function() {
70 85  
71 86 //GPS刷新事件
72 87 var allGps = {};
73   - var lineGps = {};
  88 + //var lineGps = {};
74 89 $('#mapContainer').on('gps_refresh', function(e, add, up){
75 90 var temp = add;
76 91 if(up)
77 92 temp = temp.concat(up);
78 93  
  94 + var gps;
79 95 if(!$(this).is(":hidden")){
80 96 $.each(temp, function(){
81 97 allGps[this.deviceId] = this;
82 98 });
83 99  
84   - $.each(add, function(){
  100 + /* $.each(add, function(){
85 101 if(!lineGps[this.lineId])
86 102 lineGps[this.lineId] = [];
87 103 //线路和设备号映射
88   - lineGps[this.lineId].push(this.deviceId);
89   - })
  104 + //lineGps[this.lineId].push(this.deviceId);
  105 + })*/
  106 + }
  107 +
  108 + //先暂时重绘,后面再优化
  109 + if(cLineCode){
  110 + drawLineAndGps(cLineCode);
  111 + /*var showList = [];
  112 + if(lineGps[cLineCode]){
  113 + $.each(lineGps[cLineCode], function(){
  114 + showList.push(allGps[this]);
  115 + });
  116 + }
  117 + mapObj.drawGpsMarker(showList);*/
90 118 }
91 119 });
92 120  
... ... @@ -126,6 +154,21 @@ var vehiclePanel = (function() {
126 154 },
127 155 drawLineAndGps: function(lineCode){
128 156 drawLineAndGps(lineCode);
  157 + },
  158 + //获取所有的车辆 - 从GPS定时定距里查询
  159 + getAllGps: function(){
  160 + var array = [];
  161 + /*var array = [
  162 + {nbbm: 'B-91524', state: 0, timestamp: 1469427233000, stationName: '金桥路浦东大道', lineId: 1024, lon: 121.504921, lat: 31.086559, deviceId: 000},
  163 + {nbbm: 'B-91334', state: 1, timestamp: 1469427233000, stationName: '博山东路', lineId: 1024, lon: 121.504921, lat: 31.086559, deviceId: 111},
  164 + {nbbm: 'B-91224', state: 0, timestamp: 1469427233000, stationName: '闵浦大桥', lineId: 1024, lon: 121.504921, lat: 31.086559, deviceId: 222},
  165 + {nbbm: 'B-91124', state: 0, timestamp: 1469427312000, stationName: '旧金山', lineId: 1024, lon: 121.504921, lat: 31.086559, deviceId: 333},
  166 + {nbbm: 'B-91924', state: -1, timestamp: 1469427233000, stationName: '硅谷', lineId: 1024, lon: 121.504921, lat: 31.086559, deviceId: 444},
  167 + {nbbm: 'B-92224', state: 0, timestamp: 1469427312000, stationName: '意大利', lineId: 1024, lon: 121.504921, lat: 31.086559, deviceId: 555}
  168 + ];*/
  169 + for(var deviceId in allGps)
  170 + array.push(allGps[deviceId]);
  171 + return array;
129 172 }
130 173 };
131 174  
... ...
src/main/resources/static/pages/mapmonitor/real/temps/search.html
1 1 <script id="search_panel_temp" type="text/html">
2 2 <div class="input-group">
3   - <input type="text" id="realSearchInput" class="form-control" placeholder="车辆自编号/地图位置...">
  3 + <input type="text" id="realSearchInput" class="form-control" placeholder="车辆自编号搜索...">
4 4 <span class="input-group-btn">
5 5 <button class="btn" type="button"><i class="fa fa-search"></i> 搜索</button>
6 6 </span>
... ... @@ -11,19 +11,18 @@
11 11 </script>
12 12  
13 13 <script id="search_result_temp" type="text/html">
14   -
15   - <div class="item_vehicle_list">
16   - <p class="result_item item_vehicle">
17   - <i class="fa fa-circle font-green-jungle"></i> &nbsp;W1B-023 &nbsp;&nbsp;-营运中<br>
18   - <span class="sub_text">开往 金桥路浦东大道 站(30秒前)</span>
  14 +<div class="item_vehicle_list">
  15 +{{each list as gps i}}
  16 + <p class="result_item item_vehicle" data-device={{gps.deviceId}}>
  17 + &nbsp;{{gps.nbbm}} &nbsp;&nbsp;- {{if gps.state==0}}营运中{{else if gps.state==1}}非营运{{else}}未知营运状态{{/if}}<br>
  18 + <span class="sub_text"> {{gps.stationName}}({{gps.fromNow}} 更新)</span>
19 19 </p>
20 20  
21   - <p class="result_item item_vehicle">
22   - <i class="fa fa-circle font-green-jungle"></i> &nbsp;W2C-578 &nbsp;&nbsp;-营运中<br>
23   - <span class="sub_text">开往 张江路华谊路 站(刚刚)</span>
24   - </p>
25   - </div>
  21 +{{/each}}
  22 +</div>
  23 +</script>
26 24  
  25 +<!--
27 26 {{if type == "baidu"}}
28 27 {{each result as obj i}}
29 28 <p class="result_item" data-title="{{obj.business}}">
... ... @@ -39,4 +38,4 @@
39 38 </p>
40 39 {{/each}}
41 40 {{/if}}
42   -</script>
  41 + -->
43 42 \ No newline at end of file
... ...
src/main/resources/static/pages/mapmonitor/real/temps/vehicle.html
... ... @@ -34,7 +34,7 @@
34 34 <span style="font-size: 13px;">{{gpsObj.stationName}}</span>
35 35 </div>
36 36 <div class="icon">
37   - <i class="fa fa-file-text-o"></i>
  37 + <!--<i class="fa fa-file-text-o"></i>-->
38 38 </div>
39 39 </div>
40 40 {{/each}}
... ...