Commit 8bcd7dea7ebf8fd49313e6ffded7ef839877bc06

Authored by 徐烜
1 parent 893a4fd8

时刻表v2.7

将动态时刻表的数据和统计数据导出成格式xlsx文档

Too many changes to show.

To preserve performance only 13 of 16 files are displayed.

src/main/java/com/bsth/controller/schedule/core/TTInfoDetailController.java
@@ -5,9 +5,13 @@ import com.bsth.controller.schedule.BController; @@ -5,9 +5,13 @@ import com.bsth.controller.schedule.BController;
5 import com.bsth.entity.schedule.TTInfoDetail; 5 import com.bsth.entity.schedule.TTInfoDetail;
6 import com.bsth.service.schedule.TTInfoDetailService; 6 import com.bsth.service.schedule.TTInfoDetailService;
7 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit; 7 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
  8 +import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
  9 +import com.bsth.service.schedule.utils.DataToolsFile;
8 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.web.bind.annotation.*; 11 import org.springframework.web.bind.annotation.*;
10 12
  13 +import javax.servlet.http.HttpServletResponse;
  14 +import java.io.*;
11 import java.util.HashMap; 15 import java.util.HashMap;
12 import java.util.List; 16 import java.util.List;
13 import java.util.Map; 17 import java.util.Map;
@@ -120,4 +124,32 @@ public class TTInfoDetailController extends BController<TTInfoDetail, Long> { @@ -120,4 +124,32 @@ public class TTInfoDetailController extends BController<TTInfoDetail, Long> {
120 public Map<String, Object> skbDetailMxSave(@RequestParam Map<String, Object> entities){ 124 public Map<String, Object> skbDetailMxSave(@RequestParam Map<String, Object> entities){
121 return ttInfoDetailService.skbDetailMxSave(entities); 125 return ttInfoDetailService.skbDetailMxSave(entities);
122 } 126 }
  127 +
  128 +
  129 + @RequestMapping(value = "/exportDTDFile", method = RequestMethod.POST)
  130 + public void exportFile(
  131 + @RequestBody TTinfoDetailDynamicData.DTInfos dtInfos,
  132 + HttpServletResponse response) throws Exception {
  133 + DataToolsFile dataToolsFile = ttInfoDetailService.exportDynamicTTinfo(dtInfos);
  134 + // 流输出导出文件
  135 + response.setHeader("content-type", "application/octet-stream");
  136 + response.setHeader("Content-Disposition", "attachment; filename=" + dataToolsFile.getFile().getName());
  137 + response.setContentType("application/octet-stream");
  138 +
  139 + OutputStream os = response.getOutputStream();
  140 + BufferedOutputStream bos = new BufferedOutputStream(os);
  141 +
  142 + InputStream is = new FileInputStream(dataToolsFile.getFile());
  143 + BufferedInputStream bis = new BufferedInputStream(is);
  144 +
  145 + int length = 0;
  146 + byte[] temp = new byte[1 * 1024 * 10];
  147 + while ((length = bis.read(temp)) != -1) {
  148 + bos.write(temp, 0, length);
  149 + }
  150 + bos.flush();
  151 + bis.close();
  152 + bos.close();
  153 + is.close();
  154 + }
123 } 155 }
src/main/java/com/bsth/service/schedule/TTInfoDetailService.java
@@ -2,7 +2,9 @@ package com.bsth.service.schedule; @@ -2,7 +2,9 @@ package com.bsth.service.schedule;
2 2
3 import com.bsth.entity.schedule.TTInfoDetail; 3 import com.bsth.entity.schedule.TTInfoDetail;
4 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit; 4 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
  5 +import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
5 import com.bsth.service.schedule.exception.ScheduleException; 6 import com.bsth.service.schedule.exception.ScheduleException;
  7 +import com.bsth.service.schedule.utils.DataToolsFile;
6 8
7 import java.util.List; 9 import java.util.List;
8 import java.util.Map; 10 import java.util.Map;
@@ -22,6 +24,14 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; { @@ -22,6 +24,14 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; {
22 TTInfoDetailForEdit.EditInfo getEditInfo(Integer xlid, Long ttid, Long maxfcno) throws ScheduleException; 24 TTInfoDetailForEdit.EditInfo getEditInfo(Integer xlid, Long ttid, Long maxfcno) throws ScheduleException;
23 25
24 /** 26 /**
  27 + * 导出动态时刻表。
  28 + * @param dtInfos
  29 + * @return
  30 + * @throws ScheduleException
  31 + */
  32 + DataToolsFile exportDynamicTTinfo(TTinfoDetailDynamicData.DTInfos dtInfos) throws ScheduleException;
  33 +
  34 + /**
25 * 获取时刻表最大发车顺序号 35 * 获取时刻表最大发车顺序号
26 * @param xlid 线路id 36 * @param xlid 线路id
27 * @param ttinfoid 时刻表id 37 * @param ttinfoid 时刻表id
src/main/java/com/bsth/service/schedule/datatools/TTInfoDetailDataToolsImpl.java
1 package com.bsth.service.schedule.datatools; 1 package com.bsth.service.schedule.datatools;
2 2
  3 +import com.bsth.entity.Station;
  4 +import com.bsth.service.StationService;
3 import com.bsth.service.schedule.exception.ScheduleException; 5 import com.bsth.service.schedule.exception.ScheduleException;
4 import com.bsth.service.schedule.utils.*; 6 import com.bsth.service.schedule.utils.*;
5 import jxl.Sheet; 7 import jxl.Sheet;
@@ -8,7 +10,13 @@ import jxl.write.Label; @@ -8,7 +10,13 @@ import jxl.write.Label;
8 import jxl.write.WritableSheet; 10 import jxl.write.WritableSheet;
9 import jxl.write.WritableWorkbook; 11 import jxl.write.WritableWorkbook;
10 import org.apache.commons.lang3.StringUtils; 12 import org.apache.commons.lang3.StringUtils;
  13 +import org.apache.poi.ss.usermodel.Cell;
11 import org.apache.poi.ss.usermodel.Row; 14 import org.apache.poi.ss.usermodel.Row;
  15 +import org.apache.poi.ss.util.CellRangeAddress;
  16 +import org.apache.poi.ss.util.WorkbookUtil;
  17 +import org.apache.poi.xssf.usermodel.XSSFRow;
  18 +import org.apache.poi.xssf.usermodel.XSSFSheet;
  19 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
12 import org.joda.time.DateTime; 20 import org.joda.time.DateTime;
13 import org.slf4j.Logger; 21 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
@@ -17,20 +25,27 @@ import org.springframework.beans.factory.annotation.Qualifier; @@ -17,20 +25,27 @@ import org.springframework.beans.factory.annotation.Qualifier;
17 import org.springframework.boot.context.properties.EnableConfigurationProperties; 25 import org.springframework.boot.context.properties.EnableConfigurationProperties;
18 import org.springframework.stereotype.Service; 26 import org.springframework.stereotype.Service;
19 27
  28 +import java.awt.*;
20 import java.io.File; 29 import java.io.File;
  30 +import java.io.FileOutputStream;
21 import java.io.PrintWriter; 31 import java.io.PrintWriter;
22 import java.io.StringWriter; 32 import java.io.StringWriter;
23 import java.util.*; 33 import java.util.*;
  34 +import java.util.List;
24 35
25 /** 36 /**
26 * Created by xu on 17/5/16. 37 * Created by xu on 17/5/16.
27 */ 38 */
28 @EnableConfigurationProperties(DataToolsProperties.class) 39 @EnableConfigurationProperties(DataToolsProperties.class)
29 @Service(value = "ttInfoDetail_dataTool") 40 @Service(value = "ttInfoDetail_dataTool")
30 -public class TTInfoDetailDataToolsImpl implements DataToolsService, TTInfoDetailForEdit { 41 +public class TTInfoDetailDataToolsImpl implements DataToolsService, TTInfoDetailForEdit, TTinfoDetailDynamicData {
31 /** 日志记录器 */ 42 /** 日志记录器 */
32 private final static Logger LOGGER = LoggerFactory.getLogger(TTInfoDetailDataToolsImpl.class); 43 private final static Logger LOGGER = LoggerFactory.getLogger(TTInfoDetailDataToolsImpl.class);
33 44
  45 + // TODO:之后改了
  46 + @Autowired
  47 + private StationService stationService;
  48 +
34 @Autowired 49 @Autowired
35 @Qualifier(value = "dataToolsServiceImpl") 50 @Qualifier(value = "dataToolsServiceImpl")
36 private DataToolsService dataToolsService; 51 private DataToolsService dataToolsService;
@@ -363,4 +378,140 @@ public class TTInfoDetailDataToolsImpl implements DataToolsService, TTInfoDetail @@ -363,4 +378,140 @@ public class TTInfoDetailDataToolsImpl implements DataToolsService, TTInfoDetail
363 } 378 }
364 } 379 }
365 380
  381 + @Override
  382 + public DataToolsFile exportDynamicTTinfo(DTInfos dtInfos) throws ScheduleException {
  383 + try {
  384 + // 使用POI,创建xlsx文件
  385 + XSSFWorkbook wb = new XSSFWorkbook();
  386 + XSSFSheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName("时刻表信息"));
  387 +
  388 + //-------------------------------- 1、路牌班次数据 -------------------------------//
  389 + List<LpObj> lpObjList = dtInfos.getLpObjList();
  390 +
  391 + // 构建第一行数据
  392 + XSSFRow lpHeadRow = sheet.createRow((short) 0);
  393 + if (lpObjList.size() == 0) {
  394 + throw new RuntimeException("没有班次数据!");
  395 + }
  396 + int groupCount = lpObjList.get(0).getGroupCount(); // 获取总圈数
  397 + if (groupCount == 0) {
  398 + throw new RuntimeException("总圈数为0,有问题!");
  399 + }
  400 +
  401 + // 构造表头
  402 + PoiUtils.createStringXSSFCell(wb, lpHeadRow, (short)0, "路牌", new Color(0x96b9d7));
  403 + Station station1 = stationService.findById(lpObjList.get(0).getStationRouteId1());
  404 + Station station2 = stationService.findById(lpObjList.get(1).getStationRouteId2());
  405 + for (int i = 0; i < groupCount; i++) {
  406 + PoiUtils.createStringXSSFCell(wb, lpHeadRow, (short) (i * 2 + 1),
  407 + station1.getStationName(), new Color(0x96b9d7));
  408 + PoiUtils.createStringXSSFCell(wb, lpHeadRow, (short) (i * 2 + 2),
  409 + station2.getStationName(), new Color(0x96b9d7));
  410 + }
  411 + PoiUtils.createStringXSSFCell(wb, lpHeadRow, (short) (groupCount * 2 + 1),
  412 + "路牌工时", new Color(0x96b9d7));
  413 + PoiUtils.createStringXSSFCell(wb, lpHeadRow, (short) (groupCount * 2 + 2),
  414 + "营运班次数", new Color(0x96b9d7));
  415 +
  416 + // 构建每个路牌的班次数据
  417 + for (int i = 0; i < lpObjList.size(); i++) {
  418 + LpObj lpObj = lpObjList.get(i);
  419 + XSSFRow lpRow = sheet.createRow((short) (i + 1));
  420 + PoiUtils.createStringXSSFCell(wb, lpRow, (short) 0, lpObj.getLpname());
  421 + for (int j = 0; j < groupCount; j++) {
  422 + PoiUtils.createStringXSSFCell(wb, lpRow, (short) (j * 2 + 1), "");
  423 + PoiUtils.createStringXSSFCell(wb, lpRow, (short) (j * 2 + 2), "");
  424 + }
  425 + for (BcObj bcObj : lpObj.getBcObjList()) {
  426 + Cell cell = lpRow.getCell((short) (bcObj.getGroupNo() * 2 + bcObj.getGroupBcNo() + 1));
  427 + cell.setCellValue(bcObj.getFcsj());
  428 + }
  429 + // 路牌工时/班次数
  430 + PoiUtils.createDoubleXSSFCell(wb, lpRow, (short) (groupCount * 2 + 1),
  431 + lpObj.getZgs() / 60);
  432 + // 营运班次数
  433 + PoiUtils.createIntegerXSSFCell(wb, lpRow, (short) (groupCount * 2 + 2),
  434 + lpObj.getZbc());
  435 + }
  436 +
  437 + // 自适应单元格长宽
  438 + sheet.autoSizeColumn(0);
  439 + for (int i = 0; i < groupCount; i++) {
  440 + sheet.autoSizeColumn(i * 2 + 1);
  441 + sheet.autoSizeColumn(i * 2 + 2);
  442 + }
  443 + sheet.autoSizeColumn(groupCount * 2 + 1);
  444 + sheet.autoSizeColumn(groupCount * 2 + 2);
  445 +
  446 + // 锁定行首,列首
  447 + sheet.createFreezePane(1, 1);
  448 +
  449 + //-------------------------------- 2、统计数据 -------------------------------//
  450 + List<StatInfo> statInfos = dtInfos.getStatInfoList();
  451 +
  452 + // 创建总的统计数据格式
  453 + // 第一行 统计数据
  454 + // 第二行 序号,统计项目(8个单元格合并),统计数值
  455 + // 第三行开始数据,一共20行
  456 +
  457 + int startrow = lpObjList.size() + 3;
  458 + for (int i = startrow; i <= startrow + 22; i++) {
  459 + XSSFRow xssfRow = sheet.createRow(i);
  460 + for (int j = 0; j < 10; j++) {
  461 + PoiUtils.createStringXSSFCell(wb, xssfRow, (short) j, "");
  462 + }
  463 + }
  464 + // 合并第一行
  465 + sheet.addMergedRegion(new CellRangeAddress(startrow, startrow, 0, 9));
  466 + sheet.getRow(startrow).getCell(0).setCellValue("统计数据");
  467 + // 合并第二行
  468 + sheet.getRow(startrow + 1).getCell(0).setCellValue("序号");
  469 + sheet.getRow(startrow + 1).getCell(1).setCellValue("统计项目");
  470 + sheet.getRow(startrow + 1).getCell(9).setCellValue("统计数值");
  471 + sheet.addMergedRegion(new CellRangeAddress(startrow + 1, startrow + 1, 1, 8));
  472 + // 处理后面具体统计行
  473 + for (int row = startrow + 2; row <= startrow + 2 + statInfos.size(); row++) {
  474 + sheet.addMergedRegion(new CellRangeAddress(row, row, 1, 8));
  475 + }
  476 +
  477 + for (int i = 0; i < statInfos.size(); i++) {
  478 + StatInfo statInfo = statInfos.get(i);
  479 +
  480 + // 1、统计序号
  481 + PoiUtils.setIntegerStyleXSSFCellStyle(wb, sheet.getRow(startrow + 2 + i).getCell(0));
  482 + sheet.getRow(startrow + 2 + i).getCell(0).setCellValue(i);
  483 +
  484 + // 2、统计项目
  485 + sheet.getRow(startrow + 2 + i).getCell(1).setCellValue(statInfo.getStatItem());
  486 +
  487 + // 3、统计数值
  488 + PoiUtils.setDoubleStyleXSSFCellStyle(wb, sheet.getRow(startrow + 2 + i).getCell(9));
  489 + sheet.getRow(startrow + 2 + i).getCell(9).setCellValue(statInfo.getStatValue());
  490 + }
  491 +
  492 + // 最后内存写入文件
  493 + String filepath = dataToolsProperties.getFileoutputDir() +
  494 + File.separator +
  495 + "动态时刻表-" +
  496 + new DateTime().toString("yyyyMMddHHmmss") + ".xlsx";
  497 + FileOutputStream fileOut = new FileOutputStream(filepath);
  498 + wb.write(fileOut);
  499 +
  500 + DataToolsFile dataToolsFile = new DataToolsFile();
  501 + dataToolsFile.setFileType(DataToolsFileType.XLSX);
  502 + dataToolsFile.setFile(new File(filepath));
  503 +
  504 + return dataToolsFile;
  505 +
  506 + } catch (Exception exp) {
  507 + LOGGER.info("//---------------- 动态时刻表输出 failed... ----------------//");
  508 +
  509 + StringWriter sw = new StringWriter();
  510 + exp.printStackTrace(new PrintWriter(sw));
  511 + LOGGER.info(sw.toString());
  512 +
  513 + throw new ScheduleException(exp);
  514 + }
  515 +
  516 + }
366 } 517 }
src/main/java/com/bsth/service/schedule/datatools/TTinfoDetailDynamicData.java 0 → 100644
  1 +package com.bsth.service.schedule.datatools;
  2 +
  3 +import com.bsth.service.schedule.exception.ScheduleException;
  4 +import com.bsth.service.schedule.utils.DataToolsFile;
  5 +import com.fasterxml.jackson.annotation.JsonCreator;
  6 +import com.fasterxml.jackson.annotation.JsonValue;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 动态时刻表数据。
  12 + */
  13 +public interface TTinfoDetailDynamicData {
  14 +
  15 + //---------------------- 生成时刻表用对象(以下) ---------------------//
  16 + public static enum BcType { // 班次类型枚举
  17 + IN("in"), // 进场
  18 + OUT("out"), // 出场
  19 + BD("bd"), // 早例保
  20 + LC("lc"), // 晚例保
  21 + NORMAL("normal"); // 正常
  22 + private String flag;
  23 +
  24 + @JsonCreator
  25 + private BcType(String flag) {
  26 + this.flag = flag;
  27 + }
  28 +
  29 + @JsonValue
  30 + public String getFlag() {
  31 + return flag;
  32 + }
  33 +
  34 + public void setFlag(String flag) {
  35 + this.flag = flag;
  36 + }
  37 + }
  38 +
  39 + public static class BcObj { // 班次对象
  40 + /** 班次时间 */
  41 + private Integer bcsj;
  42 + /** 停站时间 */
  43 + private Integer ssj;
  44 + /** 吃饭时间 */
  45 + private Integer eatsj;
  46 +
  47 + /** 停车场id */
  48 + private Integer tccid;
  49 + /** 起点站id */
  50 + private Integer qdzid;
  51 + /** 终点站id */
  52 + private Integer zdzid;
  53 +
  54 + /** 是否上行 */
  55 + private Boolean isUp;
  56 +
  57 + /** 班次类型 */
  58 + private BcType bcType;
  59 + /** 发车时刻 */
  60 + private String fcsj;
  61 +
  62 + /** 第几圈(从1开始) */
  63 + private Integer groupNo;
  64 + /** 圈里第几个班次(1或者2) */
  65 + private Integer groupBcNo;
  66 +
  67 + public Integer getBcsj() {
  68 + return bcsj;
  69 + }
  70 +
  71 + public void setBcsj(Integer bcsj) {
  72 + this.bcsj = bcsj;
  73 + }
  74 +
  75 + public Integer getSsj() {
  76 + return ssj;
  77 + }
  78 +
  79 + public void setSsj(Integer ssj) {
  80 + this.ssj = ssj;
  81 + }
  82 +
  83 + public Integer getEatsj() {
  84 + return eatsj;
  85 + }
  86 +
  87 + public void setEatsj(Integer eatsj) {
  88 + this.eatsj = eatsj;
  89 + }
  90 +
  91 + public Integer getTccid() {
  92 + return tccid;
  93 + }
  94 +
  95 + public void setTccid(Integer tccid) {
  96 + this.tccid = tccid;
  97 + }
  98 +
  99 + public Integer getQdzid() {
  100 + return qdzid;
  101 + }
  102 +
  103 + public void setQdzid(Integer qdzid) {
  104 + this.qdzid = qdzid;
  105 + }
  106 +
  107 + public Integer getZdzid() {
  108 + return zdzid;
  109 + }
  110 +
  111 + public void setZdzid(Integer zdzid) {
  112 + this.zdzid = zdzid;
  113 + }
  114 +
  115 + public BcType getBcType() {
  116 + return bcType;
  117 + }
  118 +
  119 + public void setBcType(BcType bcType) {
  120 + this.bcType = bcType;
  121 + }
  122 +
  123 + public String getFcsj() {
  124 + return fcsj;
  125 + }
  126 +
  127 + public void setFcsj(String fcsj) {
  128 + this.fcsj = fcsj;
  129 + }
  130 +
  131 + public Boolean getIsUp() {
  132 + return isUp;
  133 + }
  134 +
  135 + public void setIsUp(Boolean isUp) {
  136 + this.isUp = isUp;
  137 + }
  138 +
  139 + public Integer getGroupNo() {
  140 + return groupNo;
  141 + }
  142 +
  143 + public void setGroupNo(Integer groupNo) {
  144 + this.groupNo = groupNo;
  145 + }
  146 +
  147 + public Integer getGroupBcNo() {
  148 + return groupBcNo;
  149 + }
  150 +
  151 + public void setGroupBcNo(Integer groupBcNo) {
  152 + this.groupBcNo = groupBcNo;
  153 + }
  154 + }
  155 +
  156 + public static class LpObj { // 路牌对象
  157 + /** 路牌名字 */
  158 + private String lpname;
  159 + /** 每圈的第一个班次是否上行 */
  160 + private Boolean isUp;
  161 +
  162 + /** 第一个班次起点站路由id */
  163 + private Integer stationRouteId1;
  164 + /** 第二个班次起点站路由id */
  165 + private Integer stationRouteId2;
  166 +
  167 + /** 班次列表 */
  168 + private List<BcObj> bcObjList;
  169 + /** 总圈数 */
  170 + private Integer groupCount;
  171 +
  172 + /** 总工时 */
  173 + private Double zgs;
  174 + /** 总班次 */
  175 + private Integer zbc;
  176 +
  177 +
  178 + public String getLpname() {
  179 + return lpname;
  180 + }
  181 +
  182 + public void setLpname(String lpname) {
  183 + this.lpname = lpname;
  184 + }
  185 +
  186 + public Boolean getIsUp() {
  187 + return isUp;
  188 + }
  189 +
  190 + public void setIsUp(Boolean isUp) {
  191 + this.isUp = isUp;
  192 + }
  193 +
  194 + public List<BcObj> getBcObjList() {
  195 + return bcObjList;
  196 + }
  197 +
  198 + public void setBcObjList(List<BcObj> bcObjList) {
  199 + this.bcObjList = bcObjList;
  200 + }
  201 +
  202 + public Integer getGroupCount() {
  203 + return groupCount;
  204 + }
  205 +
  206 + public void setGroupCount(Integer groupCount) {
  207 + this.groupCount = groupCount;
  208 + }
  209 +
  210 + public Double getZgs() {
  211 + return zgs;
  212 + }
  213 +
  214 + public void setZgs(Double zgs) {
  215 + this.zgs = zgs;
  216 + }
  217 +
  218 + public Integer getZbc() {
  219 + return zbc;
  220 + }
  221 +
  222 + public void setZbc(Integer zbc) {
  223 + this.zbc = zbc;
  224 + }
  225 +
  226 + public Integer getStationRouteId1() {
  227 + return stationRouteId1;
  228 + }
  229 +
  230 + public void setStationRouteId1(Integer stationRouteId1) {
  231 + this.stationRouteId1 = stationRouteId1;
  232 + }
  233 +
  234 + public Integer getStationRouteId2() {
  235 + return stationRouteId2;
  236 + }
  237 +
  238 + public void setStationRouteId2(Integer stationRouteId2) {
  239 + this.stationRouteId2 = stationRouteId2;
  240 + }
  241 + }
  242 +
  243 + public static class StatInfo { // 统计数据对象
  244 + /** 统计项目 */
  245 + private String statItem;
  246 + /** 统计值 */
  247 + private Double statValue;
  248 +
  249 + public String getStatItem() {
  250 + return statItem;
  251 + }
  252 +
  253 + public void setStatItem(String statItem) {
  254 + this.statItem = statItem;
  255 + }
  256 +
  257 + public Double getStatValue() {
  258 + return statValue;
  259 + }
  260 +
  261 + public void setStatValue(Double statValue) {
  262 + this.statValue = statValue;
  263 + }
  264 + }
  265 +
  266 + public static class DTInfos { // 所有数据信息
  267 + /** 路牌班次数据列表 */
  268 + private List<LpObj> lpObjList;
  269 + /** 统计数据列表 */
  270 + private List<StatInfo> statInfoList;
  271 +
  272 + public List<LpObj> getLpObjList() {
  273 + return lpObjList;
  274 + }
  275 +
  276 + public void setLpObjList(List<LpObj> lpObjList) {
  277 + this.lpObjList = lpObjList;
  278 + }
  279 +
  280 + public List<StatInfo> getStatInfoList() {
  281 + return statInfoList;
  282 + }
  283 +
  284 + public void setStatInfoList(List<StatInfo> statInfoList) {
  285 + this.statInfoList = statInfoList;
  286 + }
  287 + }
  288 +
  289 + //---------------------- 生成时刻表用对象(以上) ---------------------//
  290 +
  291 + /**
  292 + * 导出动态时刻表数据。
  293 + * @param dtInfos
  294 + * @return
  295 + * @throws ScheduleException
  296 + */
  297 + public DataToolsFile exportDynamicTTinfo(DTInfos dtInfos) throws ScheduleException;
  298 +}
src/main/java/com/bsth/service/schedule/impl/TTInfoDetailServiceImpl.java
@@ -19,6 +19,7 @@ import com.bsth.service.StationRouteService; @@ -19,6 +19,7 @@ import com.bsth.service.StationRouteService;
19 import com.bsth.service.schedule.GuideboardInfoService; 19 import com.bsth.service.schedule.GuideboardInfoService;
20 import com.bsth.service.schedule.TTInfoDetailService; 20 import com.bsth.service.schedule.TTInfoDetailService;
21 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit; 21 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
  22 +import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
22 import com.bsth.service.schedule.exception.ScheduleException; 23 import com.bsth.service.schedule.exception.ScheduleException;
23 import com.bsth.service.schedule.utils.DataToolsFile; 24 import com.bsth.service.schedule.utils.DataToolsFile;
24 import com.bsth.service.schedule.utils.DataToolsFileType; 25 import com.bsth.service.schedule.utils.DataToolsFileType;
@@ -86,6 +87,10 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im @@ -86,6 +87,10 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
86 private TTInfoDetailForEdit ttInfoDetailForEdit; 87 private TTInfoDetailForEdit ttInfoDetailForEdit;
87 88
88 @Autowired 89 @Autowired
  90 + @Qualifier(value = "ttInfoDetail_dataTool")
  91 + private TTinfoDetailDynamicData tTinfoDetailDynamicData;
  92 +
  93 + @Autowired
89 private JdbcTemplate jdbcTemplate; 94 private JdbcTemplate jdbcTemplate;
90 95
91 /** 96 /**
@@ -134,6 +139,10 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im @@ -134,6 +139,10 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
134 return dataToolsService.exportData(params); 139 return dataToolsService.exportData(params);
135 } 140 }
136 141
  142 + @Override
  143 + public DataToolsFile exportDynamicTTinfo(TTinfoDetailDynamicData.DTInfos dtInfos) throws ScheduleException {
  144 + return tTinfoDetailDynamicData.exportDynamicTTinfo(dtInfos);
  145 + }
137 146
138 @Override 147 @Override
139 public TTInfoDetailForEdit.EditInfo getEditInfo(Integer xlid, Long ttid, Long maxfcno) throws ScheduleException { 148 public TTInfoDetailForEdit.EditInfo getEditInfo(Integer xlid, Long ttid, Long maxfcno) throws ScheduleException {
src/main/java/com/bsth/service/schedule/utils/PoiUtils.java
1 package com.bsth.service.schedule.utils; 1 package com.bsth.service.schedule.utils;
2 2
3 import org.apache.poi.hssf.usermodel.HSSFDateUtil; 3 import org.apache.poi.hssf.usermodel.HSSFDateUtil;
4 -import org.apache.poi.ss.usermodel.Cell;  
5 -import org.apache.poi.xssf.usermodel.XSSFCell; 4 +import org.apache.poi.ss.usermodel.*;
  5 +import org.apache.poi.ss.util.WorkbookUtil;
  6 +import org.apache.poi.xssf.usermodel.*;
6 7
  8 +import java.awt.Color;
7 import java.text.DecimalFormat; 9 import java.text.DecimalFormat;
8 import java.text.SimpleDateFormat; 10 import java.text.SimpleDateFormat;
9 import java.util.Date; 11 import java.util.Date;
@@ -52,4 +54,136 @@ public class PoiUtils { @@ -52,4 +54,136 @@ public class PoiUtils {
52 } 54 }
53 return cellValue; 55 return cellValue;
54 } 56 }
  57 +
  58 + public static XSSFCell createStringXSSFCell(
  59 + XSSFWorkbook xssfWorkbook, XSSFRow xssfRow, short column, String value,
  60 + Color backgroundColor) {
  61 + return createXSSFCell(
  62 + xssfWorkbook, xssfRow, column,
  63 + value, XSSFCell.CELL_TYPE_STRING,
  64 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  65 + BorderStyle.MEDIUM, new Color(0xdedede),
  66 + (short) 13, new Color(0x2765A7), "宋体",
  67 + backgroundColor, FillPatternType.SOLID_FOREGROUND
  68 + );
  69 + }
  70 +
  71 + public static XSSFCell createStringXSSFCell(
  72 + XSSFWorkbook xssfWorkbook, XSSFRow xssfRow, short column, String value) {
  73 + return createXSSFCell(
  74 + xssfWorkbook, xssfRow, column,
  75 + value, XSSFCell.CELL_TYPE_STRING,
  76 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  77 + BorderStyle.MEDIUM, new Color(0xdedede),
  78 + (short) 13, new Color(0x2765A7), "宋体",
  79 + new Color(0xffffff), FillPatternType.SOLID_FOREGROUND
  80 + );
  81 + }
  82 +
  83 + public static XSSFCell createDoubleXSSFCell(
  84 + XSSFWorkbook xssfWorkbook, XSSFRow xssfRow, short column, Double value) {
  85 + return createXSSFCell(
  86 + xssfWorkbook, xssfRow, column,
  87 + value, XSSFCell.CELL_TYPE_NUMERIC,
  88 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  89 + BorderStyle.MEDIUM, new Color(0xdedede),
  90 + (short) 13, new Color(0x2765A7), "宋体",
  91 + new Color(0xffffff), FillPatternType.SOLID_FOREGROUND
  92 + );
  93 + }
  94 +
  95 + public static XSSFCell createIntegerXSSFCell(
  96 + XSSFWorkbook xssfWorkbook, XSSFRow xssfRow, short column, Integer value) {
  97 + return createXSSFCell(
  98 + xssfWorkbook, xssfRow, column,
  99 + value, XSSFCell.CELL_TYPE_NUMERIC,
  100 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  101 + BorderStyle.MEDIUM, new Color(0xdedede),
  102 + (short) 13, new Color(0x2765A7), "宋体",
  103 + new Color(0xffffff), FillPatternType.SOLID_FOREGROUND
  104 + );
  105 + }
  106 +
  107 + public static XSSFCell setIntegerStyleXSSFCellStyle(XSSFWorkbook xssfWorkbook, XSSFCell xssfCell) {
  108 + CreationHelper creationHelper = xssfWorkbook.getCreationHelper();
  109 + XSSFCellStyle xssfCellStyle = xssfCell.getCellStyle();
  110 + xssfCellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0"));
  111 + return xssfCell;
  112 + }
  113 + public static XSSFCell setDoubleStyleXSSFCellStyle(XSSFWorkbook xssfWorkbook, XSSFCell xssfCell) {
  114 + CreationHelper creationHelper = xssfWorkbook.getCreationHelper();
  115 + XSSFCellStyle xssfCellStyle = xssfCell.getCellStyle();
  116 + xssfCellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00"));
  117 + return xssfCell;
  118 + }
  119 +
  120 + public static XSSFCell createXSSFCell(
  121 + XSSFWorkbook xssfWorkbook, XSSFRow xssfRow, short column,
  122 + Object value, int valueType,
  123 + HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment,
  124 + BorderStyle borderStyle, Color borderColor,
  125 + short fontSize, Color fontColor, String fontName,
  126 + Color backgroudColor, FillPatternType fillPatternType) {
  127 + CreationHelper creationHelper = xssfWorkbook.getCreationHelper();
  128 +
  129 + // 1、创建单元格对象
  130 + XSSFCell cell = xssfRow.createCell(column);
  131 +
  132 + // 2、设定样式
  133 + XSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();
  134 +
  135 + // 设定值
  136 + if (valueType == XSSFCell.CELL_TYPE_STRING) {
  137 + cell.setCellValue(creationHelper.createRichTextString(
  138 + WorkbookUtil.createSafeSheetName(String.valueOf(value))));
  139 + } else if (valueType == XSSFCell.CELL_TYPE_NUMERIC) {
  140 + if (value instanceof Date) { // 日期
  141 + cellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-mm-dd"));
  142 + cell.setCellValue((Date) value);
  143 + } else if (value instanceof Double) {
  144 + cellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00"));
  145 + cell.setCellValue((Double) value);
  146 + } else if (value instanceof Integer) {
  147 + cellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0"));
  148 + cell.setCellValue(Double.valueOf(value.toString()));
  149 + } else {
  150 + throw new RuntimeException("只支持 Date Double Integer 单元格类型");
  151 + }
  152 + } else {
  153 + throw new RuntimeException("暂时不支持字符串、日期、数字以为的类型");
  154 + }
  155 +
  156 + // 对齐方式
  157 + cellStyle.setAlignment(horizontalAlignment);
  158 + cellStyle.setVerticalAlignment(verticalAlignment);
  159 +
  160 + // 边框样式
  161 + cellStyle.setBorderTop(borderStyle);
  162 + cellStyle.setTopBorderColor(new XSSFColor(borderColor));
  163 + cellStyle.setBorderBottom(borderStyle);
  164 + cellStyle.setBottomBorderColor(new XSSFColor(borderColor));
  165 + cellStyle.setBorderLeft(borderStyle);
  166 + cellStyle.setLeftBorderColor(new XSSFColor(borderColor));
  167 + cellStyle.setBorderRight(borderStyle);
  168 + cellStyle.setRightBorderColor(new XSSFColor(borderColor));
  169 +
  170 + // 字体颜色
  171 + XSSFFont font = xssfWorkbook.createFont();
  172 + font.setColor(new XSSFColor(fontColor));
  173 + font.setFontHeightInPoints(fontSize);
  174 + font.setFontName(fontName);
  175 + cellStyle.setFont(font);
  176 +
  177 +
  178 + // 单元背景色
  179 + cellStyle.setFillForegroundColor(new XSSFColor(backgroudColor));
  180 + cellStyle.setFillPattern(fillPatternType);
  181 +
  182 + // TODO
  183 +
  184 + cell.setCellStyle(cellStyle);
  185 + return cell;
  186 + }
  187 +
55 } 188 }
  189 +
src/main/resources/static/index.html
@@ -61,9 +61,9 @@ @@ -61,9 +61,9 @@
61 href="/metronic_v4.5.4/plugins/bootstrap-datetimepicker-2/css/bootstrap-datetimepicker.min.css" 61 href="/metronic_v4.5.4/plugins/bootstrap-datetimepicker-2/css/bootstrap-datetimepicker.min.css"
62 rel="stylesheet" type="text/css" /> 62 rel="stylesheet" type="text/css" />
63 <!-- table 表格控件 --> 63 <!-- table 表格控件 -->
64 - <link rel="stylesheet"  
65 - href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css"  
66 - type="text/css" /> 64 + <!--<link rel="stylesheet"-->
  65 + <!--href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css"-->
  66 + <!--type="text/css" />-->
67 <link href="/metronic_v4.5.4/plugins/bootstrap-tagsinput/bootstrap-tagsinput.css" rel="stylesheet" type="text/css"/> 67 <link href="/metronic_v4.5.4/plugins/bootstrap-tagsinput/bootstrap-tagsinput.css" rel="stylesheet" type="text/css"/>
68 <!-- handsontable样式 --> 68 <!-- handsontable样式 -->
69 <link rel="stylesheet" 69 <link rel="stylesheet"
@@ -612,24 +612,24 @@ @@ -612,24 +612,24 @@
612 612
613 <!-- 地图相关 --> 613 <!-- 地图相关 -->
614 <!-- 百度 --> 614 <!-- 百度 -->
615 -<script  
616 - src="http://api.map.baidu.com/api?v=2.0&ak=IGGrr4UjwIYzatoCRFKEL8sT"  
617 - data-exclude=1></script>  
618 -<script  
619 - src="http://api.map.baidu.com/library/TrafficControl/1.4/src/TrafficControl_min.js"  
620 - data-exclude=1></script>  
621 -<script type="text/javascript"  
622 - src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"  
623 - data-exclude=1></script>  
624 -<script type="text/javascript"  
625 - src="http://api.map.baidu.com/library/RichMarker/1.2/src/RichMarker_min.js "  
626 - data-exclude=1></script> 615 +<!--<script-->
  616 + <!--src="http://api.map.baidu.com/api?v=2.0&ak=IGGrr4UjwIYzatoCRFKEL8sT"-->
  617 + <!--data-exclude=1></script>-->
  618 +<!--<script-->
  619 + <!--src="http://api.map.baidu.com/library/TrafficControl/1.4/src/TrafficControl_min.js"-->
  620 + <!--data-exclude=1></script>-->
  621 +<!--<script type="text/javascript"-->
  622 + <!--src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"-->
  623 + <!--data-exclude=1></script>-->
  624 +<!--<script type="text/javascript"-->
  625 + <!--src="http://api.map.baidu.com/library/RichMarker/1.2/src/RichMarker_min.js "-->
  626 + <!--data-exclude=1></script>-->
627 <script src="/assets/js/baidu/TextIconOverlay.js" data-exclude=1></script> 627 <script src="/assets/js/baidu/TextIconOverlay.js" data-exclude=1></script>
628 <script src="/assets/js/baidu//MarkerClusterer.js" data-exclude=1></script> 628 <script src="/assets/js/baidu//MarkerClusterer.js" data-exclude=1></script>
629 <!-- 高德 --> 629 <!-- 高德 -->
630 -<script  
631 - src="http://webapi.amap.com/maps?v=1.3&key=16cb1c5043847e09ef9edafdd77befda"  
632 - data-exclude=1></script> 630 +<!--<script-->
  631 + <!--src="http://webapi.amap.com/maps?v=1.3&key=16cb1c5043847e09ef9edafdd77befda"-->
  632 + <!--data-exclude=1></script>-->
633 633
634 <script src="/real_control_v2/assets/plugins/perfect-scrollbar/perfect-scrollbar.jquery.js" merge="plugins"></script> 634 <script src="/real_control_v2/assets/plugins/perfect-scrollbar/perfect-scrollbar.jquery.js" merge="plugins"></script>
635 635
src/main/resources/static/pages/base/timesmodel/gantt.html
@@ -47,6 +47,9 @@ @@ -47,6 +47,9 @@
47 <div class="btn-group btn-group-devided checkbtn" data-toggle="buttons"> 47 <div class="btn-group btn-group-devided checkbtn" data-toggle="buttons">
48 <a class="btn btn-circle blue checkAdd" href="javascript:;" data-pjax><i class="fa fa-check"></i> 保存数据</a> 48 <a class="btn btn-circle blue checkAdd" href="javascript:;" data-pjax><i class="fa fa-check"></i> 保存数据</a>
49 </div> 49 </div>
  50 + <div class="btn-group btn-group-devided exportbtn" data-toggle="buttons">
  51 + <a class="btn btn-circle blue exportAdd" href="javascript:;" data-pjax><i class="fa fa-file-excel-o"></i> 导出数据</a>
  52 + </div>
50 <div class="btn-group checkbtn"> 53 <div class="btn-group checkbtn">
51 <a href="javascript:" class="btn red btn-outline btn-circle" data-toggle="dropdown" aria-expanded="false"> 54 <a href="javascript:" class="btn red btn-outline btn-circle" data-toggle="dropdown" aria-expanded="false">
52 <i class="fa fa-cog"></i> 55 <i class="fa fa-cog"></i>
src/main/resources/static/pages/base/timesmodel/js/add-form-reload.js
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 $('.openHaveSkb').on('click',function() { 7 $('.openHaveSkb').on('click',function() {
8 var skbId = $("#skbNameSelect").val(); 8 var skbId = $("#skbNameSelect").val();
9 var argus = { 9 var argus = {
10 - baseRes:"0",carPark:"FFFFFF68",downInMileage:"0", 10 + baseRes:"0",czarPark:"FFFFFF68",downInMileage:"0",
11 downInTimer:"0",downMileage:"3.5",downOutMileage:"0", 11 downInTimer:"0",downMileage:"3.5",downOutMileage:"0",
12 downOutTimer:"0",downStopTime:"10",downTravelTime:"7", 12 downOutTimer:"0",downStopTime:"10",downTravelTime:"7",
13 down_s:"26922_26928",earlyDownTime:"7",earlyEndTime:"08:30", 13 down_s:"26922_26928",earlyDownTime:"7",earlyEndTime:"08:30",
src/main/resources/static/pages/base/timesmodel/js/add-form-wizard.js
@@ -372,11 +372,22 @@ var SKBFormWizard = function() { @@ -372,11 +372,22 @@ var SKBFormWizard = function() {
372 } 372 }
373 sjdArr[s].num = num; 373 sjdArr[s].num = num;
374 } 374 }
375 - map.zgfbeforepcs = sjdArr[0].num;// 早高峰前配车数  
376 - map.zgfpcs = sjdArr[2].num;// 早高峰配车数  
377 - map.gfzjpcs = sjdArr[4].num;// 高峰之间配车数  
378 - map.wgfpcs = sjdArr[2].num ;// 晚高峰配车数  
379 - map.wgfafterpcs = sjdArr[1].num + sjdArr[3].num;// 晚高峰后配车数 375 +
  376 + // 注意:如果为0,设置成 10 17默认值
  377 + map.zgfbeforepcs = sjdArr[0].num == 0 ? 10 : sjdArr[0].num;// 早高峰前配车数
  378 + map.zgfpcs = sjdArr[2].num == 0 ? 17 : sjdArr[2].num;// 早高峰配车数
  379 + map.gfzjpcs = sjdArr[4].num == 0 ? 10 : sjdArr[4].num;// 高峰之间配车数
  380 + map.wgfpcs = sjdArr[2].num == 0 ? 17 : sjdArr[2].num ;// 晚高峰配车数
  381 + map.wgfafterpcs = (sjdArr[1].num + sjdArr[3].num) == 0 ? 10 : sjdArr[1].num + sjdArr[3].num;// 晚高峰后配车数
  382 +
  383 + // 注意:高峰 5 低谷 20 其他 10
  384 + map.upStopTime = 10;
  385 + map.downStopTime = 10;
  386 + map.mixstopTime = 5;
  387 + map.maxstopTime = 20;
  388 +
  389 + //alert("dddd");
  390 +
380 // 返回参数详情模版. 391 // 返回参数详情模版.
381 return cb && cb ({'forminput':template(tempName,{map:map}),'datadisplay': template(tempName +'config',{map:null})}); 392 return cb && cb ({'forminput':template(tempName,{map:map}),'datadisplay': template(tempName +'config',{map:null})});
382 }); 393 });
@@ -640,13 +651,49 @@ var SKBFormWizard = function() { @@ -640,13 +651,49 @@ var SKBFormWizard = function() {
640 651
641 // 表单提交. 652 // 表单提交.
642 function submit(p,argus) { 653 function submit(p,argus) {
643 - storage.setItem("Gantt_AgursData",JSON.stringify(argus));  
644 - if(p!=null) {  
645 - storage.setItem('isDoDate',JSON.stringify({'rsD':p.rsD,'rsLP':p.rsLp}));  
646 - }else {  
647 - storage.setItem('isDoDate','');  
648 - }  
649 - loadPage('gantt.html'); 654 + var baseRes2 = $('#submit_argus_form input[name="baseRes"]:checked').val();// 获取参数方式值.
  655 + if (baseRes2 == 0) {
  656 + // TODO:客流暂时有问题,直接使用现有时刻表打开,日后有机会再改好
  657 + var skbId2 = $("#skbNameSelect").val();
  658 + var argus2 = {
  659 + baseRes:"0",carPark:"FFFFFF68",downInMileage:"0",
  660 + downInTimer:"0",downMileage:"3.5",downOutMileage:"0",
  661 + downOutTimer:"0",downStopTime:"10",downTravelTime:"7",
  662 + down_s:"26922_26928",earlyDownTime:"7",earlyEndTime:"08:30",
  663 + earlyStartTime:"06:31",earlyUpTime:"10",endStationEndTime:"22:30",
  664 + endStationFirstTime:"05:50",gfzjpcs:"7",istidc:1,kfsj:"",krl:"50",
  665 + lateDownTime:"7",lateEndTime:"18:30",lateStartTime:"16:31",
  666 + lateUpTime:"10",lb:"15",lineName:"801702_801702_1109路",
  667 + linePlayType:"0",maxstopTime:"20",mixstopTime:"8",qjDownTime:"",
  668 + qjUpTime:"",skbName:skbId2,skbmc:"2016.4.6双时刻表",
  669 + startStationEndTime:"23:00",startStationFirstTime:"06:15",tcc_id:45,troughDownTime:"7",troughUpTime:"10",upInMileage:"0",
  670 + upInTimer:"10",upMileage:"3.5",upOutMileage:"0",upOutTimer:"10",upStopTime:"10",upTravelTime:"10",
  671 + up_s:"26912_26921",wgfafterpcs:"5",wgfpcs:"10",workeDinner:"20",workeLunch:"20",xlmc:"1109路",zgfbeforepcs:"3",zgfpcs:"10",}
  672 + // 获取时刻表明细.
  673 + $get('/tidc/all',{'ttinfo.id_eq':parseInt(argus.skbName)},function(data) {
  674 + var p = formatData(data.data,argus2);
  675 + // TODO:添加parent
  676 + for (var ii = 0; ii < p.rsD.length; ii++) {
  677 + p.rsD[ii].parent = p.rsD[ii].lpNo;// 路牌名称
  678 + }
  679 +
  680 + argus2.istidc = 1;
  681 + var storage = window.localStorage;
  682 + storage.setItem("Gantt_AgursData",JSON.stringify(argus2));
  683 + storage.setItem('isDoDate',JSON.stringify({'rsD':p.rsD,'rsLP':p.rsLp}));
  684 + loadPage('gantt.html');
  685 + });
  686 + } else {
  687 + storage.setItem("Gantt_AgursData",JSON.stringify(argus));
  688 + if(p!=null) {
  689 + storage.setItem('isDoDate',JSON.stringify({'rsD':p.rsD,'rsLP':p.rsLp}));
  690 + }else {
  691 + storage.setItem('isDoDate','');
  692 + }
  693 + loadPage('gantt.html');
  694 + }
  695 +
  696 +
650 } 697 }
651 } 698 }
652 }); 699 });
src/main/resources/static/pages/base/timesmodel/js/gantt.js
@@ -84,6 +84,7 @@ @@ -84,6 +84,7 @@
84 // TODO:var seDate = getksjssj(null,seMap.s); 关联参数必须设置 84 // TODO:var seDate = getksjssj(null,seMap.s); 关联参数必须设置
85 // TODO:CSMap.maxCar 之后要设定一下的 85 // TODO:CSMap.maxCar 之后要设定一下的
86 data = Main_v2.BXPplaceClassesTime03(_paramObj, CSMap.maxCar); 86 data = Main_v2.BXPplaceClassesTime03(_paramObj, CSMap.maxCar);
  87 + Main_v2.exportDataConfig(data.aInternalLpObj);
87 } 88 }
88 89
89 }else { 90 }else {
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalBcObj.js
@@ -51,7 +51,7 @@ var InternalBcObj = function( @@ -51,7 +51,7 @@ var InternalBcObj = function(
51 //------------------- get/set 方法 -------------------// 51 //------------------- get/set 方法 -------------------//
52 52
53 InternalBcObj.prototype.fnSetIsFirstBc = function(bFlag) { 53 InternalBcObj.prototype.fnSetIsFirstBc = function(bFlag) {
54 - this._$_bIsFirstBc = true; 54 + this._$_bIsFirstBc = bFlag;
55 }; 55 };
56 InternalBcObj.prototype.fnIsFirstBc = function() { 56 InternalBcObj.prototype.fnIsFirstBc = function() {
57 return this._$_bIsFirstBc; 57 return this._$_bIsFirstBc;
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalLpObj.js
1 -/**  
2 - * 内部路牌对象。  
3 - * @constructor  
4 - */  
5 -var InternalLpObj = function(  
6 - orilpObj, // 原始路牌对象  
7 - qCount, // 总共多少圈  
8 - isUp // 圈是以上行开始还是下行开始  
9 -) {  
10 - // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)  
11 - this._$$_orign_lp_obj = orilpObj;  
12 -  
13 - this._$_isUp = isUp;  
14 -  
15 - // 路牌的圈数,注意每个路牌的圈数都是一致的,  
16 - // 但并不是每一圈都有值  
17 - // 第1圈从上标线开始  
18 - // 第0圈表示中标线的第一个班次组成的半圈  
19 - // 有多少圈根据最终迭代的结果来看  
20 - this._$_qCount = qCount;  
21 - // 保存的是 InternalGroupBcObj 对象  
22 - this._$_groupBcArray = new Array(qCount);  
23 -  
24 - var i;  
25 - for (i = 0; i < this._$_qCount; i++) {  
26 - this._$_groupBcArray[i] = new InternalGroupObj(  
27 - this, this._$_isUp, undefined, undefined);  
28 - }  
29 -  
30 - // 距离上一个路牌的最小发车间隔时间  
31 - // 用于纵向添加班次的时候使用  
32 - // 默认第一个路牌为0  
33 - this._$_minVerticalIntervalTime = 0;  
34 -  
35 - // 详细记录每圈每个方向上的发车间隔时间  
36 - // 第一维度表示圈数,第二维度表示第一个方向,第二个方向  
37 - // 第一个方向是否上行由 _$_isUp 决定  
38 - // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔  
39 - // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔  
40 - this._$_aVerticalIntervalTime = new Array(this._$_qCount);  
41 - var i;  
42 - for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {  
43 - this._$_aVerticalIntervalTime[i] = new Array(2);  
44 - }  
45 -  
46 - // 班型的相关变量  
47 - this._$_bx_isLb = false; // 是否连班  
48 - this._$_bx_isfb = false; // 是否分班  
49 - this._$_bx_isfb_5_2 = false; // 是否5休2分班  
50 - this._$_bx_desc; // 班型描述(默认为路牌编号)  
51 -  
52 - // 其他班次(进出场,例包,吃饭等),TODO:以后再拆  
53 - this._$_other_bc_array = [];  
54 -  
55 - // TODO:  
56 -  
57 -};  
58 -  
59 -//------------------- get/set 方法 -------------------//  
60 -  
61 -InternalLpObj.prototype.getOtherBcArray = function() {  
62 - return this._$_other_bc_array;  
63 -};  
64 -InternalLpObj.prototype.addOtherBcArray = function(ba) {  
65 - this._$_other_bc_array = this._$_other_bc_array.concat(ba);  
66 -};  
67 -  
68 -/**  
69 - * 获取圈  
70 - * @param qIndex 圈index  
71 - */  
72 -InternalLpObj.prototype.getGroup = function(qIndex) {  
73 - return this._$_groupBcArray[qIndex];  
74 -};  
75 -  
76 -/**  
77 - * 获取班次。  
78 - * @param qIndex 第几圈  
79 - * @param bcIndex 第几个班次  
80 - */  
81 -InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {  
82 - var group = this._$_groupBcArray[qIndex];  
83 - var bc;  
84 - if (bcIndex == 0) {  
85 - bc = group.getBc1();  
86 - } else if (bcIndex == 1) {  
87 - bc = group.getBc2();  
88 - }  
89 - return bc;  
90 -};  
91 -  
92 -/**  
93 - * 在具体位置设置班次。  
94 - * @param qIndex 第几圈  
95 - * @param bcIndex 第几个班次  
96 - * @param bc 班次对象  
97 - */  
98 -InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {  
99 - var group = this._$_groupBcArray[qIndex];  
100 - if (bcIndex == 0) {  
101 - group.setBc1(bc);  
102 - bc.setGroup(group);  
103 - } else if (bcIndex == 1) {  
104 - group.setBc2(bc);  
105 - bc.setGroup(group);  
106 - }  
107 -};  
108 -  
109 -/**  
110 - * 设置原始路牌对象。  
111 - * @param lpObj 原始路牌对象  
112 - */  
113 -InternalLpObj.prototype.setLp = function(lpObj) {  
114 - this._$$_orign_lp_obj = lpObj;  
115 - var i;  
116 - var group;  
117 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
118 - group = this._$_groupBcArray[i];  
119 - if (group) {  
120 - group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象  
121 - }  
122 - }  
123 -};  
124 -  
125 -InternalLpObj.prototype.getLpNo = function() {  
126 - return this._$$_orign_lp_obj.lpNo;  
127 -};  
128 -InternalLpObj.prototype.getLpName = function() {  
129 - return this._$$_orign_lp_obj.lpName;  
130 -};  
131 -InternalLpObj.prototype.setBxFb5_2 = function(fb) {  
132 - this._$_bx_isfb_5_2 = fb;  
133 -};  
134 -InternalLpObj.prototype.isBxFb5_2 = function() {  
135 - return this._$_bx_isfb_5_2;  
136 -};  
137 -InternalLpObj.prototype.setBxLb = function(lb) {  
138 - this._$_bx_isLb = lb;  
139 -};  
140 -InternalLpObj.prototype.isBxLb = function() {  
141 - return this._$_bx_isLb;  
142 -};  
143 -  
144 -InternalLpObj.prototype.setBxFb = function(fb) {  
145 - this._$_bx_isfb = fb;  
146 -};  
147 -InternalLpObj.prototype.isBxFb = function() {  
148 - return this._$_bx_isfb;  
149 -};  
150 -  
151 -/**  
152 - * 设置路牌的班型描述(最终是设置班次的路牌名字)。  
153 - * @param desc 描述  
154 - */  
155 -InternalLpObj.prototype.setBxDesc = function(desc) {  
156 - // 最终原始路牌的名字  
157 - this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;  
158 - // 内部对象的班型描述  
159 - this._$_bx_desc = desc;  
160 -};  
161 -/**  
162 - * 获取版型描述  
163 - * @returns string  
164 - */  
165 -InternalLpObj.prototype.getBxDesc = function() {  
166 - return this._$_bx_desc;  
167 -};  
168 -  
169 -/**  
170 - * 设置纵向最小发车间隔时间。  
171 - * @param v  
172 - */  
173 -InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {  
174 - // 第一个路牌,都为0  
175 - this._$_minVerticalIntervalTime = v;  
176 -};  
177 -/**  
178 - * 获取纵向最小发车间隔时间。  
179 - * @returns {number|*}  
180 - */  
181 -InternalLpObj.prototype.getVerticalMinIntervalTime = function() {  
182 - return this._$_minVerticalIntervalTime;  
183 -};  
184 -  
185 -/**  
186 - * 设置纵向发车间隔。  
187 - * @param iQindex 圈index  
188 - * @param iBindex 班次index  
189 - * @param iTime 间隔时间  
190 - */  
191 -InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {  
192 - this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;  
193 -};  
194 -  
195 -/**  
196 - * 返回纵向发车间隔。  
197 - * @param iQindex 圈index  
198 - * @param iBindex 班次index  
199 - */  
200 -InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {  
201 - return this._$_aVerticalIntervalTime[iQindex][iBindex];  
202 -};  
203 -  
204 -//-------------------- 班次操作方法(查询,统计,删除) -----------------------//  
205 -  
206 -/**  
207 - * 返回总共班次数。  
208 - */  
209 -InternalLpObj.prototype.getBcCount = function() {  
210 - var i;  
211 - var group;  
212 - var bccount = 0;  
213 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
214 - group = this._$_groupBcArray[i];  
215 - if (group) {  
216 - if (group.getBc1()) {  
217 - bccount += 1;  
218 - }  
219 - if (group.getBc2()) {  
220 - bccount += 1;  
221 - }  
222 - }  
223 - }  
224 -  
225 - return bccount;  
226 -};  
227 -  
228 -/**  
229 - * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。  
230 - * @returns arrays (InternalBcObj)  
231 - */  
232 -InternalLpObj.prototype.getBcArray = function() {  
233 - var bcArray = [];  
234 - var i;  
235 - var group;  
236 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
237 - group = this._$_groupBcArray[i];  
238 - if (group) {  
239 - group.getBc1() ? bcArray.push(group.getBc1()) : "";  
240 - group.getBc2() ? bcArray.push(group.getBc2()) : "";  
241 - }  
242 - }  
243 -  
244 - return bcArray;  
245 -};  
246 -  
247 -/**  
248 - * 获取最小(最早)班次对象。  
249 - * @returns [{圈index},{班次index}]  
250 - */  
251 -InternalLpObj.prototype.getMinBcObjPosition = function() {  
252 - var i;  
253 - var bIndex = [];  
254 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
255 - if (this._$_groupBcArray[i].getBc1()) {  
256 - bIndex.push(i);  
257 - bIndex.push(0);  
258 - break;  
259 - }  
260 - if (this._$_groupBcArray[i].getBc2()) {  
261 - bIndex.push(i);  
262 - bIndex.push(1);  
263 - break;  
264 - }  
265 - }  
266 - return bIndex;  
267 -};  
268 -  
269 -/**  
270 - * 获取最大(最晚)班次对象。  
271 - * @returns [{圈index},{班次index}]  
272 - */  
273 -InternalLpObj.prototype.getMaxBcObjPosition = function() {  
274 - var i;  
275 - var bIndex = [];  
276 - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {  
277 - if (this._$_groupBcArray[i].getBc2()) {  
278 - bIndex.push(i);  
279 - bIndex.push(1);  
280 - break;  
281 - }  
282 - if (this._$_groupBcArray[i].getBc1()) {  
283 - bIndex.push(i);  
284 - bIndex.push(0);  
285 - break;  
286 - }  
287 - }  
288 - return bIndex;  
289 -};  
290 -  
291 -InternalLpObj.prototype.getMinBcObj = function() {  
292 - var i;  
293 - var bcObj;  
294 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
295 - bcObj = this._$_groupBcArray[i].getBc1();  
296 - if (bcObj) {  
297 - break;  
298 - }  
299 - bcObj = this._$_groupBcArray[i].getBc2();  
300 - if (bcObj) {  
301 - break;  
302 - }  
303 - }  
304 - return bcObj;  
305 -};  
306 -InternalLpObj.prototype.getMaxBcObj = function() {  
307 - var i;  
308 - var bcObj;  
309 - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {  
310 - bcObj = this._$_groupBcArray[i].getBc2();  
311 - if (bcObj) {  
312 - break;  
313 - }  
314 - bcObj = this._$_groupBcArray[i].getBc1();  
315 - if (bcObj) {  
316 - break;  
317 - }  
318 - }  
319 - return bcObj;  
320 -};  
321 -  
322 -/**  
323 - * 获取车次链信息。  
324 - * @param num 第几个车次链  
325 - * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}  
326 - */  
327 -InternalLpObj.prototype.fnGetBcChainInfo = function(num) {  
328 - // 计算总的车次链信息  
329 - var aChainInfo = [];  
330 - var oChainInfo;  
331 - var aBcIndex = this.getMinBcObjPosition();  
332 - var oBc;  
333 - var iQIndex;  
334 - var iBcIndex;  
335 - var i;  
336 - var bFlag;  
337 -  
338 - var iBcount = 0;  
339 -  
340 - if (aBcIndex.length == 2) {  
341 - iBcount = 1;  
342 - oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};  
343 - aChainInfo.push(oChainInfo);  
344 - bFlag = true;  
345 -  
346 - // 下一个班次的索引  
347 - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;  
348 - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;  
349 -  
350 - for (i = iQIndex; i < this._$_qCount; i++) {  
351 - while (iBcIndex <= 1) {  
352 - oBc = this.getBc(i, iBcIndex);  
353 - if (!oBc) {  
354 - if (bFlag) {  
355 - // 车次链结尾是这个班次的前一个班次  
356 - oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;  
357 - oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;  
358 - oChainInfo.bcount = iBcount;  
359 - }  
360 -  
361 - bFlag = false;  
362 - } else {  
363 - if (bFlag) {  
364 - iBcount ++;  
365 - oChainInfo.bcount = iBcount;  
366 - } else {  
367 - // 下一个车次链开始  
368 - iBcount = 1;  
369 - oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};  
370 - aChainInfo.push(oChainInfo);  
371 - bFlag = true;  
372 - }  
373 - }  
374 -  
375 -  
376 - iBcIndex ++;  
377 - }  
378 - iBcIndex = 0;  
379 - }  
380 -  
381 - }  
382 -  
383 - return aChainInfo[num];  
384 -};  
385 -  
386 -/**  
387 - * 获取车次链的个数。  
388 - * @returns int  
389 - */  
390 -InternalLpObj.prototype.fnGetBcChainCount = function() {  
391 - var iChainCount = 0;  
392 - var aBcIndex = this.getMinBcObjPosition();  
393 -  
394 - var oBc;  
395 - var iQIndex;  
396 - var iBcIndex;  
397 - var i;  
398 - var bFlag;  
399 -  
400 - if (aBcIndex.length == 2) {  
401 - iChainCount = 1;  
402 - bFlag = true;  
403 -  
404 - // 下一个班次的索引  
405 - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;  
406 - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;  
407 -  
408 - for (i = iQIndex; i < this._$_qCount; i++) {  
409 - while (iBcIndex <= 1) {  
410 - oBc = this.getBc(i, iBcIndex);  
411 - if (!oBc) {  
412 - bFlag = false;  
413 - } else {  
414 - if (bFlag) {  
415 -  
416 - } else {  
417 - iChainCount ++;  
418 - bFlag = true;  
419 - }  
420 - }  
421 -  
422 -  
423 - iBcIndex ++;  
424 - }  
425 - iBcIndex = 0;  
426 - }  
427 -  
428 - }  
429 -  
430 -  
431 - return iChainCount;  
432 -};  
433 -  
434 -/**  
435 - * 在具体位置移除班次。  
436 - * @param qIndex 第几圈  
437 - * @param bcIndex 第几个班次  
438 - */  
439 -InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {  
440 - var group = this._$_groupBcArray[qIndex];  
441 - if (bcIndex == 0) {  
442 - group.removeBc1();  
443 - } else if (bcIndex == 1) {  
444 - group.removeBc2();  
445 - }  
446 -};  
447 -  
448 -/**  
449 - * 使用指定时间匹配返回离之最近的第几圈第几个班次,  
450 - * 使用时间差的绝度值,比较,取最小的  
451 - * 如果有两个一样的时间差,取比fctime大的时间  
452 - * @param fctime moment 比较用时间  
453 - * @param groupArray 圈数组  
454 - * @param hasUp boolean 计算上行班次  
455 - * @param hasDown boolean 计算下行班次  
456 - * @returns [{第几圈},{第几个班次}]  
457 - */  
458 -InternalLpObj.prototype.fnGetQBcIndexWithFcTimeFromGroupArray = function(  
459 - fctime, groupArray, hasUp, hasDown  
460 -) {  
461 - var i;  
462 - var timediff; // 时间差取绝对值  
463 - var qIndex;  
464 - var bcIndex;  
465 -  
466 - var group;  
467 - var bc1time;  
468 - var bc2time;  
469 -  
470 - var tempdiff;  
471 -  
472 - console.log("比较时间=" + fctime.format("HH:mm"));  
473 -  
474 - for (i = 0; i < this._$_qCount; i++) {  
475 - group = groupArray[i];  
476 - if (group) {  
477 - if (group.getBc1() && hasUp) {  
478 - bc1time = group.getBc1().getFcTimeObj();  
479 - console.log("bc1time=" + bc1time.format("HH:mm") + " tempdiff=" + tempdiff);  
480 - tempdiff = Math.abs(bc1time.diff(fctime));  
481 -  
482 - if (!timediff) {  
483 - timediff = Math.abs(tempdiff);  
484 - qIndex = i;  
485 - bcIndex = 0;  
486 - } else {  
487 - if (tempdiff < timediff) {  
488 - timediff = tempdiff;  
489 - qIndex = i;  
490 - bcIndex = 0;  
491 - } if (Math.abs(tempdiff) == timediff) {  
492 - if (bc1time.isAfter(fctime)) {  
493 - timediff = tempdiff;  
494 - qIndex = i;  
495 - bcIndex = 0;  
496 - }  
497 -  
498 - }  
499 - }  
500 - }  
501 -  
502 - if (group.getBc2() && hasDown) {  
503 - bc2time = group.getBc2().getFcTimeObj();  
504 - console.log("bc2time=" + bc2time.format("HH:mm") + " tempdiff=" + tempdiff);  
505 - tempdiff = Math.abs(bc2time.diff(fctime));  
506 -  
507 - if (!timediff) {  
508 - timediff = Math.abs(tempdiff);  
509 - qIndex = i;  
510 - bcIndex = 1;  
511 - } else {  
512 - if (tempdiff < timediff) {  
513 - timediff = tempdiff;  
514 - qIndex = i;  
515 - bcIndex = 1;  
516 - } if (Math.abs(tempdiff) == timediff) {  
517 - if (bc2time.isBefore(fctime)) {  
518 - timediff = tempdiff;  
519 - qIndex = i;  
520 - bcIndex = 1;  
521 - }  
522 -  
523 - }  
524 - }  
525 - }  
526 - }  
527 - }  
528 -  
529 - console.log("中标线对应数组索引=" + qIndex);  
530 -  
531 - var rst = [];  
532 - rst.push(qIndex);  
533 - rst.push(bcIndex);  
534 -  
535 - return rst;  
536 -};  
537 -  
538 -/**  
539 - * 使用指定时间匹配返回离之最近的第几圈第几个班次,  
540 - * 使用时间差的绝度值,比较,取最小的  
541 - * 如果有两个一样的时间差,取比fctime大的时间  
542 - * @param fctime moment 比较用时间  
543 - * @param hasUp boolean 计算上行班次  
544 - * @param hasDown boolean 计算下行班次  
545 - * @returns [{第几圈},{第几个班次}]  
546 - */  
547 -InternalLpObj.prototype.getQBcIndexWithFcTime = function(  
548 - fctime, hasUp, hasDown  
549 -) {  
550 - return this.fnGetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);  
551 -};  
552 -  
553 -//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//  
554 -  
555 -/**  
556 - * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌  
557 - * 注意,之前有班次会删除后再创建。  
558 - * @param startTime 开始时间  
559 - * @param endTime 结束时间  
560 - * @param isUp 第一个班次是上行还是下行  
561 - * @param fromQ 从第几圈开始加入  
562 - * @param paramObj 参数对象  
563 - * @param factory 工厂对象  
564 - */  
565 -InternalLpObj.prototype.initDataFromTimeToTime = function(  
566 - startTime,  
567 - endTime,  
568 - isUp,  
569 - fromQ,  
570 - paramObj,  
571 - factory) {  
572 -  
573 - var bcData = []; // 班次数组  
574 - var bcObj;  
575 - var kssj = startTime;  
576 - var fcno = 1; // 发车顺序号  
577 - var bcCount = 1; // 班次数  
578 - do {  
579 - bcObj = factory.createBcObj(  
580 - this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象  
581 - bcData.push(bcObj);  
582 -  
583 - kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());  
584 - fcno ++;  
585 - bcCount ++;  
586 - isUp = !isUp;  
587 - } while(kssj.isBefore(endTime));  
588 - bcCount--;  
589 -  
590 - //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));  
591 - //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));  
592 - //console.log("endtime: " + endTime.format("HH:mm"));  
593 -  
594 - //if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {  
595 - // // 如果最后一个班次的到达时间超过结束时间,也要去除  
596 - // bcData.splice(bcCount - 1, 1);  
597 - //}  
598 -  
599 - this._initDataFromLbBcArray(bcData, fromQ);  
600 -  
601 -};  
602 -  
603 -/**  
604 - * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。  
605 - * @param bcArray 连班班次数组  
606 - * @param fromQ 从第几圈开始加入  
607 - */  
608 -InternalLpObj.prototype._initDataFromLbBcArray = function(  
609 - bcArray,  
610 - fromQ  
611 -) {  
612 - var _bc1Obj;  
613 - var _bc2Obj;  
614 - var _qObj;  
615 -  
616 - // 第一班次是上行还是下行  
617 - var isUp = bcArray[0].isUp();  
618 -  
619 - if (bcArray.length > 0 && fromQ < this._$_qCount) {  
620 - // 构造圈数  
621 - if (isUp != this._$_isUp) {  
622 - // 如果方向不一致,意味着第一个班次是半圈  
623 - // 加半圈,并加在bc2上  
624 - _bc2Obj = bcArray.slice(0, 1)[0];  
625 - _qObj = new InternalGroupObj(  
626 - this,  
627 - this._$_isUp,  
628 - undefined,  
629 - _bc2Obj  
630 - );  
631 - _bc2Obj.setGroup(_qObj);  
632 - this._$_groupBcArray[fromQ] = _qObj;  
633 -  
634 - bcArray.splice(0, 1);  
635 - fromQ ++;  
636 - }  
637 -  
638 - var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈  
639 - var qCount2 = bcArray.length % 2; // 最后是否有半圈  
640 -  
641 - while (fromQ < this._$_qCount) {  
642 - if (qCount1 > 0) {  
643 - _bc1Obj = bcArray.slice(0, 1)[0];  
644 - _bc2Obj = bcArray.slice(1, 2)[0];  
645 - _qObj = new InternalGroupObj(  
646 - this,  
647 - this._$_isUp,  
648 - _bc1Obj,  
649 - _bc2Obj  
650 - );  
651 - _bc1Obj.setGroup(_qObj);  
652 - _bc2Obj.setGroup(_qObj);  
653 - this._$_groupBcArray[fromQ] = _qObj;  
654 -  
655 - bcArray.splice(0, 2);  
656 - qCount1 --;  
657 - } else if (qCount2 > 0) {  
658 - // 加半圈,并加在bc1上  
659 - _bc1Obj = bcArray.slice(0, 1)[0];  
660 - _qObj = new InternalGroupObj(  
661 - this,  
662 - this._$_isUp,  
663 - _bc1Obj,  
664 - undefined  
665 - );  
666 - _bc1Obj.setGroup(_qObj);  
667 - this._$_groupBcArray[fromQ] = _qObj;  
668 -  
669 - bcArray.splice(0, 1);  
670 - qCount2 --;  
671 - } else {  
672 - break;  
673 - }  
674 -  
675 - fromQ ++;  
676 - }  
677 - }  
678 -};  
679 -  
680 -//-------------------------- 其他方法 ----------------------------//  
681 -  
682 -/**  
683 - * 从指定位置的班次开始,往后所有的班次修正发车时间  
684 - * @param groupIndex  
685 - * @param bcIndex  
686 - * @param time  
687 - */  
688 -InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {  
689 - var i;  
690 - var oCurBc;  
691 -  
692 - // 修正之前班次的停站时间  
693 - //oCurBc = this.getBc(  
694 - // bcIndex == 0 ? groupIndex - 1 : groupIndex,  
695 - // bcIndex == 1 ? 0 : 1  
696 - //);  
697 - //if (oCurBc) {  
698 - // oCurBc.setStopTime(oCurBc.getStopTime() + time);  
699 - //}  
700 -  
701 -  
702 - for (i = groupIndex; i < this._$_qCount; i++) {  
703 - if (bcIndex == 0) {  
704 - oCurBc = this.getBc(i, 0);  
705 - if (oCurBc) {  
706 - oCurBc.addMinuteToFcsj(time);  
707 - }  
708 - oCurBc = this.getBc(i, 1);  
709 - if (oCurBc) {  
710 - oCurBc.addMinuteToFcsj(time);  
711 - }  
712 -  
713 - } else {  
714 - oCurBc = this.getBc(i, 1);  
715 - if (oCurBc) {  
716 - oCurBc.addMinuteToFcsj(time);  
717 - }  
718 -  
719 - }  
720 -  
721 - bcIndex = 0;  
722 - }  
723 -};  
724 -  
725 -/**  
726 - * 在指定位置添加一个吃饭班次。  
727 - * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array  
728 - * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化  
729 - * @param groupIndex  
730 - * @param bcIndex  
731 - * @param factory  
732 - * @param paramObj  
733 - * @returns int 相差时间(吃饭时间距离和停站时间相差值)  
734 - */  
735 -InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {  
736 - var oPreBc;  
737 - var oEatBc;  
738 - var iBcModifyTime;  
739 - oPreBc = this.getBc( // 前一个邻接班次  
740 - bcIndex == 0 ? groupIndex - 1 : groupIndex,  
741 - bcIndex == 1 ? 0 : 1);  
742 - if (oPreBc) { // 存在前一个班次  
743 - oEatBc = factory.createBcObj(  
744 - this,  
745 - "cf",  
746 - !oPreBc.isUp(), // 和上一个班次方向相反  
747 - 1,  
748 - paramObj.addMinute(oPreBc.getArrTimeObj(), oPreBc.getStopTime()), // 使用上一个班次的到达时间作为开始时间  
749 - paramObj  
750 - );  
751 -  
752 - //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间  
753 -  
754 - // 修正之后的班次发车时间  
755 - // 注意:之后那个班次发车时间就是吃饭班次的到达时间  
756 - iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");  
757 - this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);  
758 -  
759 - oPreBc.setStopTime(0); // 不重置停站时间  
760 - oPreBc.fnSetEatTime(oEatBc.getBcTime());  
761 -  
762 - //this._$_other_bc_array.push(oEatBc);  
763 -  
764 - return iBcModifyTime;  
765 - } else {  
766 - return false;  
767 - }  
768 -  
769 -};  
770 -  
771 -/**  
772 - * 调整路牌的班次,通过调整停站时间,或者班次发车时间,不能让班次的到达时间和下一个班次的发车时间重叠。  
773 - * @param iPeakAverStopTime 高峰平均停站时间  
774 - * @param iTroughAverStopTime 低谷平均停站时间  
775 - * @param oParam 参数对象  
776 - */  
777 -InternalLpObj.prototype.fnAdjustBcInterval = function(iPeakAverStopTime, iTroughAverStopTime, oParam) {  
778 - // 获取车次链个数  
779 - var iBcChainCount = this.fnGetBcChainCount();  
780 -  
781 - var i;  
782 - var j;  
783 - var oBcIndex;  
784 - var iQIndex;  
785 - var iBcIndex;  
786 - var iBcCount;  
787 - var oBc;  
788 - var oNextBc;  
789 -  
790 - var iBcStopTime;  
791 -  
792 - for (i = 0; i < iBcChainCount; i++) {  
793 - oBcIndex = this.fnGetBcChainInfo(i);  
794 - iQIndex = oBcIndex["s_q"];  
795 - iBcIndex = oBcIndex["s_b"];  
796 - iBcCount = oBcIndex["bcount"];  
797 -  
798 - for (j = 0; j < iBcCount - 1; j++) {  
799 - oBc = this.getBc(iQIndex, iBcIndex);  
800 - oNextBc = this.getBc(  
801 - iBcIndex == 0 ? iQIndex : iQIndex + 1,  
802 - iBcIndex == 0 ? 1 : 0);  
803 -  
804 - if (oNextBc.fnIsFirstBc()) { // 如果同一路牌连续2个方向首站班次,都不做处理  
805 - continue;  
806 - }  
807 -  
808 - // 不改变当前班次的行驶时间,修正停站时间和下一个班次的发车时间  
809 - iBcStopTime = oNextBc.getFcTimeObj().diff(oBc.getArrTimeObj(), "m");  
810 - if (iBcStopTime < 0) {  
811 - // 当前班次使用最小停站时间  
812 - oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));  
813 - oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);  
814 -  
815 - } else {  
816 - if (iBcStopTime == oBc.getStopTime() + oBc.fnGetEatTime()) {  
817 - // 停站时间一致,没有问题  
818 -  
819 -  
820 - } else {  
821 - // TODO:当前班次使用最小停站时间  
822 - oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));  
823 - oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);  
824 -  
825 - }  
826 - }  
827 -  
828 - iBcIndex = iBcIndex == 0 ? 1 : 0;  
829 - iQIndex = iBcIndex == 0 ? iQIndex + 1 : iQIndex;  
830 - }  
831 -  
832 - this.getBc(iQIndex, iBcIndex).setStopTime(0);  
833 - }  
834 -  
835 -  
836 -};  
837 -  
838 -  
839 -// TODO  
840 -  
841 -/**  
842 - *  
843 - *  
844 - */  
845 -InternalLpObj.prototype.calcuLpBx = function() {  
846 -  
847 -};  
848 -  
849 -  
850 -  
851 -  
852 -  
853 -  
854 - 1 +/**
  2 + * 内部路牌对象。
  3 + * @constructor
  4 + */
  5 +var InternalLpObj = function(
  6 + orilpObj, // 原始路牌对象
  7 + qCount, // 总共多少圈
  8 + isUp // 圈是以上行开始还是下行开始
  9 +) {
  10 + // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)
  11 + this._$$_orign_lp_obj = orilpObj;
  12 +
  13 + this._$_isUp = isUp;
  14 +
  15 + // 路牌的圈数,注意每个路牌的圈数都是一致的,
  16 + // 但并不是每一圈都有值
  17 + // 第1圈从上标线开始
  18 + // 第0圈表示中标线的第一个班次组成的半圈
  19 + // 有多少圈根据最终迭代的结果来看
  20 + this._$_qCount = qCount;
  21 + // 保存的是 InternalGroupBcObj 对象
  22 + this._$_groupBcArray = new Array(qCount);
  23 +
  24 + var i;
  25 + for (i = 0; i < this._$_qCount; i++) {
  26 + this._$_groupBcArray[i] = new InternalGroupObj(
  27 + this, this._$_isUp, undefined, undefined);
  28 + }
  29 +
  30 + // 距离上一个路牌的最小发车间隔时间
  31 + // 用于纵向添加班次的时候使用
  32 + // 默认第一个路牌为0
  33 + this._$_minVerticalIntervalTime = 0;
  34 +
  35 + // 详细记录每圈每个方向上的发车间隔时间
  36 + // 第一维度表示圈数,第二维度表示第一个方向,第二个方向
  37 + // 第一个方向是否上行由 _$_isUp 决定
  38 + // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔
  39 + // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔
  40 + this._$_aVerticalIntervalTime = new Array(this._$_qCount);
  41 + for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {
  42 + this._$_aVerticalIntervalTime[i] = new Array(2);
  43 + }
  44 +
  45 + // 班型的相关变量
  46 + this._$_bx_isLb = false; // 是否连班
  47 + this._$_bx_isfb = false; // 是否分班
  48 + this._$_bx_isfb_5_2 = false; // 是否5休2分班
  49 + this._$_bx_desc; // 班型描述(默认为路牌编号)
  50 +
  51 + // 其他班次(进出场,例包,吃饭等),TODO:以后再拆
  52 + this._$_other_bc_array = [];
  53 +
  54 + // TODO:
  55 +
  56 +};
  57 +
  58 +//------------------- get/set 方法 -------------------//
  59 +
  60 +InternalLpObj.prototype.getOtherBcArray = function() {
  61 + return this._$_other_bc_array;
  62 +};
  63 +InternalLpObj.prototype.addOtherBcArray = function(ba) {
  64 + this._$_other_bc_array = this._$_other_bc_array.concat(ba);
  65 +};
  66 +
  67 +/**
  68 + * 获取圈
  69 + * @param qIndex 圈index
  70 + */
  71 +InternalLpObj.prototype.getGroup = function(qIndex) {
  72 + return this._$_groupBcArray[qIndex];
  73 +};
  74 +
  75 +/**
  76 + * 获取路牌圈数。
  77 + * @returns {*}
  78 + */
  79 +InternalLpObj.prototype.fnGetGroupCount = function() {
  80 + return this._$_qCount;
  81 +};
  82 +
  83 +/**
  84 + * 是否上行。
  85 + * @returns boolean
  86 + */
  87 +InternalLpObj.prototype.isUp = function() {
  88 + return this._$_isUp;
  89 +};
  90 +
  91 +/**
  92 + * 获取班次。
  93 + * @param qIndex 第几圈
  94 + * @param bcIndex 第几个班次
  95 + */
  96 +InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {
  97 + var group = this._$_groupBcArray[qIndex];
  98 + var bc;
  99 + if (bcIndex == 0) {
  100 + bc = group.getBc1();
  101 + } else if (bcIndex == 1) {
  102 + bc = group.getBc2();
  103 + }
  104 + return bc;
  105 +};
  106 +
  107 +/**
  108 + * 在具体位置设置班次。
  109 + * @param qIndex 第几圈
  110 + * @param bcIndex 第几个班次
  111 + * @param bc 班次对象
  112 + */
  113 +InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {
  114 + var group = this._$_groupBcArray[qIndex];
  115 + if (bcIndex == 0) {
  116 + group.setBc1(bc);
  117 + bc.setGroup(group);
  118 + } else if (bcIndex == 1) {
  119 + group.setBc2(bc);
  120 + bc.setGroup(group);
  121 + }
  122 +};
  123 +
  124 +/**
  125 + * 设置原始路牌对象。
  126 + * @param lpObj 原始路牌对象
  127 + */
  128 +InternalLpObj.prototype.setLp = function(lpObj) {
  129 + this._$$_orign_lp_obj = lpObj;
  130 + var i;
  131 + var group;
  132 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  133 + group = this._$_groupBcArray[i];
  134 + if (group) {
  135 + group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象
  136 + }
  137 + }
  138 +};
  139 +
  140 +InternalLpObj.prototype.getLpNo = function() {
  141 + return this._$$_orign_lp_obj.lpNo;
  142 +};
  143 +InternalLpObj.prototype.getLpName = function() {
  144 + return this._$$_orign_lp_obj.lpName;
  145 +};
  146 +InternalLpObj.prototype.setBxFb5_2 = function(fb) {
  147 + this._$_bx_isfb_5_2 = fb;
  148 +};
  149 +InternalLpObj.prototype.isBxFb5_2 = function() {
  150 + return this._$_bx_isfb_5_2;
  151 +};
  152 +InternalLpObj.prototype.setBxLb = function(lb) {
  153 + this._$_bx_isLb = lb;
  154 +};
  155 +InternalLpObj.prototype.isBxLb = function() {
  156 + return this._$_bx_isLb;
  157 +};
  158 +
  159 +InternalLpObj.prototype.setBxFb = function(fb) {
  160 + this._$_bx_isfb = fb;
  161 +};
  162 +InternalLpObj.prototype.isBxFb = function() {
  163 + return this._$_bx_isfb;
  164 +};
  165 +
  166 +/**
  167 + * 设置路牌的班型描述(最终是设置班次的路牌名字)。
  168 + * @param desc 描述
  169 + */
  170 +InternalLpObj.prototype.setBxDesc = function(desc) {
  171 + // 最终原始路牌的名字
  172 + this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;
  173 + // 内部对象的班型描述
  174 + this._$_bx_desc = desc;
  175 +};
  176 +/**
  177 + * 获取版型描述
  178 + * @returns string
  179 + */
  180 +InternalLpObj.prototype.getBxDesc = function() {
  181 + return this._$_bx_desc;
  182 +};
  183 +
  184 +/**
  185 + * 设置纵向最小发车间隔时间。
  186 + * @param v
  187 + */
  188 +InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {
  189 + // 第一个路牌,都为0
  190 + this._$_minVerticalIntervalTime = v;
  191 +};
  192 +/**
  193 + * 获取纵向最小发车间隔时间。
  194 + * @returns {number|*}
  195 + */
  196 +InternalLpObj.prototype.getVerticalMinIntervalTime = function() {
  197 + return this._$_minVerticalIntervalTime;
  198 +};
  199 +
  200 +/**
  201 + * 设置纵向发车间隔。
  202 + * @param iQindex 圈index
  203 + * @param iBindex 班次index
  204 + * @param iTime 间隔时间
  205 + */
  206 +InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {
  207 + this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;
  208 +};
  209 +
  210 +/**
  211 + * 返回纵向发车间隔。
  212 + * @param iQindex 圈index
  213 + * @param iBindex 班次index
  214 + */
  215 +InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {
  216 + return this._$_aVerticalIntervalTime[iQindex][iBindex];
  217 +};
  218 +
  219 +//-------------------- 班次操作方法(查询,统计,删除) -----------------------//
  220 +
  221 +/**
  222 + * 返回总共班次数。
  223 + */
  224 +InternalLpObj.prototype.getBcCount = function() {
  225 + var i;
  226 + var group;
  227 + var bccount = 0;
  228 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  229 + group = this._$_groupBcArray[i];
  230 + if (group) {
  231 + if (group.getBc1()) {
  232 + bccount += 1;
  233 + }
  234 + if (group.getBc2()) {
  235 + bccount += 1;
  236 + }
  237 + }
  238 + }
  239 +
  240 + return bccount;
  241 +};
  242 +
  243 +/**
  244 + * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。
  245 + * @returns arrays (InternalBcObj)
  246 + */
  247 +InternalLpObj.prototype.getBcArray = function() {
  248 + var bcArray = [];
  249 + var i;
  250 + var group;
  251 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  252 + group = this._$_groupBcArray[i];
  253 + if (group) {
  254 + group.getBc1() ? bcArray.push(group.getBc1()) : "";
  255 + group.getBc2() ? bcArray.push(group.getBc2()) : "";
  256 + }
  257 + }
  258 +
  259 + return bcArray;
  260 +};
  261 +
  262 +/**
  263 + * 获取最小(最早)班次对象。
  264 + * @returns [{圈index},{班次index}]
  265 + */
  266 +InternalLpObj.prototype.getMinBcObjPosition = function() {
  267 + var i;
  268 + var bIndex = [];
  269 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  270 + if (this._$_groupBcArray[i].getBc1()) {
  271 + bIndex.push(i);
  272 + bIndex.push(0);
  273 + break;
  274 + }
  275 + if (this._$_groupBcArray[i].getBc2()) {
  276 + bIndex.push(i);
  277 + bIndex.push(1);
  278 + break;
  279 + }
  280 + }
  281 + return bIndex;
  282 +};
  283 +
  284 +/**
  285 + * 获取最大(最晚)班次对象。
  286 + * @returns [{圈index},{班次index}]
  287 + */
  288 +InternalLpObj.prototype.getMaxBcObjPosition = function() {
  289 + var i;
  290 + var bIndex = [];
  291 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  292 + if (this._$_groupBcArray[i].getBc2()) {
  293 + bIndex.push(i);
  294 + bIndex.push(1);
  295 + break;
  296 + }
  297 + if (this._$_groupBcArray[i].getBc1()) {
  298 + bIndex.push(i);
  299 + bIndex.push(0);
  300 + break;
  301 + }
  302 + }
  303 + return bIndex;
  304 +};
  305 +
  306 +InternalLpObj.prototype.getMinBcObj = function() {
  307 + var i;
  308 + var bcObj;
  309 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  310 + bcObj = this._$_groupBcArray[i].getBc1();
  311 + if (bcObj) {
  312 + break;
  313 + }
  314 + bcObj = this._$_groupBcArray[i].getBc2();
  315 + if (bcObj) {
  316 + break;
  317 + }
  318 + }
  319 + return bcObj;
  320 +};
  321 +InternalLpObj.prototype.getMaxBcObj = function() {
  322 + var i;
  323 + var bcObj;
  324 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  325 + bcObj = this._$_groupBcArray[i].getBc2();
  326 + if (bcObj) {
  327 + break;
  328 + }
  329 + bcObj = this._$_groupBcArray[i].getBc1();
  330 + if (bcObj) {
  331 + break;
  332 + }
  333 + }
  334 + return bcObj;
  335 +};
  336 +
  337 +/**
  338 + * 获取车次链信息。
  339 + * @param num 第几个车次链
  340 + * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}
  341 + */
  342 +InternalLpObj.prototype.fnGetBcChainInfo = function(num) {
  343 + // 计算总的车次链信息
  344 + var aChainInfo = [];
  345 + var oChainInfo;
  346 + var aBcIndex = this.getMinBcObjPosition();
  347 + var oBc;
  348 + var iQIndex;
  349 + var iBcIndex;
  350 + var i;
  351 + var bFlag;
  352 +
  353 + var iBcount = 0;
  354 +
  355 + if (aBcIndex.length == 2) {
  356 + iBcount = 1;
  357 + oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};
  358 + aChainInfo.push(oChainInfo);
  359 + bFlag = true;
  360 +
  361 + // 下一个班次的索引
  362 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  363 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  364 +
  365 + for (i = iQIndex; i < this._$_qCount; i++) {
  366 + while (iBcIndex <= 1) {
  367 + oBc = this.getBc(i, iBcIndex);
  368 + if (!oBc) {
  369 + if (bFlag) {
  370 + // 车次链结尾是这个班次的前一个班次
  371 + oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;
  372 + oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;
  373 + oChainInfo.bcount = iBcount;
  374 + }
  375 +
  376 + bFlag = false;
  377 + } else {
  378 + if (bFlag) {
  379 + iBcount ++;
  380 + oChainInfo.bcount = iBcount;
  381 + } else {
  382 + // 下一个车次链开始
  383 + iBcount = 1;
  384 + oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};
  385 + aChainInfo.push(oChainInfo);
  386 + bFlag = true;
  387 + }
  388 + }
  389 +
  390 +
  391 + iBcIndex ++;
  392 + }
  393 + iBcIndex = 0;
  394 + }
  395 +
  396 + }
  397 +
  398 + return aChainInfo[num];
  399 +};
  400 +
  401 +/**
  402 + * 获取车次链的个数。
  403 + * @returns int
  404 + */
  405 +InternalLpObj.prototype.fnGetBcChainCount = function() {
  406 + var iChainCount = 0;
  407 + var aBcIndex = this.getMinBcObjPosition();
  408 +
  409 + var oBc;
  410 + var iQIndex;
  411 + var iBcIndex;
  412 + var i;
  413 + var bFlag;
  414 +
  415 + if (aBcIndex.length == 2) {
  416 + iChainCount = 1;
  417 + bFlag = true;
  418 +
  419 + // 下一个班次的索引
  420 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  421 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  422 +
  423 + for (i = iQIndex; i < this._$_qCount; i++) {
  424 + while (iBcIndex <= 1) {
  425 + oBc = this.getBc(i, iBcIndex);
  426 + if (!oBc) {
  427 + bFlag = false;
  428 + } else {
  429 + if (bFlag) {
  430 +
  431 + } else {
  432 + iChainCount ++;
  433 + bFlag = true;
  434 + }
  435 + }
  436 +
  437 +
  438 + iBcIndex ++;
  439 + }
  440 + iBcIndex = 0;
  441 + }
  442 +
  443 + }
  444 +
  445 +
  446 + return iChainCount;
  447 +};
  448 +
  449 +/**
  450 + * 在具体位置移除班次。
  451 + * @param qIndex 第几圈
  452 + * @param bcIndex 第几个班次
  453 + */
  454 +InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {
  455 + var group = this._$_groupBcArray[qIndex];
  456 + if (bcIndex == 0) {
  457 + group.removeBc1();
  458 + } else if (bcIndex == 1) {
  459 + group.removeBc2();
  460 + }
  461 +};
  462 +
  463 +/**
  464 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  465 + * 使用时间差的绝度值,比较,取最小的
  466 + * 如果有两个一样的时间差,取比fctime大的时间
  467 + * @param fctime moment 比较用时间
  468 + * @param groupArray 圈数组
  469 + * @param hasUp boolean 计算上行班次
  470 + * @param hasDown boolean 计算下行班次
  471 + * @returns [{第几圈},{第几个班次}]
  472 + */
  473 +InternalLpObj.prototype.fnGetQBcIndexWithFcTimeFromGroupArray = function(
  474 + fctime, groupArray, hasUp, hasDown
  475 +) {
  476 + var i;
  477 + var timediff; // 时间差取绝对值
  478 + var qIndex;
  479 + var bcIndex;
  480 +
  481 + var group;
  482 + var bc1time;
  483 + var bc2time;
  484 +
  485 + var tempdiff;
  486 +
  487 + console.log("比较时间=" + fctime.format("HH:mm"));
  488 +
  489 + for (i = 0; i < this._$_qCount; i++) {
  490 + group = groupArray[i];
  491 + if (group) {
  492 + if (group.getBc1() && hasUp) {
  493 + bc1time = group.getBc1().getFcTimeObj();
  494 + console.log("bc1time=" + bc1time.format("HH:mm") + " tempdiff=" + tempdiff);
  495 + tempdiff = Math.abs(bc1time.diff(fctime));
  496 +
  497 + if (!timediff) {
  498 + timediff = Math.abs(tempdiff);
  499 + qIndex = i;
  500 + bcIndex = 0;
  501 + } else {
  502 + if (tempdiff < timediff) {
  503 + timediff = tempdiff;
  504 + qIndex = i;
  505 + bcIndex = 0;
  506 + } if (Math.abs(tempdiff) == timediff) {
  507 + if (bc1time.isAfter(fctime)) {
  508 + timediff = tempdiff;
  509 + qIndex = i;
  510 + bcIndex = 0;
  511 + }
  512 +
  513 + }
  514 + }
  515 + }
  516 +
  517 + if (group.getBc2() && hasDown) {
  518 + bc2time = group.getBc2().getFcTimeObj();
  519 + console.log("bc2time=" + bc2time.format("HH:mm") + " tempdiff=" + tempdiff);
  520 + tempdiff = Math.abs(bc2time.diff(fctime));
  521 +
  522 + if (!timediff) {
  523 + timediff = Math.abs(tempdiff);
  524 + qIndex = i;
  525 + bcIndex = 1;
  526 + } else {
  527 + if (tempdiff < timediff) {
  528 + timediff = tempdiff;
  529 + qIndex = i;
  530 + bcIndex = 1;
  531 + } if (Math.abs(tempdiff) == timediff) {
  532 + if (bc2time.isBefore(fctime)) {
  533 + timediff = tempdiff;
  534 + qIndex = i;
  535 + bcIndex = 1;
  536 + }
  537 +
  538 + }
  539 + }
  540 + }
  541 + }
  542 + }
  543 +
  544 + console.log("中标线对应数组索引=" + qIndex);
  545 +
  546 + var rst = [];
  547 + rst.push(qIndex);
  548 + rst.push(bcIndex);
  549 +
  550 + return rst;
  551 +};
  552 +
  553 +/**
  554 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  555 + * 使用时间差的绝度值,比较,取最小的
  556 + * 如果有两个一样的时间差,取比fctime大的时间
  557 + * @param fctime moment 比较用时间
  558 + * @param hasUp boolean 计算上行班次
  559 + * @param hasDown boolean 计算下行班次
  560 + * @returns [{第几圈},{第几个班次}]
  561 + */
  562 +InternalLpObj.prototype.getQBcIndexWithFcTime = function(
  563 + fctime, hasUp, hasDown
  564 +) {
  565 + return this.fnGetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);
  566 +};
  567 +
  568 +//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//
  569 +
  570 +/**
  571 + * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌
  572 + * 注意,之前有班次会删除后再创建。
  573 + * @param startTime 开始时间
  574 + * @param endTime 结束时间
  575 + * @param isUp 第一个班次是上行还是下行
  576 + * @param fromQ 从第几圈开始加入
  577 + * @param paramObj 参数对象
  578 + * @param factory 工厂对象
  579 + */
  580 +InternalLpObj.prototype.initDataFromTimeToTime = function(
  581 + startTime,
  582 + endTime,
  583 + isUp,
  584 + fromQ,
  585 + paramObj,
  586 + factory) {
  587 +
  588 + var bcData = []; // 班次数组
  589 + var bcObj;
  590 + var kssj = startTime;
  591 + var fcno = 1; // 发车顺序号
  592 + var bcCount = 1; // 班次数
  593 + do {
  594 + bcObj = factory.createBcObj(
  595 + this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象
  596 + bcData.push(bcObj);
  597 +
  598 + kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());
  599 + fcno ++;
  600 + bcCount ++;
  601 + isUp = !isUp;
  602 + } while(kssj.isBefore(endTime));
  603 + bcCount--;
  604 +
  605 + //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));
  606 + //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));
  607 + //console.log("endtime: " + endTime.format("HH:mm"));
  608 +
  609 + //if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {
  610 + // // 如果最后一个班次的到达时间超过结束时间,也要去除
  611 + // bcData.splice(bcCount - 1, 1);
  612 + //}
  613 +
  614 + this._initDataFromLbBcArray(bcData, fromQ);
  615 +
  616 +};
  617 +
  618 +/**
  619 + * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。
  620 + * @param bcArray 连班班次数组
  621 + * @param fromQ 从第几圈开始加入
  622 + */
  623 +InternalLpObj.prototype._initDataFromLbBcArray = function(
  624 + bcArray,
  625 + fromQ
  626 +) {
  627 + var _bc1Obj;
  628 + var _bc2Obj;
  629 + var _qObj;
  630 +
  631 + // 第一班次是上行还是下行
  632 + var isUp = bcArray[0].isUp();
  633 +
  634 + if (bcArray.length > 0 && fromQ < this._$_qCount) {
  635 + // 构造圈数
  636 + if (isUp != this._$_isUp) {
  637 + // 如果方向不一致,意味着第一个班次是半圈
  638 + // 加半圈,并加在bc2上
  639 + _bc2Obj = bcArray.slice(0, 1)[0];
  640 + _qObj = new InternalGroupObj(
  641 + this,
  642 + this._$_isUp,
  643 + undefined,
  644 + _bc2Obj
  645 + );
  646 + _bc2Obj.setGroup(_qObj);
  647 + this._$_groupBcArray[fromQ] = _qObj;
  648 +
  649 + bcArray.splice(0, 1);
  650 + fromQ ++;
  651 + }
  652 +
  653 + var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈
  654 + var qCount2 = bcArray.length % 2; // 最后是否有半圈
  655 +
  656 + while (fromQ < this._$_qCount) {
  657 + if (qCount1 > 0) {
  658 + _bc1Obj = bcArray.slice(0, 1)[0];
  659 + _bc2Obj = bcArray.slice(1, 2)[0];
  660 + _qObj = new InternalGroupObj(
  661 + this,
  662 + this._$_isUp,
  663 + _bc1Obj,
  664 + _bc2Obj
  665 + );
  666 + _bc1Obj.setGroup(_qObj);
  667 + _bc2Obj.setGroup(_qObj);
  668 + this._$_groupBcArray[fromQ] = _qObj;
  669 +
  670 + bcArray.splice(0, 2);
  671 + qCount1 --;
  672 + } else if (qCount2 > 0) {
  673 + // 加半圈,并加在bc1上
  674 + _bc1Obj = bcArray.slice(0, 1)[0];
  675 + _qObj = new InternalGroupObj(
  676 + this,
  677 + this._$_isUp,
  678 + _bc1Obj,
  679 + undefined
  680 + );
  681 + _bc1Obj.setGroup(_qObj);
  682 + this._$_groupBcArray[fromQ] = _qObj;
  683 +
  684 + bcArray.splice(0, 1);
  685 + qCount2 --;
  686 + } else {
  687 + break;
  688 + }
  689 +
  690 + fromQ ++;
  691 + }
  692 + }
  693 +};
  694 +
  695 +//-------------------------- 其他方法 ----------------------------//
  696 +
  697 +/**
  698 + * 从指定位置的班次开始,往后所有的班次修正发车时间
  699 + * @param groupIndex
  700 + * @param bcIndex
  701 + * @param time
  702 + */
  703 +InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {
  704 + var i;
  705 + var oCurBc;
  706 +
  707 + // 修正之前班次的停站时间
  708 + //oCurBc = this.getBc(
  709 + // bcIndex == 0 ? groupIndex - 1 : groupIndex,
  710 + // bcIndex == 1 ? 0 : 1
  711 + //);
  712 + //if (oCurBc) {
  713 + // oCurBc.setStopTime(oCurBc.getStopTime() + time);
  714 + //}
  715 +
  716 +
  717 + for (i = groupIndex; i < this._$_qCount; i++) {
  718 + if (bcIndex == 0) {
  719 + oCurBc = this.getBc(i, 0);
  720 + if (oCurBc) {
  721 + oCurBc.addMinuteToFcsj(time);
  722 + }
  723 + oCurBc = this.getBc(i, 1);
  724 + if (oCurBc) {
  725 + oCurBc.addMinuteToFcsj(time);
  726 + }
  727 +
  728 + } else {
  729 + oCurBc = this.getBc(i, 1);
  730 + if (oCurBc) {
  731 + oCurBc.addMinuteToFcsj(time);
  732 + }
  733 +
  734 + }
  735 +
  736 + bcIndex = 0;
  737 + }
  738 +};
  739 +
  740 +/**
  741 + * 在指定位置添加一个吃饭班次。
  742 + * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array
  743 + * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化
  744 + * @param groupIndex
  745 + * @param bcIndex
  746 + * @param factory
  747 + * @param paramObj
  748 + * @returns int 相差时间(吃饭时间距离和停站时间相差值)
  749 + */
  750 +InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {
  751 + var oPreBc;
  752 + var oEatBc;
  753 + var iBcModifyTime;
  754 + oPreBc = this.getBc( // 前一个邻接班次
  755 + bcIndex == 0 ? groupIndex - 1 : groupIndex,
  756 + bcIndex == 1 ? 0 : 1);
  757 + if (oPreBc) { // 存在前一个班次
  758 + oEatBc = factory.createBcObj(
  759 + this,
  760 + "cf",
  761 + !oPreBc.isUp(), // 和上一个班次方向相反
  762 + 1,
  763 + paramObj.addMinute(oPreBc.getArrTimeObj(), oPreBc.getStopTime()), // 使用上一个班次的到达时间作为开始时间
  764 + paramObj
  765 + );
  766 +
  767 + //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间
  768 +
  769 + // 修正之后的班次发车时间
  770 + // 注意:之后那个班次发车时间就是吃饭班次的到达时间
  771 + iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");
  772 + this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);
  773 +
  774 + oPreBc.setStopTime(0); // 不重置停站时间
  775 + oPreBc.fnSetEatTime(oEatBc.getBcTime());
  776 +
  777 + //this._$_other_bc_array.push(oEatBc);
  778 +
  779 + return iBcModifyTime;
  780 + } else {
  781 + return false;
  782 + }
  783 +
  784 +};
  785 +
  786 +/**
  787 + * 调整路牌的班次,通过调整停站时间,或者班次发车时间,不能让班次的到达时间和下一个班次的发车时间重叠。
  788 + * @param iPeakAverStopTime 高峰平均停站时间
  789 + * @param iTroughAverStopTime 低谷平均停站时间
  790 + * @param oParam 参数对象
  791 + */
  792 +InternalLpObj.prototype.fnAdjustBcInterval = function(iPeakAverStopTime, iTroughAverStopTime, oParam) {
  793 + // 获取车次链个数
  794 + var iBcChainCount = this.fnGetBcChainCount();
  795 +
  796 + var i;
  797 + var j;
  798 + var oBcIndex;
  799 + var iQIndex;
  800 + var iBcIndex;
  801 + var iBcCount;
  802 + var oBc;
  803 + var oNextBc;
  804 +
  805 + var iBcStopTime;
  806 +
  807 + for (i = 0; i < iBcChainCount; i++) {
  808 + oBcIndex = this.fnGetBcChainInfo(i);
  809 + iQIndex = oBcIndex["s_q"];
  810 + iBcIndex = oBcIndex["s_b"];
  811 + iBcCount = oBcIndex["bcount"];
  812 +
  813 + for (j = 0; j < iBcCount - 1; j++) {
  814 + oBc = this.getBc(iQIndex, iBcIndex);
  815 + oNextBc = this.getBc(
  816 + iBcIndex == 0 ? iQIndex : iQIndex + 1,
  817 + iBcIndex == 0 ? 1 : 0);
  818 +
  819 + if (oNextBc.fnIsFirstBc()) { // 如果同一路牌连续2个方向首站班次,都不做处理
  820 + continue;
  821 + }
  822 +
  823 + // 不改变当前班次的行驶时间,修正停站时间和下一个班次的发车时间
  824 + iBcStopTime = oNextBc.getFcTimeObj().diff(oBc.getArrTimeObj(), "m");
  825 + if (iBcStopTime < 0) {
  826 + // 当前班次使用最小停站时间
  827 + oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));
  828 + oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);
  829 +
  830 + } else {
  831 + if (iBcStopTime == oBc.getStopTime() + oBc.fnGetEatTime()) {
  832 + // 停站时间一致,没有问题
  833 +
  834 +
  835 + } else {
  836 + // TODO:当前班次使用最小停站时间
  837 + oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));
  838 + oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);
  839 +
  840 + }
  841 + }
  842 +
  843 + iBcIndex = iBcIndex == 0 ? 1 : 0;
  844 + iQIndex = iBcIndex == 0 ? iQIndex + 1 : iQIndex;
  845 + }
  846 +
  847 + this.getBc(iQIndex, iBcIndex).setStopTime(0);
  848 + }
  849 +
  850 +
  851 +};
  852 +
  853 +
  854 +// TODO
  855 +
  856 +/**
  857 + *
  858 + *
  859 + */
  860 +InternalLpObj.prototype.calcuLpBx = function() {
  861 +
  862 +};
  863 +
  864 +