Commit 8ac4a72ac39c68924d86e72b30269d263d3a2f6c

Authored by 徐烜
1 parent aa9c5bb7

添加新的时刻表导入格式(带工时)

1、重构时刻表导入逻辑,重构相关文件到包com.bsth.service.schedule.timetable下
2、修改相关的controller,servcie,entity(添加gs属性)
3、添加导入格式对应的ktr文件
4、修改前端时刻表显示指令,去除之前的班型和配档数修改,添加工时修改
5、数据库时刻表班型信息表添加gs字段,字典表添加新的时刻表导入格式

Too many changes to show.

To preserve performance only 20 of 28 files are displayed.

@@ -184,6 +184,12 @@ @@ -184,6 +184,12 @@
184 <groupId>pentaho-kettle</groupId> 184 <groupId>pentaho-kettle</groupId>
185 <artifactId>kettle-core</artifactId> 185 <artifactId>kettle-core</artifactId>
186 <version>6.0.1.0-386</version> 186 <version>6.0.1.0-386</version>
  187 + <exclusions>
  188 + <exclusion>
  189 + <groupId>org.apache.xmlgraphics</groupId>
  190 + <artifactId>batik-js</artifactId>
  191 + </exclusion>
  192 + </exclusions>
187 </dependency> 193 </dependency>
188 <dependency> 194 <dependency>
189 <groupId>pentaho-kettle</groupId> 195 <groupId>pentaho-kettle</groupId>
src/main/java/com/bsth/controller/schedule/core/TTInfoDetailController_facade.java
@@ -12,7 +12,7 @@ import com.bsth.controller.schedule.BController_facade; @@ -12,7 +12,7 @@ import com.bsth.controller.schedule.BController_facade;
12 import com.bsth.service.schedule.TTInfoDetailService; 12 import com.bsth.service.schedule.TTInfoDetailService;
13 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit; 13 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
14 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData; 14 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
15 -import com.bsth.service.schedule.timetable.ExcelFormatType; 15 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
16 import com.bsth.service.schedule.utils.DataToolsFile; 16 import com.bsth.service.schedule.utils.DataToolsFile;
17 import com.bsth.service.schedule.utils.DataToolsFileType; 17 import com.bsth.service.schedule.utils.DataToolsFileType;
18 import org.apache.commons.lang3.StringUtils; 18 import org.apache.commons.lang3.StringUtils;
@@ -143,7 +143,7 @@ public class TTInfoDetailController_facade extends BController_facade&lt;Long, TTIn @@ -143,7 +143,7 @@ public class TTInfoDetailController_facade extends BController_facade&lt;Long, TTIn
143 throw new Exception("线路版本未知"); 143 throw new Exception("线路版本未知");
144 } 144 }
145 ttInfoDetailService.validateExcelSheet(filename, sheetname, lineid, linename, lineversion, 145 ttInfoDetailService.validateExcelSheet(filename, sheetname, lineid, linename, lineversion,
146 - ExcelFormatType.getEnum(excelFormatType)); 146 + TimetableExcelFormatType.fromDesc(excelFormatType));
147 rtn.put("status", ResponseCode.SUCCESS); 147 rtn.put("status", ResponseCode.SUCCESS);
148 } catch (Exception exp) { 148 } catch (Exception exp) {
149 rtn.put("status", ResponseCode.ERROR); 149 rtn.put("status", ResponseCode.ERROR);
src/main/java/com/bsth/controller/schedule/core/legacy/TTInfoDetailController.java
@@ -7,7 +7,7 @@ import com.bsth.entity.schedule.TTInfoDetail; @@ -7,7 +7,7 @@ import com.bsth.entity.schedule.TTInfoDetail;
7 import com.bsth.service.schedule.TTInfoDetailService; 7 import com.bsth.service.schedule.TTInfoDetailService;
8 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit; 8 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
9 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData; 9 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
10 -import com.bsth.service.schedule.timetable.ExcelFormatType; 10 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
11 import com.bsth.service.schedule.utils.DataToolsFile; 11 import com.bsth.service.schedule.utils.DataToolsFile;
12 import com.bsth.service.schedule.utils.DataToolsFileType; 12 import com.bsth.service.schedule.utils.DataToolsFileType;
13 import com.bsth.service.schedule.utils.MyHttpUtils; 13 import com.bsth.service.schedule.utils.MyHttpUtils;
@@ -54,7 +54,7 @@ public class TTInfoDetailController extends BController&lt;TTInfoDetail, Long&gt; { @@ -54,7 +54,7 @@ public class TTInfoDetailController extends BController&lt;TTInfoDetail, Long&gt; {
54 throw new Exception("线路版本未知"); 54 throw new Exception("线路版本未知");
55 } 55 }
56 ttInfoDetailService.validateExcelSheet(filename, sheetname, lineid, linename, lineversion, 56 ttInfoDetailService.validateExcelSheet(filename, sheetname, lineid, linename, lineversion,
57 - ExcelFormatType.getEnum(excelFormatType)); 57 + TimetableExcelFormatType.fromDesc(excelFormatType));
58 rtn.put("status", ResponseCode.SUCCESS); 58 rtn.put("status", ResponseCode.SUCCESS);
59 } catch (Exception exp) { 59 } catch (Exception exp) {
60 rtn.put("status", ResponseCode.ERROR); 60 rtn.put("status", ResponseCode.ERROR);
src/main/java/com/bsth/entity/schedule/TTInfoBxDetail.java
@@ -34,14 +34,17 @@ public class TTInfoBxDetail extends BEntity { @@ -34,14 +34,17 @@ public class TTInfoBxDetail extends BEntity {
34 34
35 /** 路牌班型1 */ 35 /** 路牌班型1 */
36 @Convert(converter = BxTypeConverter.class) 36 @Convert(converter = BxTypeConverter.class)
37 - @Column(nullable = false) 37 + @Column(columnDefinition = "default '_null_'", nullable = false)
38 private BxType bxType1; 38 private BxType bxType1;
39 /** 路牌班型2 */ 39 /** 路牌班型2 */
40 - @Column(nullable = false)  
41 @Convert(converter = BxTypeConverter.class) 40 @Convert(converter = BxTypeConverter.class)
  41 + @Column(columnDefinition = "default '_null_'", nullable = false)
42 private BxType bxType2; 42 private BxType bxType2;
43 /** 路牌配档数 */ 43 /** 路牌配档数 */
44 private String bxPds; 44 private String bxPds;
  45 + /** 工时 */
  46 + @Column(nullable = false)
  47 + private String gs;
45 48
46 /** 版本控制 */ 49 /** 版本控制 */
47 @Version 50 @Version
@@ -122,4 +125,11 @@ public class TTInfoBxDetail extends BEntity { @@ -122,4 +125,11 @@ public class TTInfoBxDetail extends BEntity {
122 this.version = version; 125 this.version = version;
123 } 126 }
124 127
  128 + public String getGs() {
  129 + return gs;
  130 + }
  131 +
  132 + public void setGs(String gs) {
  133 + this.gs = gs;
  134 + }
125 } 135 }
src/main/java/com/bsth/service/schedule/TTInfoDetailService.java
@@ -4,7 +4,7 @@ import com.bsth.entity.schedule.TTInfoDetail; @@ -4,7 +4,7 @@ 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.datatools.TTinfoDetailDynamicData;
6 import com.bsth.service.schedule.exception.ScheduleException; 6 import com.bsth.service.schedule.exception.ScheduleException;
7 -import com.bsth.service.schedule.timetable.ExcelFormatType; 7 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
8 import com.bsth.service.schedule.utils.DataToolsFile; 8 import com.bsth.service.schedule.utils.DataToolsFile;
9 import com.bsth.service.schedule.utils.DataToolsFileType; 9 import com.bsth.service.schedule.utils.DataToolsFileType;
10 10
@@ -77,7 +77,7 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; { @@ -77,7 +77,7 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; {
77 * @param sheetname sheet名字 77 * @param sheetname sheet名字
78 * @param lineid 线路id 78 * @param lineid 线路id
79 * @param lineversion 线路版本 79 * @param lineversion 线路版本
80 - * @param excelFormatType 版本 80 + * @param timetableExcelFormatType 时刻表excel格式类型
81 */ 81 */
82 void validateExcelSheet( 82 void validateExcelSheet(
83 String filename, 83 String filename,
@@ -85,7 +85,7 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; { @@ -85,7 +85,7 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; {
85 Integer lineid, 85 Integer lineid,
86 String linename, 86 String linename,
87 Integer lineversion, 87 Integer lineversion,
88 - ExcelFormatType excelFormatType) throws ScheduleException; 88 + TimetableExcelFormatType timetableExcelFormatType) throws ScheduleException;
89 89
90 /** 90 /**
91 * 验证关联的线路标准信息(以后放到规则引擎里去做)。 91 * 验证关联的线路标准信息(以后放到规则引擎里去做)。
src/main/java/com/bsth/service/schedule/datatools/TTInfoDetailDataToolsImpl.java
@@ -3,7 +3,9 @@ package com.bsth.service.schedule.datatools; @@ -3,7 +3,9 @@ package com.bsth.service.schedule.datatools;
3 import com.bsth.entity.StationRoute; 3 import com.bsth.entity.StationRoute;
4 import com.bsth.service.StationRouteService; 4 import com.bsth.service.StationRouteService;
5 import com.bsth.service.schedule.exception.ScheduleException; 5 import com.bsth.service.schedule.exception.ScheduleException;
6 -import com.bsth.service.schedule.timetable.ExcelFormatType; 6 +import com.bsth.service.schedule.timetable.TimetableExcelData;
  7 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
  8 +import com.bsth.service.schedule.timetable.strategy.impl.TimetableExcelDataImportStrategyImpl;
7 import com.bsth.service.schedule.utils.*; 9 import com.bsth.service.schedule.utils.*;
8 import jxl.Sheet; 10 import jxl.Sheet;
9 import jxl.Workbook; 11 import jxl.Workbook;
@@ -14,7 +16,6 @@ import org.apache.commons.lang3.StringUtils; @@ -14,7 +16,6 @@ import org.apache.commons.lang3.StringUtils;
14 import org.apache.poi.ss.usermodel.Cell; 16 import org.apache.poi.ss.usermodel.Cell;
15 import org.apache.poi.ss.usermodel.Row; 17 import org.apache.poi.ss.usermodel.Row;
16 import org.apache.poi.ss.util.CellRangeAddress; 18 import org.apache.poi.ss.util.CellRangeAddress;
17 -import org.apache.poi.xssf.usermodel.XSSFWorkbook;  
18 import org.joda.time.DateTime; 19 import org.joda.time.DateTime;
19 import org.joda.time.LocalTime; 20 import org.joda.time.LocalTime;
20 import org.joda.time.format.DateTimeFormat; 21 import org.joda.time.format.DateTimeFormat;
@@ -22,7 +23,6 @@ import org.slf4j.Logger; @@ -22,7 +23,6 @@ import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 23 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.beans.factory.annotation.Qualifier; 25 import org.springframework.beans.factory.annotation.Qualifier;
25 -import org.springframework.boot.context.properties.EnableConfigurationProperties;  
26 import org.springframework.stereotype.Service; 26 import org.springframework.stereotype.Service;
27 27
28 import java.awt.*; 28 import java.awt.*;
@@ -84,126 +84,144 @@ public class TTInfoDetailDataToolsImpl implements DataToolsService, TTInfoDetail @@ -84,126 +84,144 @@ public class TTInfoDetailDataToolsImpl implements DataToolsService, TTInfoDetail
84 try { 84 try {
85 LOGGER.info("//---------------- 导入时刻表明细 start... ----------------//"); 85 LOGGER.info("//---------------- 导入时刻表明细 start... ----------------//");
86 86
87 - if (params.get("lineversion") == null) {  
88 - throw new Exception("线路版本未知");  
89 - }  
90 -  
91 - String filename = file.getAbsolutePath(); // xls xlsx 文件名  
92 - String sheetname = String.valueOf(params.get("sheetname")); // sheet名字  
93 - Long ttid = Long.valueOf(String.valueOf(params.get("ttid"))); // 时刻表id  
94 - Long xlid = Long.valueOf(String.valueOf(params.get("xlid"))); // 线路id  
95 - Integer lineid = Integer.valueOf(String.valueOf(params.get("lineinfo"))); // 线路标准id  
96 - String xlname = String.valueOf(params.get("xlname")); // 线路名字  
97 - String ttname = String.valueOf(params.get("ttname")); // 时刻表名字  
98 - Integer lineversion = Integer.valueOf(params.get("lineversion").toString()); // 线路路由版本  
99 - ExcelFormatType excelFormatType = ExcelFormatType.getEnum(String.valueOf(params.get("excelFormatType"))); // 格式  
100 -  
101 - LOGGER.info("参数1, xls文件名={},sheet名字={}", filename, sheetname);  
102 - LOGGER.info("参数2, 线路id={},线路名字={}", xlid, xlname);  
103 - LOGGER.info("参数3, 时刻表id={},时刻表名字={}", ttid, ttname);  
104 -  
105 - LOGGER.info("转换xls文件格式成文本格式...");  
106 - // 1、修改已经上传的excel文件,在每个起点站后标示数字,表示第几个班次  
107 - // 2、由于格式问题,需要把内容都转换成字符串  
108 - List<String> colList = new ArrayList<>();  
109 -  
110 - // poi api,并读取第一行数据,组合成站点列表,逗号分隔  
111 - org.apache.poi.ss.usermodel.Workbook poi_workbook;  
112 - org.apache.poi.ss.usermodel.Sheet poi_sheet;  
113 - if (DataToolsFileType.XLS.isThisType(file)) {  
114 - poi_workbook = DataToolsFileType.XLS.getWorkBook(file);  
115 - } else if (DataToolsFileType.XLSX.isThisType(file)) {  
116 - poi_workbook = DataToolsFileType.XLSX.getWorkBook(file);  
117 - } else {  
118 - throw new Exception("不是xls xlsx文件!");  
119 - }  
120 - poi_sheet = poi_workbook.getSheet(sheetname);  
121 - int rownums = poi_sheet.getLastRowNum() + 1;  
122 - int colnums = poi_sheet.getRow(0).getLastCellNum();  
123 - Row firstrow = poi_sheet.getRow(0);  
124 - for (int i = 0; i < colnums; i++) {  
125 - org.apache.poi.ss.usermodel.Cell cell = firstrow.getCell(i);  
126 - if (i == 0) {  
127 - colList.add(PoiUtils.getStringValueFromCell(cell).trim());  
128 - } else {  
129 - // 站点名字后加->数字形式标示成不同的字段  
130 - colList.add(PoiUtils.getStringValueFromCell(cell).trim().replaceAll("(->\\d+)", "") + "->" + i);  
131 - }  
132 - }  
133 -  
134 - // jxl api  
135 - File fileCal = new File(filename + "_stringType.xls");  
136 - WritableWorkbook writableWorkbook = Workbook.createWorkbook(fileCal);  
137 - WritableSheet sheet1 = writableWorkbook.createSheet(sheetname, 0);  
138 - for (int i = 0; i < colnums; i++) { // 第一行数据  
139 - sheet1.addCell(new Label(i, 0, colList.get(i)));  
140 - }  
141 - for (int i = 1; i < rownums; i++) { // 第二行开始  
142 - for (int j = 0; j < colnums; j++) {  
143 - // poi读  
144 - String cellContent = PoiUtils.getStringValueFromCell(  
145 - poi_sheet.getRow(i).getCell(j)  
146 - ).replaceAll("\\s*", "");  
147 - // jxl写  
148 - sheet1.addCell(new Label(j, i, cellContent));  
149 - }  
150 - }  
151 - writableWorkbook.write();  
152 - writableWorkbook.close();  
153 -  
154 - // 2、删除原有数据  
155 - // 操作在ktr内部执行  
156 -  
157 - // 3、导入时刻表  
158 -  
159 - // 计算表头参数  
160 - Workbook book = Workbook.getWorkbook(fileCal);  
161 - Sheet sheet_exp = book.getSheet(sheetname);  
162 - List<String> columnames = new ArrayList<>();  
163 - for (int i = 0; i < sheet_exp.getColumns(); i++) { // 获取第一行,数据,作为列名  
164 - columnames.add(sheet_exp.getCell(i, 0).getContents());  
165 - }  
166 - LOGGER.info("表头={}", StringUtils.join(columnames.toArray(), ","));  
167 -  
168 - // 创建ktr转换所需参数  
169 - Map<String, Object> ktrParms = new HashMap<>();  
170 - // 元数据ktr  
171 - File mktrFile = new File(this.getClass().getResource(  
172 - dataToolsProperties.getTtinfodetailMetadatainputktr()).toURI());  
173 - // 实际数据ktr  
174 - File ktrFile2_version = new File(this.getClass().getResource(  
175 - dataToolsProperties.getTtinfodetailDatainputktr2version()).toURI());  
176 - // 实际数据ktr2  
177 - File ktrFile2_version2 = new File(this.getClass().getResource(  
178 - dataToolsProperties.getTtinfodetailDatainputktr2version2()).toURI());  
179 -  
180 -  
181 - // 通用参数,转换文件路径,excel输入文件路径,错误输出文件路径  
182 - ktrParms.put("transpath", mktrFile.getAbsolutePath());  
183 - ktrParms.put("filepath", fileCal.getAbsolutePath());  
184 - ktrParms.put("erroroutputdir", dataToolsProperties.getTransErrordir());  
185 -  
186 - // 附加参数  
187 - if (excelFormatType == ExcelFormatType.Normal) {  
188 - ktrParms.put("injectktrfile", ktrFile2_version.getAbsolutePath()); // 注入元数据的ktr文件  
189 - } else if (excelFormatType == ExcelFormatType.Dynamic) {  
190 - ktrParms.put("injectktrfile", ktrFile2_version2.getAbsolutePath()); // 注入元数据的ktr文件  
191 - } else {  
192 - throw new ScheduleException("未知ExcelFormatType");  
193 - }  
194 -  
195 - ktrParms.put("sheetname", sheetname); // sheet工作区的名字  
196 - ktrParms.put("lineinfoid", lineid); // 线路标准id  
197 - ktrParms.put("xlname", xlname); // 线路名称  
198 - ktrParms.put("xlid", xlid); // 线路id  
199 - ktrParms.put("ttinfoname", ttname); // 时刻表名称  
200 - ktrParms.put("ttid", ttid.intValue()); // 时刻表id  
201 - ktrParms.put("lineversion", lineversion); // 站点路由版本  
202 - ktrParms.put("excelfieldnames", StringUtils.join(columnames.toArray(), ",")); // 时刻表excel输入字段名,以逗号连接  
203 - columnames.remove(0);  
204 - ktrParms.put("normalizefieldnames", StringUtils.join(columnames.toArray(), ",")); // 数据范式化字段名,以逗号连接  
205 -  
206 - dataToolsService.importData(fileCal, ktrParms); 87 + TimetableExcelData timetableExcelData = TimetableExcelData.withImportBuilder()
  88 + .setExcelFilePath(file.getAbsolutePath())
  89 + .setExcelSheetName(String.valueOf(params.get("sheetname")))
  90 + .setTtInfoId(Long.valueOf(String.valueOf(params.get("ttid"))))
  91 + .setLineId(Integer.valueOf(String.valueOf(params.get("xlid"))))
  92 + .setLineInfoId(Integer.valueOf(String.valueOf(params.get("lineinfo"))))
  93 + .setLineName(String.valueOf(params.get("xlname")))
  94 + .setTtInfoName(String.valueOf(params.get("ttname")))
  95 + .setLineRouteVersion(Integer.valueOf(String.valueOf(params.get("lineversion"))))
  96 + .setTimetableExcelFormatType(TimetableExcelFormatType.fromDesc(
  97 + String.valueOf(params.get("excelFormatType"))))
  98 + .setDataToolsService(this.dataToolsService)
  99 + .setDataToolsProperties(this.dataToolsProperties)
  100 + .setTimetableExcelDataImportStrategy(new TimetableExcelDataImportStrategyImpl())
  101 + .build();
  102 +
  103 + timetableExcelData.doImport();
  104 +
  105 +// if (params.get("lineversion") == null) {
  106 +// throw new Exception("线路版本未知");
  107 +// }
  108 +//
  109 +// String filename = file.getAbsolutePath(); // xls xlsx 文件名
  110 +// String sheetname = String.valueOf(params.get("sheetname")); // sheet名字
  111 +// Long ttid = Long.valueOf(String.valueOf(params.get("ttid"))); // 时刻表id
  112 +// Long xlid = Long.valueOf(String.valueOf(params.get("xlid"))); // 线路id
  113 +// Integer lineid = Integer.valueOf(String.valueOf(params.get("lineinfo"))); // 线路标准id
  114 +// String xlname = String.valueOf(params.get("xlname")); // 线路名字
  115 +// String ttname = String.valueOf(params.get("ttname")); // 时刻表名字
  116 +// Integer lineversion = Integer.valueOf(params.get("lineversion").toString()); // 线路路由版本
  117 +// ExcelFormatType excelFormatType = ExcelFormatType.getEnum(String.valueOf(params.get("excelFormatType"))); // 格式
  118 +//
  119 +// LOGGER.info("参数1, xls文件名={},sheet名字={}", filename, sheetname);
  120 +// LOGGER.info("参数2, 线路id={},线路名字={}", xlid, xlname);
  121 +// LOGGER.info("参数3, 时刻表id={},时刻表名字={}", ttid, ttname);
  122 +//
  123 +// LOGGER.info("转换xls文件格式成文本格式...");
  124 +// // 1、修改已经上传的excel文件,在每个起点站后标示数字,表示第几个班次
  125 +// // 2、由于格式问题,需要把内容都转换成字符串
  126 +// List<String> colList = new ArrayList<>();
  127 +//
  128 +// // poi api,并读取第一行数据,组合成站点列表,逗号分隔
  129 +// org.apache.poi.ss.usermodel.Workbook poi_workbook;
  130 +// org.apache.poi.ss.usermodel.Sheet poi_sheet;
  131 +// if (DataToolsFileType.XLS.isThisType(file)) {
  132 +// poi_workbook = DataToolsFileType.XLS.getWorkBook(file);
  133 +// } else if (DataToolsFileType.XLSX.isThisType(file)) {
  134 +// poi_workbook = DataToolsFileType.XLSX.getWorkBook(file);
  135 +// } else {
  136 +// throw new Exception("不是xls xlsx文件!");
  137 +// }
  138 +// poi_sheet = poi_workbook.getSheet(sheetname);
  139 +// int rownums = poi_sheet.getLastRowNum() + 1;
  140 +// int colnums = poi_sheet.getRow(0).getLastCellNum();
  141 +// Row firstrow = poi_sheet.getRow(0);
  142 +// for (int i = 0; i < colnums; i++) {
  143 +// org.apache.poi.ss.usermodel.Cell cell = firstrow.getCell(i);
  144 +// if (i == 0) {
  145 +// colList.add(PoiUtils.getStringValueFromCell(cell).trim());
  146 +// } else {
  147 +// // 站点名字后加->数字形式标示成不同的字段
  148 +// colList.add(PoiUtils.getStringValueFromCell(cell).trim().replaceAll("(->\\d+)", "") + "->" + i);
  149 +// }
  150 +// }
  151 +//
  152 +// // jxl api
  153 +// File fileCal = new File(filename + "_stringType.xls");
  154 +// WritableWorkbook writableWorkbook = Workbook.createWorkbook(fileCal);
  155 +// WritableSheet sheet1 = writableWorkbook.createSheet(sheetname, 0);
  156 +// for (int i = 0; i < colnums; i++) { // 第一行数据
  157 +// sheet1.addCell(new Label(i, 0, colList.get(i)));
  158 +// }
  159 +// for (int i = 1; i < rownums; i++) { // 第二行开始
  160 +// for (int j = 0; j < colnums; j++) {
  161 +// // poi读
  162 +// String cellContent = PoiUtils.getStringValueFromCell(
  163 +// poi_sheet.getRow(i).getCell(j)
  164 +// ).replaceAll("\\s*", "");
  165 +// // jxl写
  166 +// sheet1.addCell(new Label(j, i, cellContent));
  167 +// }
  168 +// }
  169 +// writableWorkbook.write();
  170 +// writableWorkbook.close();
  171 +//
  172 +// // 2、删除原有数据
  173 +// // 操作在ktr内部执行
  174 +//
  175 +// // 3、导入时刻表
  176 +//
  177 +// // 计算表头参数
  178 +// Workbook book = Workbook.getWorkbook(fileCal);
  179 +// Sheet sheet_exp = book.getSheet(sheetname);
  180 +// List<String> columnames = new ArrayList<>();
  181 +// for (int i = 0; i < sheet_exp.getColumns(); i++) { // 获取第一行,数据,作为列名
  182 +// columnames.add(sheet_exp.getCell(i, 0).getContents());
  183 +// }
  184 +// LOGGER.info("表头={}", StringUtils.join(columnames.toArray(), ","));
  185 +//
  186 +// // 创建ktr转换所需参数
  187 +// Map<String, Object> ktrParms = new HashMap<>();
  188 +// // 元数据ktr
  189 +// File mktrFile = new File(this.getClass().getResource(
  190 +// dataToolsProperties.getTtinfodetailMetadatainputktr()).toURI());
  191 +// // 实际数据ktr
  192 +// File ktrFile2_version = new File(this.getClass().getResource(
  193 +// dataToolsProperties.getTtinfodetailDatainputktr2version()).toURI());
  194 +// // 实际数据ktr2
  195 +// File ktrFile2_version2 = new File(this.getClass().getResource(
  196 +// dataToolsProperties.getTtinfodetailDatainputktr2version2()).toURI());
  197 +//
  198 +//
  199 +// // 通用参数,转换文件路径,excel输入文件路径,错误输出文件路径
  200 +// ktrParms.put("transpath", mktrFile.getAbsolutePath());
  201 +// ktrParms.put("filepath", fileCal.getAbsolutePath());
  202 +// ktrParms.put("erroroutputdir", dataToolsProperties.getTransErrordir());
  203 +//
  204 +// // 附加参数
  205 +// if (excelFormatType == ExcelFormatType.Normal) {
  206 +// ktrParms.put("injectktrfile", ktrFile2_version.getAbsolutePath()); // 注入元数据的ktr文件
  207 +// } else if (excelFormatType == ExcelFormatType.Dynamic) {
  208 +// ktrParms.put("injectktrfile", ktrFile2_version2.getAbsolutePath()); // 注入元数据的ktr文件
  209 +// } else {
  210 +// throw new ScheduleException("未知ExcelFormatType");
  211 +// }
  212 +//
  213 +// ktrParms.put("sheetname", sheetname); // sheet工作区的名字
  214 +// ktrParms.put("lineinfoid", lineid); // 线路标准id
  215 +// ktrParms.put("xlname", xlname); // 线路名称
  216 +// ktrParms.put("xlid", xlid); // 线路id
  217 +// ktrParms.put("ttinfoname", ttname); // 时刻表名称
  218 +// ktrParms.put("ttid", ttid.intValue()); // 时刻表id
  219 +// ktrParms.put("lineversion", lineversion); // 站点路由版本
  220 +// ktrParms.put("excelfieldnames", StringUtils.join(columnames.toArray(), ",")); // 时刻表excel输入字段名,以逗号连接
  221 +// columnames.remove(0);
  222 +// ktrParms.put("normalizefieldnames", StringUtils.join(columnames.toArray(), ",")); // 数据范式化字段名,以逗号连接
  223 +//
  224 +// dataToolsService.importData(fileCal, ktrParms);
207 225
208 LOGGER.info("//---------------- 导入时刻表明细 success... ----------------//"); 226 LOGGER.info("//---------------- 导入时刻表明细 success... ----------------//");
209 } catch (Exception exp) { 227 } catch (Exception exp) {
src/main/java/com/bsth/service/schedule/impl/TTInfoDetailServiceImpl.java
@@ -28,8 +28,9 @@ import com.bsth.service.schedule.datatools.ExcelPoiOperator; @@ -28,8 +28,9 @@ import com.bsth.service.schedule.datatools.ExcelPoiOperator;
28 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit; 28 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
29 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData; 29 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
30 import com.bsth.service.schedule.exception.ScheduleException; 30 import com.bsth.service.schedule.exception.ScheduleException;
31 -import com.bsth.service.schedule.timetable.ExcelData;  
32 -import com.bsth.service.schedule.timetable.ExcelFormatType; 31 +import com.bsth.service.schedule.timetable.TimetableExcelData;
  32 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
  33 +import com.bsth.service.schedule.timetable.strategy.impl.TimetableExcelDataValidateStrategyImpl;
33 import com.bsth.service.schedule.utils.*; 34 import com.bsth.service.schedule.utils.*;
34 import org.apache.commons.lang3.StringUtils; 35 import org.apache.commons.lang3.StringUtils;
35 import org.apache.commons.lang3.time.DateFormatUtils; 36 import org.apache.commons.lang3.time.DateFormatUtils;
@@ -404,13 +405,26 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im @@ -404,13 +405,26 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
404 } 405 }
405 406
406 @Override 407 @Override
407 - public void validateExcelSheet(String filename, String sheetname, Integer lineid, String linename, Integer lineversion, ExcelFormatType excelFormatType) throws ScheduleException {  
408 - ExcelData excelData = new ExcelData(  
409 - filename, sheetname, lineid,  
410 - lineService, guideboardInfoService,  
411 - lineversion, stationRouteService,  
412 - excelFormatType);  
413 - excelData.validateExcelSheet(); 408 + public void validateExcelSheet(
  409 + String filename,
  410 + String sheetname,
  411 + Integer lineid,
  412 + String linename,
  413 + Integer lineversion,
  414 + TimetableExcelFormatType timetableExcelFormatType
  415 + ) throws ScheduleException {
  416 + TimetableExcelData timetableExcelData = TimetableExcelData.withValidateBuilder()
  417 + .setExcelFilePath(filename)
  418 + .setExcelSheetName(sheetname)
  419 + .setLineId(lineid)
  420 + .setLineRouteVersion(lineversion)
  421 + .setLineService(this.lineService)
  422 + .setStationRouteService(this.stationRouteService)
  423 + .setGuideboardInfoService(this.guideboardInfoService)
  424 + .setTimetableExcelFormatType(timetableExcelFormatType)
  425 + .setTimetableExcelDataValidateStrategy(new TimetableExcelDataValidateStrategyImpl())
  426 + .build();
  427 + timetableExcelData.doValidate();
414 } 428 }
415 429
416 @Override 430 @Override
src/main/java/com/bsth/service/schedule/timetable/ExcelData.java deleted 100644 → 0
1 -package com.bsth.service.schedule.timetable;  
2 -  
3 -import com.bsth.entity.Line;  
4 -import com.bsth.entity.LsStationRoute;  
5 -import com.bsth.entity.schedule.GuideboardInfo;  
6 -import com.bsth.service.LineService;  
7 -import com.bsth.service.StationRouteService;  
8 -import com.bsth.service.schedule.GuideboardInfoService;  
9 -import com.bsth.service.schedule.exception.ScheduleException;  
10 -import com.bsth.service.schedule.utils.DataToolsFile;  
11 -import com.bsth.service.schedule.utils.DataToolsFileType;  
12 -import com.bsth.service.schedule.utils.PoiUtils;  
13 -import org.apache.commons.lang3.StringUtils;  
14 -import org.apache.poi.ss.usermodel.Cell;  
15 -import org.apache.poi.ss.usermodel.Row;  
16 -import org.apache.poi.ss.usermodel.Sheet;  
17 -import org.apache.poi.ss.usermodel.Workbook;  
18 -import org.springframework.util.CollectionUtils;  
19 -  
20 -import java.io.File;  
21 -import java.util.ArrayList;  
22 -import java.util.HashMap;  
23 -import java.util.List;  
24 -import java.util.Map;  
25 -import java.util.regex.Matcher;  
26 -import java.util.regex.Pattern;  
27 -  
28 -/**  
29 - * 时刻表Excel数据类。  
30 - */  
31 -public class ExcelData {  
32 -  
33 - /** 导入后的Excel文件对象 */  
34 - private DataToolsFile dataToolsFile;  
35 - /** 数据sheet名 */  
36 - private String sheetName;  
37 - /** 线路 */  
38 - private Line line;  
39 - /** 线路路由列表(包含上下行的起终点站) */  
40 - private List<LsStationRoute> lsStationRouteList;  
41 - /** 路牌列表 */  
42 - private List<GuideboardInfo> guideboardInfoList;  
43 - /** excel数据格式 */  
44 - private ExcelFormatType excelFormatType;  
45 -  
46 - public DataToolsFile getDataToolsFile() {  
47 - return dataToolsFile;  
48 - }  
49 -  
50 - public void setDataToolsFile(DataToolsFile dataToolsFile) {  
51 - this.dataToolsFile = dataToolsFile;  
52 - }  
53 -  
54 - public String getSheetName() {  
55 - return sheetName;  
56 - }  
57 -  
58 - public void setSheetName(String sheetName) {  
59 - this.sheetName = sheetName;  
60 - }  
61 -  
62 - public Line getLine() {  
63 - return line;  
64 - }  
65 -  
66 - public void setLine(Line line) {  
67 - this.line = line;  
68 - }  
69 -  
70 - public List<LsStationRoute> getLsStationRouteList() {  
71 - return lsStationRouteList;  
72 - }  
73 -  
74 - public void setLsStationRouteList(List<LsStationRoute> lsStationRouteList) {  
75 - this.lsStationRouteList = lsStationRouteList;  
76 - }  
77 -  
78 - public List<GuideboardInfo> getGuideboardInfoList() {  
79 - return guideboardInfoList;  
80 - }  
81 -  
82 - public void setGuideboardInfoList(List<GuideboardInfo> guideboardInfoList) {  
83 - this.guideboardInfoList = guideboardInfoList;  
84 - }  
85 -  
86 - public ExcelFormatType getExcelFormatType() {  
87 - return excelFormatType;  
88 - }  
89 -  
90 - public void setExcelFormatType(ExcelFormatType excelFormatType) {  
91 - this.excelFormatType = excelFormatType;  
92 - }  
93 -  
94 - /**  
95 - * 构造函数  
96 - * @param filePath 文件路径  
97 - * @param sheetName sheet名字  
98 - * @param lineId 线路Id  
99 - * @param lineService LineServiceImpl  
100 - * @param guideboardInfoService GuideboardInfoServiceImpl  
101 - * @param lineRouteVersion 线路路由版本  
102 - * @param stationRouteService StationRouteServiceImpl  
103 - * @param excelFormatType excel数据格式  
104 - * @throws ScheduleException  
105 - * @see com.bsth.service.impl.LineServiceImpl  
106 - * @see com.bsth.service.schedule.impl.GuideboardInfoServiceImpl  
107 - * @see com.bsth.service.impl.StationRouteServiceImpl  
108 - */  
109 - public ExcelData(  
110 - String filePath, String sheetName,  
111 - Integer lineId, LineService lineService, GuideboardInfoService guideboardInfoService,  
112 - Integer lineRouteVersion, StationRouteService stationRouteService,  
113 - ExcelFormatType excelFormatType) throws ScheduleException {  
114 - // 获取Excel文件对象,类型  
115 - File file = new File(filePath);  
116 - this.dataToolsFile = new DataToolsFile();  
117 - this.dataToolsFile.setFile(file);  
118 - if (DataToolsFileType.XLS.isThisType(file)) {  
119 - this.dataToolsFile.setFileType(DataToolsFileType.XLS);  
120 - } else if (DataToolsFileType.XLSX.isThisType(file)) {  
121 - this.dataToolsFile.setFileType(DataToolsFileType.XLSX);  
122 - } else {  
123 - throw new ScheduleException("不是xls xlsx文件!");  
124 - }  
125 -  
126 - // sheet名字  
127 - this.sheetName = sheetName;  
128 - // 线路  
129 - this.line = lineService.findById(lineId);  
130 - // 线路路由列表  
131 - Map<String, Object> p1 = new HashMap<>();  
132 - p1.put("line.id_eq", lineId);  
133 - p1.put("stationMark_in", "B,E"); // 起点站  
134 - p1.put("destroy_eq", 0); // 未撤销  
135 - p1.put("versions_eq", lineRouteVersion); // 带线路版本  
136 - lsStationRouteList = (List<LsStationRoute>) stationRouteService.list_ls(p1);  
137 - // 路牌列表  
138 - p1.clear();  
139 - p1.put("xl.id_eq", lineId);  
140 - p1.put("isCancel_eq", false);  
141 - guideboardInfoList = guideboardInfoService.list(p1);  
142 -  
143 - // excel数据格式  
144 - this.excelFormatType = excelFormatType;  
145 - }  
146 -  
147 - /**  
148 - * 验证路由名字。  
149 - * @param colNum 列标号(从0开始)  
150 - * @param routeName 路由名字  
151 - * @throws ScheduleException  
152 - */  
153 - private void validateRouteName(int colNum, String routeName) throws ScheduleException {  
154 - List<LsStationRoute> lsStationRoutes = new ArrayList<>();  
155 - for (LsStationRoute lsStationRoute : this.lsStationRouteList) {  
156 - if ("B".equals(lsStationRoute.getStationMark()) && routeName.equals(lsStationRoute.getStationName())) {  
157 - lsStationRoutes.add(lsStationRoute);  
158 - }  
159 - }  
160 -  
161 - if (CollectionUtils.isEmpty(lsStationRoutes)) {  
162 - throw new ScheduleException(String.format("第1行,第%d列数据%s在%s站点路由中不是起点站",  
163 - colNum + 1, routeName, this.line.getName()));  
164 - } else if (lsStationRoutes.size() > 1) {  
165 - throw new ScheduleException(String.format("第1行,第%d列数据%s在%s站点路由中上下行都是起点站",  
166 - colNum + 1, routeName, this.line.getName()));  
167 - } else if (StringUtils.isEmpty(lsStationRoutes.get(0).getStationCode())) {  
168 - throw new ScheduleException(String.format("第1行,第%d列数据%s在%s站点路由中没有站点编码",  
169 - colNum + 1, routeName, this.line.getName()));  
170 - }  
171 -  
172 - }  
173 -  
174 - /**  
175 - * 验证路牌名字。  
176 - * @param colNum excelSheet 列index  
177 - * @param guideboardName 路牌名字  
178 - * @throws ScheduleException  
179 - */  
180 - private void validateGuideboardName(int colNum, String guideboardName) throws ScheduleException {  
181 - List<GuideboardInfo> guideboardInfos = new ArrayList<>();  
182 - for (GuideboardInfo guideboardInfo : this.guideboardInfoList) {  
183 - if (guideboardName.equals(guideboardInfo.getLpName())) {  
184 - guideboardInfos.add(guideboardInfo);  
185 - }  
186 - }  
187 -  
188 - if (CollectionUtils.isEmpty(guideboardInfos)) {  
189 - throw new ScheduleException(String.format("第%d行,第1列的路牌在%s中不存在",  
190 - colNum + 1, this.line.getName()));  
191 - } else if (guideboardInfos.size() > 1) {  
192 - throw new ScheduleException(String.format("第%d行,第1列的路牌在%s中重复",  
193 - colNum + 1, this.line.getName()));  
194 - }  
195 - }  
196 -  
197 - /**  
198 - * 验证发车时间内容。  
199 - * @param rowNum excelSheet 行index  
200 - * @param colNum excelSheet 列index  
201 - * @param fcsjContent 发车时间内容  
202 - * @throws ScheduleException  
203 - */  
204 - private void validateFcsjContent(int rowNum, int colNum, String fcsjContent) throws ScheduleException {  
205 - if (this.excelFormatType == ExcelFormatType.Normal) {  
206 - // 班次时间验证,正则表达式,格式hh:mm或者hhmm  
207 - String rex1 = "^([01]?[0-9]|2[0-3]):[0-5][0-9]$"; // hh:mm格式  
208 - String rex2 = "^([01]?[0-9]|2[0-3]),[0-5][0-9]$"; // hh,mm格式  
209 - String rex3 = "^([01]?[0-9]|2[0-3])[0-5][0-9]$"; // hhmm格式  
210 - Pattern p1 = Pattern.compile(rex1);  
211 - Pattern p2 = Pattern.compile(rex2);  
212 - Pattern p3 = Pattern.compile(rex3);  
213 -  
214 - Matcher m1 = p1.matcher(fcsjContent.trim());  
215 - Matcher m2 = p2.matcher(fcsjContent.trim());  
216 - Matcher m3 = p3.matcher(fcsjContent.trim());  
217 - if ((!m1.matches()) && (!m2.matches()) && (!m3.matches())) {  
218 - throw new ScheduleException(String.format("第%d行,第%d列的发车时间格式不正确,格式应为hh:mm或hh,mm或hhmm",  
219 - rowNum + 1, colNum + 1));  
220 - }  
221 - } else if (this.excelFormatType == ExcelFormatType.Dynamic) {  
222 - String rex1 = "^(\u62a5|\u51fa)?([01]?[0-9]|2[0-3]):[0-5][0-9]$"; // (报|出)hh:mm格式  
223 - String rex2 = "^([01]?[0-9]|2[0-3]):[0-5][0-9](X|\u203b)?$"; // hh:mm(X|※)格式  
224 - Pattern p1 = Pattern.compile(rex1);  
225 - Pattern p2 = Pattern.compile(rex2);  
226 - Matcher m1 = p1.matcher(fcsjContent.trim());  
227 - Matcher m2 = p2.matcher(fcsjContent.trim());  
228 - if ((!m1.matches()) && (!m2.matches())) {  
229 - throw new ScheduleException(String.format(  
230 - "第%d行,第%d列的发车时间格式不正确,格式应为(报|出)hh:mm或hh:mm(X|※)",  
231 - rowNum + 1, colNum + 1));  
232 - }  
233 - } else {  
234 - throw new ScheduleException("未知ExcelFormatType");  
235 - }  
236 -  
237 - }  
238 -  
239 - private List<Integer> calcuExcelSheetColIndexList(Workbook workbook) throws ScheduleException {  
240 - // 有些列不需要参与计算,找出参与计算的列  
241 - List<Integer> colIndexList = new ArrayList<>();  
242 - Sheet sheet = workbook.getSheet(this.sheetName);  
243 - Row firstRow = sheet.getRow(0); // 获取第一行数据列  
244 - for (int i = 0; i < firstRow.getLastCellNum(); i++) {  
245 - if (excelFormatType == ExcelFormatType.Normal) {  
246 - colIndexList.add(i);  
247 - } else if (excelFormatType == ExcelFormatType.Dynamic) {  
248 - String cell_con = StringUtils.trimToEmpty(  
249 - PoiUtils.getStringValueFromCell(firstRow.getCell(i))); // trimToEmpty  
250 - if ("报到".equals(cell_con) ||  
251 - "到场".equals(cell_con) ||  
252 - "离场".equals(cell_con) ||  
253 - "总公里".equals(cell_con) ||  
254 - "营业公里".equals(cell_con) ||  
255 - "空驶公里".equals(cell_con) ||  
256 - "总工时".equals(cell_con) ||  
257 - "营业工时".equals(cell_con) ||  
258 - "营运班次".equals(cell_con)) {  
259 - // 这些列全部祛除  
260 - continue;  
261 - } else {  
262 - colIndexList.add(i);  
263 - }  
264 - } else {  
265 - throw new ScheduleException("未知excelFormatType");  
266 - }  
267 - }  
268 - return colIndexList;  
269 - }  
270 -  
271 - /**  
272 - * 验证老系统ExcelSheet格式。  
273 - * @throws ScheduleException  
274 - */  
275 - public void validateExcelSheet() throws ScheduleException {  
276 - try {  
277 - Workbook workbook = this.dataToolsFile.getFileType().getWorkBook(  
278 - this.dataToolsFile.getFile()  
279 - );  
280 -  
281 - Sheet sheet = workbook.getSheet(this.sheetName);  
282 - int rowNums = sheet.getLastRowNum() + 1; // 基于0 base的,长度加1  
283 - int colNums = sheet.getRow(0).getLastCellNum(); // 不需要加1,就是长度  
284 -  
285 - if (rowNums == 0 || colNums == 0) { // 工作区是否为空  
286 - throw new Exception(String.format("%s 工作区没有数据!", this.sheetName));  
287 - } else {  
288 - if (rowNums <= 1 || rowNums <= 1) {  
289 - throw new Exception(String.format("工作区至少包含2行2列的数据"));  
290 - } else {  
291 - List<Integer> colIndexList = this.calcuExcelSheetColIndexList(workbook);  
292 - Row firstRow = sheet.getRow(0); // 获取第一行数据列  
293 - for (int n = 0; n < colIndexList.size(); n++) {  
294 - int i = colIndexList.get(n);  
295 - String cell_con = StringUtils.trimToEmpty(  
296 - PoiUtils.getStringValueFromCell(firstRow.getCell(i))); // trimToEmpty  
297 -  
298 - if (StringUtils.isEmpty(cell_con)) {  
299 - throw new Exception(String.format("第1行,第%d列数据不能为空", i + 1));  
300 - } else {  
301 - // 正则表达式去除右侧数字  
302 -// cell_con = cell_con.replaceAll("[\\d+]", "");  
303 -// cell_con = cell_con.replaceAll("(\\d+)$", "");  
304 -  
305 - // 如果站名中有类似->{数字},使用正则表达式过滤掉  
306 - cell_con = cell_con.replaceAll("(->\\d+)", "");  
307 -  
308 - if (i == 0) { // 第一列必须是路牌2个字  
309 - if (!"路牌".equals(cell_con.trim())) {  
310 - throw new Exception("第1行,第1列数据必须是路牌2个字");  
311 - }  
312 - } else { // 排除出场,进场,其余内容到站点路由里查询,以各个方向的起点站为查询依据  
313 - if ((!"出场".equals(cell_con.trim())) &&  
314 - (!"进场".equals(cell_con.trim()))) {  
315 - validateRouteName(i, cell_con.trim()); // 验证路由名字  
316 - }  
317 -  
318 - }  
319 - }  
320 - }  
321 -  
322 - // 验证路牌内容  
323 - Map<String, Integer> gbindexmap = new HashMap<>(); // 记录每个路牌在第几行  
324 - for (int i = 1; i < rowNums; i++) { // 从第2行开始验证数据  
325 - Cell cell = sheet.getRow(i).getCell(0); // 获取第1列  
326 - String bcell_con = StringUtils.trimToEmpty(  
327 - PoiUtils.getStringValueFromCell(cell)); // trimToEmpty  
328 - if (StringUtils.isEmpty(bcell_con)) {  
329 - throw new Exception(String.format("第%d行,第1列路牌无数据", i + 1));  
330 - } else if (gbindexmap.get(bcell_con.trim()) != null) {  
331 - throw new Exception(String.format("第%d行,第1列的路牌数据与第%d行,第1列数据重复",  
332 - i + 1,  
333 - gbindexmap.get(bcell_con.trim())));  
334 - } else {  
335 - validateGuideboardName(i, bcell_con.trim()); // 验证路牌名字  
336 - gbindexmap.put(bcell_con.trim(), i + 1);  
337 - }  
338 - }  
339 -  
340 - // 验证发车时间格式  
341 - for (int i = 1; i < rowNums; i++) { // 从第2行开始验证数据  
342 - Row row = sheet.getRow(i);  
343 - for (int n = 1; n < colIndexList.size(); n++) { // 从第2列开始  
344 - int j = colIndexList.get(n);  
345 - String bcell_con = StringUtils.trimToEmpty(  
346 - PoiUtils.getStringValueFromCell(  
347 - row.getCell(j))).replaceAll("\\s*", ""); // trimToEmpty  
348 - if (StringUtils.isNotEmpty(bcell_con)) {  
349 - validateFcsjContent(i, j, bcell_con);  
350 - }  
351 - }  
352 - }  
353 - }  
354 -  
355 - }  
356 -  
357 - } catch (Exception exp) {  
358 - exp.printStackTrace();  
359 - throw new ScheduleException(exp.getMessage());  
360 - }  
361 - }  
362 -  
363 -}  
src/main/java/com/bsth/service/schedule/timetable/ExcelFormatType.java deleted 100644 → 0
1 -package com.bsth.service.schedule.timetable;  
2 -  
3 -import com.fasterxml.jackson.annotation.JsonCreator;  
4 -import com.fasterxml.jackson.annotation.JsonValue;  
5 -  
6 -/**  
7 - * 导入时刻表时,excel的数据格式类型。  
8 - */  
9 -public enum ExcelFormatType {  
10 - Normal("normal"), // 老系统格式  
11 - Dynamic("dynamic"); // 自动生成的导出格式  
12 -  
13 - private String flag;  
14 -  
15 - @JsonCreator  
16 - ExcelFormatType(String flag) {  
17 - this.flag = flag;  
18 - }  
19 -  
20 - @JsonValue  
21 - public String getFlag() {  
22 - return flag;  
23 - }  
24 -  
25 - public void setFlag(String flag) {  
26 - this.flag = flag;  
27 - }  
28 -  
29 - public static ExcelFormatType getEnum(String str) {  
30 - if ("normal".equals(str)) {  
31 - return Normal;  
32 - } else if ("dynamic".equals(str)) {  
33 - return Dynamic;  
34 - } else {  
35 - throw new IllegalArgumentException("未知ExcelFormatType");  
36 - }  
37 - }  
38 -}  
src/main/java/com/bsth/service/schedule/timetable/TimetableExcelData.java 0 → 100644
  1 +package com.bsth.service.schedule.timetable;
  2 +
  3 +import com.bsth.entity.Line;
  4 +import com.bsth.entity.LsStationRoute;
  5 +import com.bsth.entity.schedule.GuideboardInfo;
  6 +import com.bsth.service.LineService;
  7 +import com.bsth.service.StationRouteService;
  8 +import com.bsth.service.schedule.GuideboardInfoService;
  9 +import com.bsth.service.schedule.exception.ScheduleException;
  10 +import com.bsth.service.schedule.timetable.strategy.TimetableExcelDataImportStrategy;
  11 +import com.bsth.service.schedule.timetable.strategy.TimetableExcelDataValidateStrategy;
  12 +import com.bsth.service.schedule.utils.*;
  13 +import org.apache.commons.lang3.StringUtils;
  14 +import org.apache.poi.ss.usermodel.Sheet;
  15 +import org.apache.poi.ss.usermodel.Workbook;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
  18 +import org.springframework.util.Assert;
  19 +import org.springframework.util.CollectionUtils;
  20 +
  21 +import java.io.File;
  22 +import java.util.HashMap;
  23 +import java.util.List;
  24 +import java.util.Map;
  25 +
  26 +/**
  27 + * 时刻表Excel数据类,用于验证,导入,导出时刻表数据。
  28 + * 混合Builder和Strategy模式。
  29 + */
  30 +public class TimetableExcelData {
  31 + /** 日志记录器 */
  32 + private final static Logger LOG = LoggerFactory.getLogger(TimetableExcelData.class);
  33 +
  34 + // ------------------ 公共属性及方法,如下:------------------- //
  35 + /** 待导入excel workbook对象 */
  36 + private Workbook excelWorkBook;
  37 + /** 待导入excel workbook 工作区对象 */
  38 + private Sheet excelWorkBookSheet;
  39 + /** 时刻表excel格式类型 */
  40 + private TimetableExcelFormatType timetableExcelFormatType;
  41 +
  42 + // 内部标识excel单元格类
  43 + public static class TimetableExcelInternalCell {
  44 + /** 是否可用(默认不可用) */
  45 + public Boolean isEnable = false;
  46 + /** 单元格内容 */
  47 + public String cellContent;
  48 +
  49 + //------------- 班次类型(发车时间单元格 isFcsjCell = true)-----------//
  50 + /** 是否是班次 */
  51 + public Boolean isBc = false;
  52 + /** 是否是出场班次 */
  53 + public Boolean isOutBc = false;
  54 + /** 是否是进场班次 */
  55 + public Boolean isInBc = false;
  56 +
  57 + //------------- 单元格类型 -------------//
  58 + /** 是否表头Cell */
  59 + public Boolean isHeadCell = false;
  60 + /** 是否路牌名字Cell */
  61 + public Boolean isLpNameCell = false;
  62 + /** 是否发车时间Cell */
  63 + public Boolean isFcsjCell = false;
  64 + /** 是否工时Cell */
  65 + public Boolean isGsCell = false;
  66 + }
  67 + /** 内部Excel单元格二维数组 */
  68 + private TimetableExcelInternalCell[][] internalExcelCells;
  69 + // 初始化内部标识excel单元格
  70 + private void initInternalExcelCells() {
  71 + int rowCount = this.excelWorkBookSheet.getLastRowNum() + 1; // 基于0 base的,长度加1
  72 + Assert.isTrue(rowCount > 1, String.format("%s 工作区没有数据!", this.excelWorkBookSheet.getSheetName()));
  73 + int colCount = this.excelWorkBookSheet.getRow(0).getLastCellNum(); // 不需要加1,就是长度
  74 + Assert.isTrue(colCount > 0, String.format("%s 工作区第一行没有数据!", this.excelWorkBookSheet.getSheetName()));
  75 +
  76 + this.internalExcelCells = new TimetableExcelInternalCell[rowCount][colCount];
  77 + for (int rowNum = 0; rowNum < rowCount; rowNum ++) {
  78 + for (int colNum = 0; colNum < colCount; colNum ++) {
  79 + TimetableExcelInternalCell cell = new TimetableExcelInternalCell();
  80 + String cell_con = StringUtils.trimToEmpty(PoiUtils.getStringValueFromCell(
  81 + this.excelWorkBookSheet.getRow(rowNum).getCell(colNum))
  82 + .replaceAll("\\s*", "")); // trimToEmpty
  83 +
  84 + // 如果站名中有类似->{数字},使用正则表达式过滤掉
  85 + cell_con = cell_con.replaceAll("(->\\d+)", "");
  86 +
  87 + cell.cellContent = cell_con;
  88 + cell.isEnable = true;
  89 + this.internalExcelCells[rowNum][colNum] = cell;
  90 + }
  91 + }
  92 +
  93 + }
  94 +
  95 + // ------------------ 验证相关属性及方法,如下:---------------- //
  96 + /** 线路信息 */
  97 + private Line line;
  98 + /** 线路站点路由列表(包含上下行的起终点站) */
  99 + private List<LsStationRoute> lsStationRouteList;
  100 + /** 路牌列表 */
  101 + private List<GuideboardInfo> guideboardInfoList;
  102 + /** 时刻表excel验证策略 */
  103 + private TimetableExcelDataValidateStrategy timetableExcelDataValidateStrategy;
  104 + /**
  105 + * 验证excel时刻表。
  106 + */
  107 + public void doValidate() throws ScheduleException {
  108 + this.timetableExcelDataValidateStrategy.doValidate(
  109 + this.internalExcelCells,
  110 + this.timetableExcelFormatType,
  111 + this.line,
  112 + this.lsStationRouteList,
  113 + this.guideboardInfoList);
  114 + }
  115 +
  116 + // ------------------ 导入相关属性及方法,如下:---------------- //
  117 + /** 导入的Excel文件路径 */
  118 + private String excelFilePath;
  119 + /** 数据工具服务 */
  120 + private DataToolsService dataToolsService;
  121 + /** 配置数据导入导出用到的配置信息 */
  122 + private DataToolsProperties dataToolsProperties;
  123 + /** ktr转换所需参数对象 */
  124 + private Map<String, Object> ktrParams = new HashMap<>();
  125 + /** 时刻表excel导入策略 */
  126 + private TimetableExcelDataImportStrategy timetableExcelDataImportStrategy;
  127 + /**
  128 + * 导入excel时刻表。
  129 + */
  130 + public void doImport() throws ScheduleException {
  131 + this.timetableExcelDataImportStrategy.doImport(
  132 + this.excelWorkBookSheet,
  133 + this.excelFilePath,
  134 + this.dataToolsService,
  135 + this.dataToolsProperties,
  136 + this.ktrParams,
  137 + this.internalExcelCells,
  138 + this.timetableExcelFormatType);
  139 + }
  140 +
  141 +
  142 + // ----------- 构造函数 ---------- //
  143 + public TimetableExcelData(ValidateBuilder validateBuilder) {
  144 + // 公共属性
  145 + this.excelWorkBook = validateBuilder.excelWorkBook;
  146 + this.excelWorkBookSheet = validateBuilder.excelWorkBookSheet;
  147 + this.timetableExcelFormatType = validateBuilder.timetableExcelFormatType;
  148 + // 验证用属性
  149 + this.line = validateBuilder.line;
  150 + this.lsStationRouteList = validateBuilder.lsStationRouteList;
  151 + this.guideboardInfoList = validateBuilder.guideboardInfoList;
  152 + this.timetableExcelDataValidateStrategy = validateBuilder.timetableExcelDataValidateStrategy;
  153 +
  154 + // 构造内部Excel单元格二维数组
  155 + this.initInternalExcelCells();
  156 + }
  157 + public TimetableExcelData(ImportBuilder importBuilder) {
  158 + // 公共属性
  159 + this.excelWorkBook = importBuilder.excelWorkBook;
  160 + this.excelWorkBookSheet = importBuilder.excelWorkBookSheet;
  161 + this.timetableExcelFormatType = importBuilder.timetableExcelFormatType;
  162 + // 导入用属性
  163 + this.excelFilePath = importBuilder.excelFilePath;
  164 + this.dataToolsService = importBuilder.dataToolsService;
  165 + this.dataToolsProperties = importBuilder.dataToolsProperties;
  166 + this.ktrParams = importBuilder.ktrParams;
  167 + this.timetableExcelDataImportStrategy = importBuilder.timetableExcelDataImportStrategy;
  168 +
  169 + LOG.info("参数组1, xls文件名={},sheet名字={}",
  170 + this.excelFilePath, this.ktrParams.get("sheetname"));
  171 + LOG.info("参数组2, 线路id={},线路名字={},线路版本={}",
  172 + this.ktrParams.get("xlid"), this.ktrParams.get("xlname"), this.ktrParams.get("lineversion"));
  173 + LOG.info("参数组3, 时刻表id={},时刻表名字={}",
  174 + this.ktrParams.get("ttid"), this.ktrParams.get("ttinfoname"));
  175 +
  176 + // 构造内部Excel单元格二维数组
  177 + this.initInternalExcelCells();
  178 + }
  179 +
  180 + // ----------- builder类 ----------- //
  181 + public static ValidateBuilder withValidateBuilder() {
  182 + return new ValidateBuilder();
  183 + }
  184 + /**
  185 + * 验证excel时刻表数据用builder。
  186 + */
  187 + public static class ValidateBuilder {
  188 + private ValidateBuilder() {}
  189 +
  190 + /** 导入的Excel文件路径 */
  191 + private String excelFilePath;
  192 + /** 导入的Excel sheet名字 */
  193 + private String excelSheetName;
  194 + /** 线路Id */
  195 + private Integer lineId;
  196 + /** 线路路由版本 */
  197 + private Integer lineRouteVersion;
  198 + /** 线路信息service */
  199 + private LineService lineService;
  200 + /** 站点路由信息service */
  201 + private StationRouteService stationRouteService;
  202 + /** 路牌信息service */
  203 + private GuideboardInfoService guideboardInfoService;
  204 + /** 时刻表excel格式类型 */
  205 + private TimetableExcelFormatType timetableExcelFormatType;
  206 + /** 时刻表excel验证策略 */
  207 + private TimetableExcelDataValidateStrategy timetableExcelDataValidateStrategy;
  208 +
  209 + public ValidateBuilder setExcelFilePath(String excelFilePath) {
  210 + this.excelFilePath = excelFilePath;
  211 + return this;
  212 + }
  213 +
  214 + public ValidateBuilder setExcelSheetName(String excelSheetName) {
  215 + this.excelSheetName = excelSheetName;
  216 + return this;
  217 + }
  218 +
  219 + public ValidateBuilder setLineId(Integer lineId) {
  220 + this.lineId = lineId;
  221 + return this;
  222 + }
  223 +
  224 + public ValidateBuilder setLineRouteVersion(Integer lineRouteVersion) {
  225 + this.lineRouteVersion = lineRouteVersion;
  226 + return this;
  227 + }
  228 +
  229 + public ValidateBuilder setLineService(LineService lineService) {
  230 + this.lineService = lineService;
  231 + return this;
  232 + }
  233 +
  234 + public ValidateBuilder setStationRouteService(StationRouteService stationRouteService) {
  235 + this.stationRouteService = stationRouteService;
  236 + return this;
  237 + }
  238 +
  239 + public ValidateBuilder setGuideboardInfoService(GuideboardInfoService guideboardInfoService) {
  240 + this.guideboardInfoService = guideboardInfoService;
  241 + return this;
  242 + }
  243 +
  244 + public ValidateBuilder setTimetableExcelFormatType(TimetableExcelFormatType timetableExcelFormatType) {
  245 + this.timetableExcelFormatType = timetableExcelFormatType;
  246 + return this;
  247 + }
  248 +
  249 + public ValidateBuilder setTimetableExcelDataValidateStrategy(TimetableExcelDataValidateStrategy timetableExcelDataValidateStrategy) {
  250 + this.timetableExcelDataValidateStrategy = timetableExcelDataValidateStrategy;
  251 + return this;
  252 + }
  253 +
  254 + // ---------------- 内部生成的属性 ------------------ //
  255 + /** 待导入excel workbook对象 */
  256 + private Workbook excelWorkBook;
  257 + /** 待导入excel workbook工作区对象 */
  258 + private Sheet excelWorkBookSheet;
  259 + /** 线路信息 */
  260 + private Line line;
  261 + /** 线路站点路由列表(包含上下行的起终点站) */
  262 + private List<LsStationRoute> lsStationRouteList;
  263 + /** 路牌列表 */
  264 + private List<GuideboardInfo> guideboardInfoList;
  265 +
  266 + public TimetableExcelData build() throws ScheduleException {
  267 + // 0、检测时刻表excel业务格式
  268 + if (this.timetableExcelFormatType == null) {
  269 + throw new ScheduleException("导入的Excel类型为空!");
  270 + }
  271 +
  272 + // 1、检测excel文件,创建excel workbook对象
  273 + // 1-1、检测文件是否存在
  274 + Assert.hasText(this.excelFilePath, "导入的Excel文件路径为空!");
  275 + File file = new File(this.excelFilePath);
  276 + if (!file.exists()) {
  277 + throw new ScheduleException("导入的Excel文件[" + this.excelFilePath + "]不存在!");
  278 + }
  279 + // 1-2、检测文件类型
  280 + DataToolsFile dataToolsFile = new DataToolsFile();
  281 + dataToolsFile.setFile(file);
  282 + if (DataToolsFileType.XLS.isThisType(file)) {
  283 + dataToolsFile.setFileType(DataToolsFileType.XLS);
  284 + } else if (DataToolsFileType.XLSX.isThisType(file)) {
  285 + dataToolsFile.setFileType(DataToolsFileType.XLSX);
  286 + } else {
  287 + throw new ScheduleException("导入的Excel文件[" + this.excelFilePath + "]内部不是xls,xlsx文件!");
  288 + }
  289 + // 1-3、创建workbook
  290 + this.excelWorkBook = dataToolsFile.getFileType().getWorkBook(dataToolsFile.getFile());
  291 + // 1-4、检测sheet名字
  292 + Assert.hasText(this.excelSheetName, "导入的Excel sheet名字为空!");
  293 + this.excelWorkBookSheet = this.excelWorkBook.getSheet(this.excelSheetName);
  294 + if (this.excelWorkBookSheet == null) {
  295 + throw new ScheduleException("导入的Excel文件sheet[" + this.excelSheetName + "]不存在!");
  296 + }
  297 +
  298 + // 2、获取线路信息,站点路由信息
  299 + // 2-1、线路信息
  300 + Assert.notNull(this.lineService, "线路信息service为空!");
  301 + Assert.notNull(this.lineId, "线路Id为空!");
  302 + this.line = this.lineService.findById(this.lineId);
  303 + if (this.line == null) {
  304 + throw new ScheduleException("线路[id=" + this.lineId + "]不存在!");
  305 + }
  306 + // 2-2、站点路由信息
  307 + Assert.notNull(this.stationRouteService, "站点路由信息service为空!");
  308 + Assert.notNull(this.lineRouteVersion, "线路站点路由版本为空!");
  309 + Map<String, Object> p1 = new HashMap<>();
  310 + p1.put("line.id_eq", this.lineId);
  311 + p1.put("stationMark_in", "B,E"); // 起点站
  312 + p1.put("destroy_eq", 0); // 未撤销
  313 + p1.put("versions_eq", this.lineRouteVersion); // 带线路版本
  314 + this.lsStationRouteList = (List<LsStationRoute>) this.stationRouteService.list_ls(p1);
  315 + if (CollectionUtils.isEmpty(this.lsStationRouteList)) {
  316 + throw new ScheduleException("线路[" + this.line.getName() + "],站点路由[版本=" + this.lineRouteVersion + "]信息为空");
  317 + }
  318 +
  319 + // 3、获取路牌信息
  320 + Assert.notNull(this.guideboardInfoService, "路牌信息service为空!");
  321 + p1.clear();
  322 + p1.put("xl.id_eq", this.lineId);
  323 + p1.put("isCancel_eq", false);
  324 + this.guideboardInfoList = guideboardInfoService.list(p1);
  325 + if (CollectionUtils.isEmpty(this.guideboardInfoList)) {
  326 + throw new ScheduleException("线路[" + this.line.getName() + "]路牌信息为空!");
  327 + }
  328 +
  329 + // 4、验证策略类
  330 + Assert.notNull(this.timetableExcelDataValidateStrategy, "时刻表excel验证策略类为空!");
  331 +
  332 + return new TimetableExcelData(this);
  333 + }
  334 + }
  335 +
  336 + public static ImportBuilder withImportBuilder() {
  337 + return new ImportBuilder();
  338 + }
  339 + public static class ImportBuilder {
  340 + private ImportBuilder() {}
  341 +
  342 + /** 导入的Excel文件路径 */
  343 + private String excelFilePath;
  344 + /** 导入的Excel sheet名字 */
  345 + private String excelSheetName;
  346 + /** 时刻表Id */
  347 + private Long ttInfoId;
  348 + /** 线路Id */
  349 + private Integer lineId;
  350 + /** 线路标准信息Id */
  351 + private Integer lineInfoId;
  352 + /** 线路名字 */
  353 + private String lineName;
  354 + /** 时刻表名字 */
  355 + private String ttInfoName;
  356 + /** 线路路由版本 */
  357 + private Integer lineRouteVersion;
  358 + /** 时刻表excel格式类型 */
  359 + private TimetableExcelFormatType timetableExcelFormatType;
  360 + /** 数据工具服务 */
  361 + private DataToolsService dataToolsService;
  362 + /** 配置数据导入导出用到的配置信息 */
  363 + private DataToolsProperties dataToolsProperties;
  364 + /** 时刻表excel导入策略 */
  365 + private TimetableExcelDataImportStrategy timetableExcelDataImportStrategy;
  366 +
  367 + public ImportBuilder setExcelFilePath(String excelFilePath) {
  368 + this.excelFilePath = excelFilePath;
  369 + return this;
  370 + }
  371 +
  372 + public ImportBuilder setExcelSheetName(String excelSheetName) {
  373 + this.excelSheetName = excelSheetName;
  374 + return this;
  375 + }
  376 +
  377 + public ImportBuilder setTtInfoId(Long ttInfoId) {
  378 + this.ttInfoId = ttInfoId;
  379 + return this;
  380 + }
  381 +
  382 + public ImportBuilder setLineId(Integer lineId) {
  383 + this.lineId = lineId;
  384 + return this;
  385 + }
  386 +
  387 + public ImportBuilder setLineInfoId(Integer lineInfoId) {
  388 + this.lineInfoId = lineInfoId;
  389 + return this;
  390 + }
  391 +
  392 + public ImportBuilder setLineName(String lineName) {
  393 + this.lineName = lineName;
  394 + return this;
  395 + }
  396 +
  397 + public ImportBuilder setTtInfoName(String ttInfoName) {
  398 + this.ttInfoName = ttInfoName;
  399 + return this;
  400 + }
  401 +
  402 + public ImportBuilder setLineRouteVersion(Integer lineRouteVersion) {
  403 + this.lineRouteVersion = lineRouteVersion;
  404 + return this;
  405 + }
  406 +
  407 + public ImportBuilder setTimetableExcelFormatType(TimetableExcelFormatType timetableExcelFormatType) {
  408 + this.timetableExcelFormatType = timetableExcelFormatType;
  409 + return this;
  410 + }
  411 +
  412 + public ImportBuilder setDataToolsService(DataToolsService dataToolsService) {
  413 + this.dataToolsService = dataToolsService;
  414 + return this;
  415 + }
  416 +
  417 + public ImportBuilder setDataToolsProperties(DataToolsProperties dataToolsProperties) {
  418 + this.dataToolsProperties = dataToolsProperties;
  419 + return this;
  420 + }
  421 +
  422 + public ImportBuilder setTimetableExcelDataImportStrategy(TimetableExcelDataImportStrategy timetableExcelDataImportStrategy) {
  423 + this.timetableExcelDataImportStrategy = timetableExcelDataImportStrategy;
  424 + return this;
  425 + }
  426 +
  427 + // ---------------- 内部生成的属性 ------------------ //
  428 + /** 待导入excel workbook对象 */
  429 + private Workbook excelWorkBook;
  430 + /** 待导入excel workbook工作区对象 */
  431 + private Sheet excelWorkBookSheet;
  432 + /** ktr转换所需参数对象 */
  433 + private Map<String, Object> ktrParams = new HashMap<>();
  434 +
  435 + public TimetableExcelData build() throws ScheduleException {
  436 + // 0、验证策略类
  437 + Assert.notNull(this.timetableExcelDataImportStrategy, "时刻表excel导入策略类为空!");
  438 +
  439 + // 注意:这里不做其他验证,业务上导入前必须验证的(调用验证用的builder)
  440 + File file = new File(this.excelFilePath);
  441 + DataToolsFile dataToolsFile = new DataToolsFile();
  442 + dataToolsFile.setFile(file);
  443 + if (DataToolsFileType.XLS.isThisType(file)) {
  444 + dataToolsFile.setFileType(DataToolsFileType.XLS);
  445 + } else if (DataToolsFileType.XLSX.isThisType(file)) {
  446 + dataToolsFile.setFileType(DataToolsFileType.XLSX);
  447 + }
  448 + this.excelWorkBook = dataToolsFile.getFileType().getWorkBook(dataToolsFile.getFile());
  449 + this.excelWorkBookSheet = this.excelWorkBook.getSheet(this.excelSheetName);
  450 +
  451 + // 设置ktr转换参数
  452 + this.ktrParams.put("erroroutputdir", this.dataToolsProperties.getTransErrordir()); // 错误文件输出路径
  453 + this.ktrParams.put("sheetname", this.excelSheetName); // sheet工作区的名字
  454 + this.ktrParams.put("lineinfoid", this.lineInfoId); // 线路标准id
  455 + this.ktrParams.put("xlname", this.lineName); // 线路名称
  456 + this.ktrParams.put("xlid", this.lineId); // 线路id
  457 + this.ktrParams.put("ttinfoname", this.ttInfoName); // 时刻表名称
  458 + this.ktrParams.put("ttid", this.ttInfoId.intValue()); // 时刻表id
  459 + this.ktrParams.put("lineversion", this.lineRouteVersion); // 站点路由版本
  460 +
  461 + return new TimetableExcelData(this);
  462 + }
  463 + }
  464 +
  465 +}
src/main/java/com/bsth/service/schedule/timetable/TimetableExcelFormatType.java 0 → 100644
  1 +package com.bsth.service.schedule.timetable;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonCreator;
  4 +import com.fasterxml.jackson.annotation.JsonValue;
  5 +import org.springframework.util.Assert;
  6 +
  7 +import java.util.HashMap;
  8 +import java.util.Map;
  9 +
  10 +/**
  11 + * 时刻表excel格式类型。
  12 + */
  13 +public enum TimetableExcelFormatType {
  14 + Normal("normal"), // 一般格式
  15 + NormalWithGs("normalWithGs"), // 一般格式(路牌列后加一列工时列)
  16 + Dynamic("dynamic"); // 自动生成时刻表的导出格式
  17 +
  18 + private static Map<String, TimetableExcelFormatType> descMapEnum = new HashMap<>();
  19 + static {
  20 + descMapEnum.put("normal", Normal);
  21 + descMapEnum.put("normalWithGs", NormalWithGs);
  22 + descMapEnum.put("dynamic", Dynamic);
  23 + }
  24 +
  25 + private String desc;
  26 + @JsonValue
  27 + public String getDesc() {
  28 + return desc;
  29 + }
  30 +
  31 + public void setDesc(String desc) {
  32 + this.desc = desc;
  33 + }
  34 +
  35 + @JsonCreator
  36 + TimetableExcelFormatType(String desc) {
  37 + this.desc = desc;
  38 + }
  39 +
  40 + public static TimetableExcelFormatType fromDesc(String desc) {
  41 + Assert.hasText(desc, "excel导入格式为空!");
  42 + Assert.notNull(descMapEnum.get(desc), "未知的excel导入格式[" + desc + "]!");
  43 + return descMapEnum.get(desc);
  44 + }
  45 +}
src/main/java/com/bsth/service/schedule/timetable/strategy/TimetableExcelDataImportStrategy.java 0 → 100644
  1 +package com.bsth.service.schedule.timetable.strategy;
  2 +
  3 +import com.bsth.service.schedule.exception.ScheduleException;
  4 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
  5 +import com.bsth.service.schedule.timetable.TimetableExcelData.TimetableExcelInternalCell;
  6 +import com.bsth.service.schedule.utils.DataToolsProperties;
  7 +import com.bsth.service.schedule.utils.DataToolsService;
  8 +import org.apache.poi.ss.usermodel.Sheet;
  9 +
  10 +import java.util.Map;
  11 +
  12 +/**
  13 + * 时刻表excel验证策略接口。
  14 + */
  15 +public interface TimetableExcelDataImportStrategy {
  16 + /**
  17 + * 导入excel时刻表。
  18 + * @param excelWorkBookSheet 待导入excel workbook 工作区对象
  19 + * @param excelFilePath 导入的Excel文件路径
  20 + * @param dataToolsService dataToolsService
  21 + * @param dataToolsProperties dataToolsProperties
  22 + * @param ktrParams ktr转换所需参数对象
  23 + * @param internalExcelCells 内部Excel单元格二维数组
  24 + * @param timetableExcelFormatType 时刻表excel格式
  25 + * @throws ScheduleException 导入异常
  26 + */
  27 + void doImport(
  28 + Sheet excelWorkBookSheet,
  29 + String excelFilePath,
  30 + DataToolsService dataToolsService,
  31 + DataToolsProperties dataToolsProperties,
  32 + Map<String, Object> ktrParams,
  33 + TimetableExcelInternalCell[][] internalExcelCells,
  34 + TimetableExcelFormatType timetableExcelFormatType
  35 + ) throws ScheduleException;
  36 +}
src/main/java/com/bsth/service/schedule/timetable/strategy/TimetableExcelDataValidateStrategy.java 0 → 100644
  1 +package com.bsth.service.schedule.timetable.strategy;
  2 +
  3 +import com.bsth.entity.Line;
  4 +import com.bsth.entity.LsStationRoute;
  5 +import com.bsth.entity.schedule.GuideboardInfo;
  6 +import com.bsth.service.schedule.exception.ScheduleException;
  7 +import com.bsth.service.schedule.timetable.TimetableExcelData.TimetableExcelInternalCell;
  8 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 时刻表excel验证策略接口。
  14 + */
  15 +public interface TimetableExcelDataValidateStrategy {
  16 + /**
  17 + * 验证excel时刻表。
  18 + * @param internalExcelCells 内部Excel单元格二维数组
  19 + * @param timetableExcelFormatType 时刻表excel格式
  20 + * @param line 线路信息
  21 + * @param lsStationRouteList 线路站点路由列表(包含上下行的起终点站)
  22 + * @param guideBoardInfoList 路牌列表
  23 + * @throws ScheduleException 验证异常
  24 + */
  25 + void doValidate(
  26 + TimetableExcelInternalCell[][] internalExcelCells,
  27 + TimetableExcelFormatType timetableExcelFormatType,
  28 + Line line,
  29 + List<LsStationRoute> lsStationRouteList,
  30 + List<GuideboardInfo> guideBoardInfoList
  31 + ) throws ScheduleException;
  32 +}
src/main/java/com/bsth/service/schedule/timetable/strategy/impl/TimetableExcelDataImportStrategyImpl.java 0 → 100644
  1 +package com.bsth.service.schedule.timetable.strategy.impl;
  2 +
  3 +import com.bsth.service.schedule.exception.ScheduleException;
  4 +import com.bsth.service.schedule.timetable.TimetableExcelData.TimetableExcelInternalCell;
  5 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
  6 +import com.bsth.service.schedule.timetable.strategy.TimetableExcelDataImportStrategy;
  7 +import com.bsth.service.schedule.utils.DataToolsProperties;
  8 +import com.bsth.service.schedule.utils.DataToolsService;
  9 +import jxl.write.Label;
  10 +import jxl.write.WritableSheet;
  11 +import jxl.write.WritableWorkbook;
  12 +import org.apache.commons.lang3.StringUtils;
  13 +import org.apache.poi.ss.usermodel.Sheet;
  14 +import org.slf4j.Logger;
  15 +import org.slf4j.LoggerFactory;
  16 +
  17 +import java.io.File;
  18 +import java.util.ArrayList;
  19 +import java.util.List;
  20 +import java.util.Map;
  21 +
  22 +/**
  23 + * 时刻表excel导入策略实现。
  24 + */
  25 +public class TimetableExcelDataImportStrategyImpl implements TimetableExcelDataImportStrategy {
  26 + /** 日志记录器 */
  27 + private final static Logger LOG = LoggerFactory.getLogger(TimetableExcelDataImportStrategyImpl.class);
  28 +
  29 + @Override
  30 + public void doImport(
  31 + Sheet excelWorkBookSheet,
  32 + String excelFilePath,
  33 + DataToolsService dataToolsService,
  34 + DataToolsProperties dataToolsProperties,
  35 + Map<String, Object> ktrParams,
  36 + TimetableExcelInternalCell[][] internalExcelCells,
  37 + TimetableExcelFormatType timetableExcelFormatType
  38 + ) throws ScheduleException {
  39 + // 注意:这里不做验证,业务上导入前必须验证的(调用验证用的builder)
  40 +
  41 + // 1、创建内部单元格数据
  42 + // 1-1、计算第一行,并设置单元格属性
  43 + for (int colNum = 0; colNum < internalExcelCells[0].length; colNum ++) {
  44 + TimetableExcelInternalCell cell = internalExcelCells[0][colNum];
  45 + cell.isHeadCell = true;
  46 +
  47 + // 2-1-1、第一行,第一列为路牌
  48 + if (colNum == 0) {
  49 + cell.isLpNameCell = true;
  50 + continue;
  51 + }
  52 + // 2-1-1-1、第一行,第二列可能是工时
  53 + if (colNum == 1 && timetableExcelFormatType == TimetableExcelFormatType.NormalWithGs) {
  54 + cell.isGsCell = true;
  55 + continue;
  56 + }
  57 +
  58 + // 2-1-2、如果导入格式是Dynamic,忽略指定列
  59 + if (timetableExcelFormatType == TimetableExcelFormatType.Dynamic) {
  60 + if ("报到".equals(cell.cellContent) ||
  61 + "到场".equals(cell.cellContent) ||
  62 + "离场".equals(cell.cellContent) ||
  63 + "总公里".equals(cell.cellContent) ||
  64 + "营业公里".equals(cell.cellContent) ||
  65 + "空驶公里".equals(cell.cellContent) ||
  66 + "总工时".equals(cell.cellContent) ||
  67 + "营业工时".equals(cell.cellContent) ||
  68 + "营运班次".equals(cell.cellContent)) {
  69 + // 这些列都忽略,不参与计算
  70 + cell.isEnable = false;
  71 + }
  72 + }
  73 +
  74 + }
  75 +
  76 + // 1-2、根据第一行的单元格验证后的设置的属性,设置其余行单元格的属性
  77 + for (int rowNum = 1; rowNum < internalExcelCells.length; rowNum ++) {
  78 + for (int colNum = 0; colNum < internalExcelCells[rowNum].length; colNum ++) {
  79 + TimetableExcelInternalCell cell = internalExcelCells[rowNum][colNum];
  80 + TimetableExcelInternalCell firstRowCell = internalExcelCells[0][colNum];
  81 + if (firstRowCell.isEnable) {
  82 + cell.isLpNameCell = firstRowCell.isLpNameCell;
  83 + cell.isGsCell = firstRowCell.isGsCell;
  84 + }
  85 + }
  86 + }
  87 +
  88 + // 2、重新构造一个新的单元格数组,去除enable=false的,根据类型合并路牌和工时
  89 + List<List<TimetableExcelInternalCell>> newEnabledExcelCells = new ArrayList<>();
  90 + for (int rowNum = 0; rowNum < internalExcelCells.length; rowNum ++) {
  91 + List<TimetableExcelInternalCell> newEnabledExcelRowCells = new ArrayList<>();
  92 + newEnabledExcelCells.add(newEnabledExcelRowCells);
  93 +
  94 + for (int colNum = 0; colNum < internalExcelCells[rowNum].length; colNum ++) {
  95 + TimetableExcelInternalCell cell = internalExcelCells[rowNum][colNum];
  96 + if (!cell.isEnable) {
  97 + continue;
  98 + }
  99 + if (cell.isGsCell) { // 如果匹配到工时单元格,需要合并到前一个单元格中
  100 + // 前一个单元格就是当前已经保存的行单元格列表的最后一个
  101 + TimetableExcelInternalCell preNewEnabledCell =
  102 + newEnabledExcelRowCells.get(newEnabledExcelRowCells.size() - 1);
  103 + // 合并成 路牌1->工时1 这种格式
  104 + preNewEnabledCell.cellContent = preNewEnabledCell.cellContent + "->" + cell.cellContent;
  105 + } else {
  106 + newEnabledExcelRowCells.add(cell);
  107 + }
  108 + }
  109 + }
  110 +
  111 + // 3、计算其他ktr参数
  112 + // 3-1、计算字段名相关参数
  113 + List<String> columnNames = new ArrayList<>();
  114 + for (int colNum = 0; colNum < newEnabledExcelCells.get(0).size(); colNum ++) {
  115 + TimetableExcelInternalCell cell = newEnabledExcelCells.get(0).get(colNum);
  116 + if (colNum == 0) {
  117 + columnNames.add(cell.cellContent);
  118 + } else {
  119 + columnNames.add(cell.cellContent + "->" + colNum);
  120 + }
  121 + }
  122 +
  123 + LOG.info("表头参数={}", StringUtils.join(columnNames.toArray(), ","));
  124 + ktrParams.put("excelfieldnames", StringUtils.join(columnNames.toArray(), ",")); // 时刻表excel输入字段名,以逗号连接
  125 + columnNames.remove(0);
  126 + ktrParams.put("normalizefieldnames", StringUtils.join(columnNames.toArray(), ",")); // 数据范式化字段名,以逗号连接
  127 +
  128 + // 3-2、计算excel内容文件参数
  129 + File fileCal = new File(excelFilePath + "_stringType.xls");
  130 + try {
  131 + WritableWorkbook writableWorkbook = jxl.Workbook.createWorkbook(fileCal);
  132 + WritableSheet sheet1 = writableWorkbook.createSheet(excelWorkBookSheet.getSheetName(), 0);
  133 + for (int rowNum = 0; rowNum < newEnabledExcelCells.size(); rowNum ++) {
  134 + for (int colNum = 0; colNum < newEnabledExcelCells.get(rowNum).size(); colNum ++) {
  135 + TimetableExcelInternalCell cell = newEnabledExcelCells.get(rowNum).get(colNum);
  136 + sheet1.addCell(new Label(colNum, rowNum, cell.cellContent));
  137 + }
  138 + }
  139 + writableWorkbook.write();
  140 + writableWorkbook.close();
  141 + ktrParams.put("filepath", fileCal.getAbsolutePath());
  142 + } catch (Exception exp) {
  143 + exp.printStackTrace();
  144 + throw new ScheduleException("导入时刻表异常!");
  145 + }
  146 +
  147 + // 3-3、计算ktr路径相关参数
  148 + try {
  149 + // 元数据ktr
  150 + File mktrFile = new File(this.getClass().getResource(
  151 + dataToolsProperties.getTtinfodetailMetadatainputktr()).toURI());
  152 + ktrParams.put("transpath", mktrFile.getAbsolutePath());
  153 +
  154 + // 实际数据ktr
  155 + if (timetableExcelFormatType == TimetableExcelFormatType.Normal) {
  156 + File normal_ktrFile = new File(this.getClass().getResource(
  157 + dataToolsProperties.getTtinfodetailDatainputktr2version()).toURI());
  158 + ktrParams.put("injectktrfile", normal_ktrFile.getAbsolutePath());
  159 + } else if (timetableExcelFormatType == TimetableExcelFormatType.NormalWithGs) {
  160 + File noramlwithgs_ktrFile = new File(this.getClass().getResource(
  161 + dataToolsProperties.getTtinfodetailDatainputktr2normalwithgs()).toURI());
  162 + ktrParams.put("injectktrfile", noramlwithgs_ktrFile.getAbsolutePath());
  163 + } else if (timetableExcelFormatType == TimetableExcelFormatType.Dynamic) {
  164 + File dynamic_ktrFile = new File(this.getClass().getResource(
  165 + dataToolsProperties.getTtinfodetailDatainputktr2version2()).toURI());
  166 + ktrParams.put("injectktrfile", dynamic_ktrFile.getAbsolutePath());
  167 + } else {
  168 + throw new ScheduleException("未知的TimetableExcelFormatType格式[" + timetableExcelFormatType + "]");
  169 + }
  170 +
  171 + } catch (Exception exp) {
  172 + exp.printStackTrace();
  173 + throw new ScheduleException("导入时刻表异常!");
  174 + }
  175 +
  176 + // 3-4、执行ktr
  177 + dataToolsService.importData(fileCal, ktrParams);
  178 + }
  179 +}
src/main/java/com/bsth/service/schedule/timetable/strategy/impl/TimetableExcelDataValidateStrategyImpl.java 0 → 100644
  1 +package com.bsth.service.schedule.timetable.strategy.impl;
  2 +
  3 +import com.bsth.entity.Line;
  4 +import com.bsth.entity.LsStationRoute;
  5 +import com.bsth.entity.schedule.GuideboardInfo;
  6 +import com.bsth.service.schedule.exception.ScheduleException;
  7 +import com.bsth.service.schedule.timetable.TimetableExcelFormatType;
  8 +import com.bsth.service.schedule.timetable.TimetableExcelData.TimetableExcelInternalCell;
  9 +import com.bsth.service.schedule.timetable.strategy.TimetableExcelDataValidateStrategy;
  10 +import org.apache.commons.lang3.StringUtils;
  11 +import org.springframework.util.CollectionUtils;
  12 +
  13 +import java.util.ArrayList;
  14 +import java.util.HashMap;
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +import java.util.regex.Matcher;
  18 +import java.util.regex.Pattern;
  19 +
  20 +/**
  21 + * 时刻表excel验证策略实现类。
  22 + */
  23 +public class TimetableExcelDataValidateStrategyImpl implements TimetableExcelDataValidateStrategy {
  24 + // 使用第一行单元格的属性设其他行单元格的属性
  25 + private void setInternalExcelCellPropertyWithFirstRowCell(TimetableExcelInternalCell[][] internalExcelCells) {
  26 + for (int rowNum = 1; rowNum < internalExcelCells.length; rowNum ++) {
  27 + for (int colNum = 0; colNum < internalExcelCells[rowNum].length; colNum ++) {
  28 + TimetableExcelInternalCell cell = internalExcelCells[rowNum][colNum];
  29 + TimetableExcelInternalCell firstRowCell = internalExcelCells[0][colNum];
  30 + if (firstRowCell.isEnable) {
  31 + cell.isBc = firstRowCell.isBc;
  32 + cell.isInBc = firstRowCell.isInBc;
  33 + cell.isOutBc = firstRowCell.isOutBc;
  34 +
  35 + cell.isLpNameCell = firstRowCell.isLpNameCell;
  36 + cell.isFcsjCell = firstRowCell.isFcsjCell;
  37 + cell.isGsCell = firstRowCell.isGsCell;
  38 + }
  39 + }
  40 + }
  41 + }
  42 +
  43 + // 验证路由名字cell
  44 + private void validateRouteContentCell(
  45 + int colNum,
  46 + String routeName,
  47 + Line line,
  48 + List<LsStationRoute> lsStationRouteList) throws ScheduleException {
  49 + if (StringUtils.isEmpty(routeName)) {
  50 + throw new ScheduleException(String.format("第1行,第%d列数据不能为空", colNum + 1));
  51 + }
  52 +
  53 + List<LsStationRoute> lsStationRoutes = new ArrayList<>();
  54 + for (LsStationRoute lsStationRoute : lsStationRouteList) {
  55 + if ("B".equals(lsStationRoute.getStationMark()) && routeName.equals(lsStationRoute.getStationName())) {
  56 + lsStationRoutes.add(lsStationRoute);
  57 + }
  58 + }
  59 +
  60 + if (CollectionUtils.isEmpty(lsStationRoutes)) {
  61 + throw new ScheduleException(String.format("第1行,第%d列数据%s在%s站点路由中不是起点站",
  62 + colNum + 1, routeName, line.getName()));
  63 + } else if (lsStationRoutes.size() > 1) {
  64 + throw new ScheduleException(String.format("第1行,第%d列数据%s在%s站点路由中上下行都是起点站",
  65 + colNum + 1, routeName, line.getName()));
  66 + } else if (StringUtils.isEmpty(lsStationRoutes.get(0).getStationCode())) {
  67 + throw new ScheduleException(String.format("第1行,第%d列数据%s在%s站点路由中没有站点编码",
  68 + colNum + 1, routeName, line.getName()));
  69 + }
  70 +
  71 + }
  72 +
  73 + // 验证路牌名字cell
  74 + private void validateGuideboardContentCell(
  75 + int rowNum,
  76 + String guideboardName,
  77 + Line line,
  78 + List<GuideboardInfo> guideboardInfoList) throws ScheduleException {
  79 + if (StringUtils.isEmpty(guideboardName)) {
  80 + throw new ScheduleException(String.format("第%d行,第1列路牌无数据", rowNum + 1));
  81 + }
  82 +
  83 + List<GuideboardInfo> guideboardInfos = new ArrayList<>();
  84 + for (GuideboardInfo guideboardInfo : guideboardInfoList) {
  85 + if (guideboardName.equals(guideboardInfo.getLpName())) {
  86 + guideboardInfos.add(guideboardInfo);
  87 + }
  88 + }
  89 +
  90 + if (CollectionUtils.isEmpty(guideboardInfos)) {
  91 + throw new ScheduleException(String.format("第%d行,第1列的路牌在%s中不存在",
  92 + rowNum + 1, line.getName()));
  93 + } else if (guideboardInfos.size() > 1) {
  94 + throw new ScheduleException(String.format("第%d行,第1列的路牌在%s中重复",
  95 + rowNum + 1, line.getName()));
  96 + }
  97 + }
  98 +
  99 + // Normal,NormalWithGs格式下的发车时间格式
  100 + private static Pattern p1 = Pattern.compile("^([01]?[0-9]|2[0-3]):[0-5][0-9]$"); // hh:mm格式
  101 + private static Pattern p2 = Pattern.compile("^([01]?[0-9]|2[0-3]),[0-5][0-9]$"); // hh,mm格式
  102 + private static Pattern p3 = Pattern.compile("^([01]?[0-9]|2[0-3])[0-5][0-9]$"); // hhmm格式
  103 + // Dynamic格式下的发车时间格式
  104 + private static Pattern p1_1 = Pattern.compile("^([\u62a5]|[\u51fa])?([01]?[0-9]|2[0-3]):[0-5][0-9]$"); // (报|出)hh:mm格式
  105 + private static Pattern p2_1 = Pattern.compile("^([01]?[0-9]|2[0-3]):[0-5][0-9]([X]|[\u203b])?$"); // hh:mm(X|※)格式
  106 + // 验证发车时间cell
  107 + private void validateFcsjContentCell(
  108 + int rowNum,
  109 + int colNum,
  110 + String fcsjContent, TimetableExcelFormatType timetableExcelFormatType) throws ScheduleException {
  111 + if (timetableExcelFormatType == TimetableExcelFormatType.Normal ||
  112 + timetableExcelFormatType == TimetableExcelFormatType.NormalWithGs) {
  113 + Matcher m1 = p1.matcher(fcsjContent.trim());
  114 + Matcher m2 = p2.matcher(fcsjContent.trim());
  115 + Matcher m3 = p3.matcher(fcsjContent.trim());
  116 + boolean expected = m1.matches() || m2.matches() || m3.matches();
  117 + if (!expected) {
  118 + throw new ScheduleException(String.format("第%d行,第%d列的发车时间格式不正确,格式应为hh:mm或hh,mm或hhmm",
  119 + rowNum + 1, colNum + 1));
  120 + }
  121 + } else if (timetableExcelFormatType == TimetableExcelFormatType.Dynamic) {
  122 + Matcher m1 = p1_1.matcher(fcsjContent.trim());
  123 + Matcher m2 = p2_1.matcher(fcsjContent.trim());
  124 + boolean expected = m1.matches() || m2.matches();
  125 + if (!expected) {
  126 + throw new ScheduleException(String.format(
  127 + "第%d行,第%d列的发车时间格式不正确,格式应为(报|出)hh:mm或hh:mm(X|※)",
  128 + rowNum + 1, colNum + 1));
  129 + }
  130 + } else {
  131 + throw new ScheduleException(String.format("未知的导入格式[%s]", timetableExcelFormatType.getDesc()));
  132 + }
  133 + }
  134 +
  135 + private static Pattern p5 = Pattern.compile("^[-\\+]?[.\\d]*$"); // 浮点数
  136 + // 验证工时cell
  137 + private void validateGsContentCell(int rowNum, int colNum, String gsContent) throws ScheduleException {
  138 + Matcher m1 = p5.matcher(gsContent.trim());
  139 + boolean expected = m1.matches();
  140 + if (!expected) {
  141 + throw new ScheduleException(String.format("第%d行,第%d列的工时格式不正确,格式应为整数或浮点数",
  142 + rowNum + 1, colNum + 1));
  143 + }
  144 + Double gs = new Double(gsContent.trim());
  145 + if (gs < 0) {
  146 + throw new ScheduleException(String.format("第%d行,第%d列的工时值必须大于0",
  147 + rowNum + 1, colNum + 1));
  148 + }
  149 + }
  150 +
  151 + /**
  152 + * 验证excel时刻表。
  153 + * @param internalExcelCells 内部Excel单元格二维数组
  154 + * @param timetableExcelFormatType 时刻表excel格式
  155 + * @param line 线路信息
  156 + * @param lsStationRouteList 线路站点路由列表(包含上下行的起终点站)
  157 + * @param guideBoardInfoList 路牌列表
  158 + * @throws ScheduleException 验证异常
  159 + */
  160 + @Override
  161 + public void doValidate(
  162 + TimetableExcelInternalCell[][] internalExcelCells,
  163 + TimetableExcelFormatType timetableExcelFormatType,
  164 + Line line,
  165 + List<LsStationRoute> lsStationRouteList,
  166 + List<GuideboardInfo> guideBoardInfoList) throws ScheduleException {
  167 + // 1、验证数据行,列
  168 + int rowCount = internalExcelCells.length;
  169 + int colCount = internalExcelCells[0].length;
  170 + if (rowCount <= 1 || colCount <= 1) {
  171 + throw new ScheduleException("工作区至少包含2行2列的数据");
  172 + }
  173 +
  174 + // 2、验证单元格信息
  175 + // 2-1、验证第1行数据(表头行数据)
  176 + for (int colNum = 0; colNum < colCount; colNum ++) {
  177 + TimetableExcelInternalCell cell = internalExcelCells[0][colNum];
  178 + cell.isHeadCell = true;
  179 +
  180 + // 2-1-1、第一行,第一列必须路牌2个字
  181 + if (colNum == 0) {
  182 + if (!"路牌".equals(cell.cellContent)) {
  183 + throw new ScheduleException("第1行,第1列数据必须是路牌2个字");
  184 + }
  185 + cell.isLpNameCell = true;
  186 + continue;
  187 + }
  188 + // 2-1-1-1、如果导入格式是NormalWithGs,第一行,第二列必须工时2个字
  189 + if (colNum == 1 && timetableExcelFormatType == TimetableExcelFormatType.NormalWithGs) {
  190 + if (!"工时".equals(cell.cellContent)) {
  191 + throw new ScheduleException("第1行,第2列数据必须是工时2个字");
  192 + }
  193 + cell.isGsCell = true;
  194 + continue;
  195 + }
  196 +
  197 + // 2-1-2、如果导入格式是Dynamic,忽略指定列
  198 + if (timetableExcelFormatType == TimetableExcelFormatType.Dynamic) {
  199 + if ("报到".equals(cell.cellContent) ||
  200 + "到场".equals(cell.cellContent) ||
  201 + "离场".equals(cell.cellContent) ||
  202 + "总公里".equals(cell.cellContent) ||
  203 + "营业公里".equals(cell.cellContent) ||
  204 + "空驶公里".equals(cell.cellContent) ||
  205 + "总工时".equals(cell.cellContent) ||
  206 + "营业工时".equals(cell.cellContent) ||
  207 + "营运班次".equals(cell.cellContent)) {
  208 + // 这些列都忽略,不参与计算
  209 + cell.isEnable = false;
  210 + continue;
  211 + }
  212 + }
  213 +
  214 + // 2-1-3、出场,进场班次,不验证路由
  215 + if ("出场".equals(cell.cellContent)) {
  216 + cell.isBc = true;
  217 + cell.isOutBc = true;
  218 + continue;
  219 + }
  220 + if ("进场".equals(cell.cellContent)) {
  221 + cell.isBc = true;
  222 + cell.isInBc = true;
  223 + continue;
  224 + }
  225 +
  226 + // 2-1-4、其他情况作为站点路由验证
  227 + cell.isBc = true;
  228 + cell.isFcsjCell = true;
  229 + this.validateRouteContentCell(colNum, cell.cellContent, line, lsStationRouteList); // 验证路由名字
  230 +
  231 + }
  232 +
  233 + // 2-2、根据第1行的单元格验证后的设置的属性,设置其余行单元格的属性
  234 + this.setInternalExcelCellPropertyWithFirstRowCell(internalExcelCells);
  235 +
  236 + // 2-3、验证具体路牌单元格(第1列)
  237 + Map<String, Integer> gbIndexMap = new HashMap<>(); // 记录每个路牌在第几行
  238 + for (int rowNum = 1; rowNum < rowCount; rowNum ++) {
  239 + TimetableExcelInternalCell cell = internalExcelCells[rowNum][0];
  240 + if (StringUtils.isEmpty(cell.cellContent)) {
  241 + throw new ScheduleException(String.format("第%d行,第1列路牌无数据", rowNum + 1));
  242 + } else if (gbIndexMap.get(cell.cellContent) != null) {
  243 + throw new ScheduleException(String.format("第%d行,第1列的路牌数据与第%d行,第1列数据重复",
  244 + rowNum + 1,
  245 + gbIndexMap.get(cell.cellContent)));
  246 + } else {
  247 + this.validateGuideboardContentCell(rowNum, cell.cellContent, line, guideBoardInfoList); // 验证路牌名字
  248 + gbIndexMap.put(cell.cellContent, rowNum + 1);
  249 + }
  250 + }
  251 +
  252 + // 2-4、验证其余单元格(第2行,第2列开始)
  253 + for (int rowNum = 1; rowNum < rowCount; rowNum ++) {
  254 + for (int colNum = 1; colNum < colCount; colNum ++) {
  255 + TimetableExcelInternalCell cell = internalExcelCells[rowNum][colNum];
  256 + if (!cell.isEnable) {
  257 + continue;
  258 + }
  259 +
  260 + if (cell.isBc) {
  261 + // 对应路牌对应单元格没有发车班次
  262 + if (StringUtils.isNotEmpty(cell.cellContent)) {
  263 + this.validateFcsjContentCell(rowNum, colNum, cell.cellContent, timetableExcelFormatType);
  264 + }
  265 + } else if (cell.isGsCell) {
  266 + if (StringUtils.isNotEmpty(cell.cellContent)) {
  267 + this.validateGsContentCell(rowNum, colNum, cell.cellContent);
  268 + }
  269 + } else {
  270 + throw new ScheduleException(String.format("第%d行,第%d列的单元格内容既不是发车时间,也不是工时!",
  271 + rowNum + 1, colNum + 1));
  272 + }
  273 + }
  274 + }
  275 + }
  276 +}
src/main/java/com/bsth/service/schedule/utils/DataToolsProperties.java
@@ -87,6 +87,9 @@ public class DataToolsProperties { @@ -87,6 +87,9 @@ public class DataToolsProperties {
87 /** 时刻表明细信息导入2(带版本),使用生成时刻表格式 */ 87 /** 时刻表明细信息导入2(带版本),使用生成时刻表格式 */
88 @NotNull 88 @NotNull
89 private String ttinfodetailDatainputktr2version2; 89 private String ttinfodetailDatainputktr2version2;
  90 + /** 时刻表明细信息导入2,一般格式(路牌列后加一列工时列)参看 TimetableExcelFormatType */
  91 + @NotNull
  92 + private String ttinfodetailDatainputktr2normalwithgs;
90 /** 排班规则信息导入 */ 93 /** 排班规则信息导入 */
91 @NotNull 94 @NotNull
92 private String scheduleruleDatainputktr; 95 private String scheduleruleDatainputktr;
@@ -373,6 +376,14 @@ public class DataToolsProperties { @@ -373,6 +376,14 @@ public class DataToolsProperties {
373 this.ttinfodetailDatainputktr2version2 = ttinfodetailDatainputktr2version2; 376 this.ttinfodetailDatainputktr2version2 = ttinfodetailDatainputktr2version2;
374 } 377 }
375 378
  379 + public String getTtinfodetailDatainputktr2normalwithgs() {
  380 + return ttinfodetailDatainputktr2normalwithgs;
  381 + }
  382 +
  383 + public void setTtinfodetailDatainputktr2normalwithgs(String ttinfodetailDatainputktr2normalwithgs) {
  384 + this.ttinfodetailDatainputktr2normalwithgs = ttinfodetailDatainputktr2normalwithgs;
  385 + }
  386 +
376 public String getVehicleDatasyncktr() { 387 public String getVehicleDatasyncktr() {
377 return vehicleDatasyncktr; 388 return vehicleDatasyncktr;
378 } 389 }
src/main/resources/datatools/config-cloud.properties
@@ -44,6 +44,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr @@ -44,6 +44,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr
44 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr 44 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr
45 # 时刻表明细信息导入2(版本化),使用生成时刻表格式 45 # 时刻表明细信息导入2(版本化),使用生成时刻表格式
46 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr 46 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr
  47 +# 时刻表明细信息导入2,一般格式(路牌列后加一列工时列)
  48 +datatools.ttinfodetail_datainputktr2normalwithgs=/datatools/ktrs/ttinfodetailDataInput2_normalwithgs.ktr
47 49
48 # 车辆配置信息导入 50 # 车辆配置信息导入
49 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr 51 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr
src/main/resources/datatools/config-dev.properties
@@ -43,6 +43,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr @@ -43,6 +43,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr
43 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr 43 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr
44 # 时刻表明细信息导入2(版本化),使用生成时刻表格式 44 # 时刻表明细信息导入2(版本化),使用生成时刻表格式
45 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr 45 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr
  46 +# 时刻表明细信息导入2,一般格式(路牌列后加一列工时列)
  47 +datatools.ttinfodetail_datainputktr2normalwithgs=/datatools/ktrs/ttinfodetailDataInput2_normalwithgs.ktr
46 48
47 # 车辆配置信息导入 49 # 车辆配置信息导入
48 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr 50 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr
src/main/resources/datatools/config-prod.properties
@@ -44,6 +44,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr @@ -44,6 +44,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr
44 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr 44 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr
45 # 时刻表明细信息导入2(版本化),使用生成时刻表格式 45 # 时刻表明细信息导入2(版本化),使用生成时刻表格式
46 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr 46 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr
  47 +# 时刻表明细信息导入2,一般格式(路牌列后加一列工时列)
  48 +datatools.ttinfodetail_datainputktr2normalwithgs=/datatools/ktrs/ttinfodetailDataInput2_normalwithgs.ktr
47 49
48 # 车辆配置信息导入 50 # 车辆配置信息导入
49 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr 51 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr
src/main/resources/datatools/config-test.properties
@@ -44,6 +44,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr @@ -44,6 +44,8 @@ datatools.ttinfodetail_datainputktr2=/datatools/ktrs/ttinfodetailDataInput2.ktr
44 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr 44 datatools.ttinfodetail_datainputktr2version=/datatools/ktrs/ttinfodetailDataInput2_version.ktr
45 # 时刻表明细信息导入2(版本化),使用生成时刻表格式 45 # 时刻表明细信息导入2(版本化),使用生成时刻表格式
46 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr 46 datatools.ttinfodetail_datainputktr2version2=/datatools/ktrs/ttinfodetailDataInput2_version_2.ktr
  47 +# 时刻表明细信息导入2,一般格式(路牌列后加一列工时列)
  48 +datatools.ttinfodetail_datainputktr2normalwithgs=/datatools/ktrs/ttinfodetailDataInput2_normalwithgs.ktr
47 49
48 # 车辆配置信息导入 50 # 车辆配置信息导入
49 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr 51 datatools.carsconfig_datainputktr=/datatools/ktrs/carsConfigDataInput.ktr