Commit 262a587dfecb9ff6e1052c79945ccbb33327696c

Authored by 娄高锋
2 parents beca79d5 f4154ee2

Merge branch 'pudong_jdk8' of 192.168.168.201:panzhaov5/bsth_control into pudong_jdk8

src/main/java/com/bsth/controller/schedule/core/legacy/EmployeeConfigInfoController.java
... ... @@ -61,13 +61,10 @@ public class EmployeeConfigInfoController extends BController<EmployeeConfigInfo
61 61 }
62 62  
63 63 @RequestMapping(value = "/validate_get_destroy_info", method = RequestMethod.GET)
64   - public Map<String, Object> validate_get_destroy_info(HttpServletRequest request) {
65   - HttpSession session = request.getSession();
66   - List<CompanyAuthority> cmyAuths = (List<CompanyAuthority>) session.getAttribute(Constants.COMPANY_AUTHORITYS);
67   -
  64 + public Map<String, Object> validate_get_destroy_info() {
68 65 Map<String, Object> rtn = new HashMap<>();
69 66 try {
70   - rtn.put("data", this.employeeConfigInfoService.validate_get_destroy_info(cmyAuths));
  67 + rtn.put("data", this.employeeConfigInfoService.validate_get_destory_info());
71 68 rtn.put("status", ResponseCode.SUCCESS);
72 69 } catch (Exception exp) {
73 70 rtn.put("status", ResponseCode.ERROR);
... ... @@ -77,21 +74,17 @@ public class EmployeeConfigInfoController extends BController&lt;EmployeeConfigInfo
77 74 return rtn;
78 75 }
79 76 @GetMapping(value = "/validate_get_destroy_info/download")
80   - public void exportValidateGetDestroyInfo(
81   - HttpServletRequest request,
82   - HttpServletResponse response) throws Exception {
  77 + public void exportValidateGetDestroyInfo(HttpServletResponse response) throws Exception {
83 78 // 流输出导出文件
84 79 response.setHeader("content-type", "application/octet-stream");
85   - response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("人员配置停用信息.txt", "UTF-8"));
  80 + response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("排班人员停用信息.txt", "UTF-8"));
86 81 response.setContentType("application/octet-stream");
87 82  
88 83 try (
89 84 OutputStream os = response.getOutputStream();
90 85 PrintWriter printWriter = new PrintWriter(os);
91 86 ) {
92   - HttpSession session = request.getSession();
93   - List<CompanyAuthority> cmyAuths = (List<CompanyAuthority>) session.getAttribute(Constants.COMPANY_AUTHORITYS);
94   - List<String> infos = this.employeeConfigInfoService.validate_get_destroy_info(cmyAuths);
  87 + List<String> infos = this.employeeConfigInfoService.validate_get_destory_info();
95 88 for (String info : infos) {
96 89 printWriter.println(info);
97 90 }
... ...
src/main/java/com/bsth/controller/schedule/core/legacy/TTInfoDetailController.java
... ... @@ -10,6 +10,7 @@ import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
10 10 import com.bsth.service.schedule.timetable.ExcelFormatType;
11 11 import com.bsth.service.schedule.utils.DataToolsFile;
12 12 import com.bsth.service.schedule.utils.DataToolsFileType;
  13 +import com.bsth.service.schedule.utils.MyHttpUtils;
13 14 import org.springframework.beans.factory.annotation.Autowired;
14 15 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
15 16 import org.springframework.web.bind.annotation.*;
... ... @@ -118,12 +119,12 @@ public class TTInfoDetailController extends BController&lt;TTInfoDetail, Long&gt; {
118 119 }
119 120 return rtn;
120 121 }
121   -
  122 +
122 123 /**
123 124 * 时刻表明细批量插入
124   - *
  125 + *
125 126 * @param entities
126   - *
  127 + *
127 128 * @return
128 129 */
129 130 @RequestMapping(value = "/skbDetailMxSave" ,method = RequestMethod.POST)
... ... @@ -131,6 +132,11 @@ public class TTInfoDetailController extends BController&lt;TTInfoDetail, Long&gt; {
131 132 return ttInfoDetailService.skbDetailMxSave(entities);
132 133 }
133 134  
  135 + @GetMapping(value = "/exportPvInfo/{id}")
  136 + public void exportPvInfo(@PathVariable("id") Long ttInfoId, HttpServletResponse response) throws Exception {
  137 + DataToolsFile dataToolsFile = this.ttInfoDetailService.exportPvInfo(ttInfoId);
  138 + MyHttpUtils.responseStreamFile(response, dataToolsFile.getFile());
  139 + }
134 140  
135 141 @RequestMapping(value = "/exportDTDFile/{type}", method = RequestMethod.POST)
136 142 public void exportFile(
... ...
src/main/java/com/bsth/controller/schedule/datasync/VehicleDataSyncController.java
... ... @@ -6,13 +6,12 @@ import com.bsth.controller.schedule.datasync.request.VehicleDataSyncTaskRequest;
6 6 import com.bsth.entity.schedule.datasync.VehicleDataSyncTask;
7 7 import com.bsth.entity.schedule.datasync.VehicleDataSyncTaskTypeEnum;
8 8 import com.bsth.service.schedule.datasync.VehicleDataSyncTaskService;
9   -import com.bsth.service.schedule.utils.MyStringUtils;
  9 +import com.bsth.service.schedule.utils.MyHttpUtils;
10 10 import org.springframework.beans.factory.annotation.Autowired;
11 11 import org.springframework.web.bind.annotation.*;
12 12  
13 13 import javax.servlet.http.HttpServletResponse;
14   -import java.io.*;
15   -import java.net.URLEncoder;
  14 +import java.io.File;
16 15 import java.util.Date;
17 16  
18 17 @RestController
... ... @@ -107,38 +106,11 @@ public class VehicleDataSyncController extends BController&lt;VehicleDataSyncTask,
107 106 }
108 107  
109 108 try {
110   - responseStreamFile(response, file);
  109 + MyHttpUtils.responseStreamFile(response, file);
111 110 } catch (Exception exp) {
112 111 exp.printStackTrace();
113 112 throw new RuntimeException("获取同步日志文件错误:" + exp.getMessage());
114 113 }
115 114 }
116 115  
117   - // 流输出文件
118   - private void responseStreamFile(HttpServletResponse response, File file) throws IOException {
119   - // 流输出导出文件
120   - response.setHeader("content-type", "application/octet-stream");
121   - String fileName = file.getName();
122   - if (MyStringUtils.isContainChinese(fileName)) {
123   - response.setHeader("Content-Disposition", "attachment; filename*=" + URLEncoder.encode(fileName, "UTF-8"));
124   - } else {
125   - response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
126   - }
127   - response.setContentType("application/octet-stream");
128   -
129   - try (
130   - OutputStream os = response.getOutputStream();
131   - BufferedOutputStream bos = new BufferedOutputStream(os);
132   - InputStream is = new FileInputStream(file);
133   - BufferedInputStream bis = new BufferedInputStream(is)
134   - ) {
135   - int length;
136   - byte[] temp = new byte[1024 * 10];
137   - while ((length = bis.read(temp)) != -1) {
138   - bos.write(temp, 0, length);
139   - }
140   - bos.flush();
141   - }
142   - }
143   -
144 116 }
... ...
src/main/java/com/bsth/service/schedule/EmployeeConfigInfoService.java
... ... @@ -30,8 +30,8 @@ public interface EmployeeConfigInfoService extends BService&lt;EmployeeConfigInfo,
30 30 void validate_jsy_destroy(EmployeeConfigInfo employeeConfigInfo) throws ScheduleException;
31 31 // 验证售票员是否停用
32 32 void validate_spy_destroy(EmployeeConfigInfo employeeConfigInfo) throws ScheduleException;
33   - // 获取线路人员配置停用信息描述
34   - List<String> validate_get_destroy_info(List<CompanyAuthority> companyAuthorityList);
  33 + // 获取人员停用信息(使用排班信息辅助判定)
  34 + List<String> validate_get_destory_info();
35 35  
36 36 void toggleCancel(Long id) throws ScheduleException;
37 37 Long getMaxDbbm(Integer xlId);
... ...
src/main/java/com/bsth/service/schedule/TTInfoDetailService.java
... ... @@ -34,6 +34,15 @@ public interface TTInfoDetailService extends BService&lt;TTInfoDetail, Long&gt; {
34 34 DataToolsFile exportDynamicTTinfo(TTinfoDetailDynamicData.DTInfos dtInfos, DataToolsFileType type) throws ScheduleException;
35 35  
36 36 /**
  37 + * 导出时刻表预览视图信息。
  38 + * @param ttInfoId 时刻表Id
  39 + * @return
  40 + * @throws ScheduleException
  41 + */
  42 + DataToolsFile exportPvInfo(Long ttInfoId) throws ScheduleException;
  43 +
  44 +
  45 + /**
37 46 * 获取时刻表最大发车顺序号
38 47 * @param xlid 线路id
39 48 * @param ttinfoid 时刻表id
... ...
src/main/java/com/bsth/service/schedule/impl/EmployeeConfigInfoServiceImpl.java
... ... @@ -4,6 +4,7 @@ import com.bsth.entity.Personnel;
4 4 import com.bsth.entity.schedule.EmployeeConfigInfo;
5 5 import com.bsth.entity.schedule.rule.ScheduleRule1Flat;
6 6 import com.bsth.entity.sys.CompanyAuthority;
  7 +import com.bsth.entity.sys.Module;
7 8 import com.bsth.repository.PersonnelRepository;
8 9 import com.bsth.service.schedule.EmployeeConfigInfoService;
9 10 import com.bsth.service.schedule.EmployeeService;
... ... @@ -11,11 +12,15 @@ import com.bsth.service.schedule.ScheduleRule1FlatService;
11 12 import com.bsth.service.schedule.exception.ScheduleException;
12 13 import com.bsth.service.schedule.utils.DataToolsFile;
13 14 import com.bsth.service.schedule.utils.DataToolsService;
  15 +import com.bsth.service.sys.ModuleService;
  16 +import com.bsth.util.DateUtils;
  17 +import org.apache.commons.lang3.time.DateFormatUtils;
14 18 import org.springframework.beans.factory.annotation.Autowired;
15 19 import org.springframework.beans.factory.annotation.Qualifier;
16 20 import org.springframework.dao.DataAccessException;
17 21 import org.springframework.jdbc.core.JdbcTemplate;
18 22 import org.springframework.jdbc.core.ResultSetExtractor;
  23 +import org.springframework.jdbc.core.RowMapper;
19 24 import org.springframework.stereotype.Service;
20 25 import org.springframework.transaction.annotation.Transactional;
21 26 import org.springframework.util.CollectionUtils;
... ... @@ -277,51 +282,54 @@ public class EmployeeConfigInfoServiceImpl extends BServiceImpl&lt;EmployeeConfigIn
277 282 }
278 283 }
279 284  
  285 + @Autowired
  286 + private ModuleService moduleService;
280 287 @Transactional
281 288 @Override
282   - public List<String> validate_get_destroy_info(List<CompanyAuthority> companyAuthorityList) {
283   - // 获取公司分公司权限代码
284   - List<String> gs_fgs_dms = new ArrayList<>();
285   - for (CompanyAuthority companyAuthority : companyAuthorityList) {
286   - gs_fgs_dms.add(companyAuthority.getCompanyCode() + "_" + companyAuthority.getSubCompanyCode());
287   - }
288   -
289   - // 查询所有人员配置,不用in操作符,n+1查询慢,程序过滤
290   - Map<String, Object> params = new HashMap<>();
291   - List<EmployeeConfigInfo> employeeConfigInfoList_all = (List<EmployeeConfigInfo>) this.list(params);
292   - List<EmployeeConfigInfo> employeeConfigInfoList = new ArrayList<>();
293   - for (EmployeeConfigInfo employeeConfigInfo : employeeConfigInfoList_all) {
294   - if (gs_fgs_dms.contains(employeeConfigInfo.getXl().getCgsbm())) {
295   - employeeConfigInfoList.add(employeeConfigInfo);
  289 + public List<String> validate_get_destory_info() {
  290 + // 1、查找当前用户是否有运营计划管理,没有的话不分析是否有停用人鱼信息
  291 + List<Module> moduleList = this.moduleService.findByCurrentUser();
  292 + boolean hasPlanModule = false;
  293 + for (Module module : moduleList) {
  294 + if ("运营计划管理".equals(module.getName())) {
  295 + hasPlanModule = true;
  296 + break;
296 297 }
297 298 }
  299 + if (!hasPlanModule) {
  300 + return null;
  301 + }
298 302  
299   - // 停用信息
300   - List<String> destroy_infos = new ArrayList<>();
301   - String info_format = "线路[%s]中人员配置有停用人员,请处理!";
302   - String info = "";
303   - Integer xlId = null;
304   - for (EmployeeConfigInfo employeeConfigInfo : employeeConfigInfoList) {
305   - if (employeeConfigInfo.getJsy() != null &&
306   - employeeConfigInfo.getJsy().getDestroy() != null &&
307   - employeeConfigInfo.getJsy().getDestroy() == 1) { // 驾驶员判定是否停用
308   - info = String.format(info_format, employeeConfigInfo.getXl().getName());
309   - if (!destroy_infos.contains(info)) {
310   - destroy_infos.add(info);
311   - }
312   - }
313   -
314   - if (employeeConfigInfo.getSpy() != null &&
315   - employeeConfigInfo.getSpy().getDestroy() != null &&
316   - employeeConfigInfo.getSpy().getDestroy() == 1) {
317   - info = String.format(info_format, employeeConfigInfo.getXl().getName());
318   - if (!destroy_infos.contains(info)) {
319   - destroy_infos.add(info);
320   - }
  303 + // 2、计算从当前时间开始的排班计划中是否有停用人员
  304 + String sql =
  305 + "select distinct " +
  306 + "pinfo.xl_name xlName " +
  307 + ", pinfo.schedule_date scheduleDate " +
  308 + "from " +
  309 + "(" +
  310 + "select plan.xl_name, plan.schedule_date " +
  311 + "from bsth_c_s_sp_info plan " +
  312 + "left join bsth_c_personnel jsy on plan.j = jsy.id " +
  313 + "left join bsth_c_personnel spy on plan.s = spy.id " +
  314 + "where schedule_date >= ? " +
  315 + "and (jsy.destroy = 1 || spy.destroy = 1) " +
  316 + "order by plan.xl_name asc, plan.schedule_date asc " +
  317 + ") pinfo " +
  318 + "group by pinfo.xl_name, pinfo.schedule_date ";
  319 +
  320 + Date currentDate = new Date(DateUtils.getTimestamp());
  321 + System.out.println(currentDate);
  322 + String info_format = "线路[%s][%s]排班中有人员已经停用,请及时处理!";
  323 + List<String> infoList = this.jdbcTemplate.query(sql, new Object[] {currentDate}, new RowMapper<String>() {
  324 + @Override
  325 + public String mapRow(ResultSet resultSet, int i) throws SQLException {
  326 + String xlName = resultSet.getString("xlName");
  327 + Date scheduleDate = new Date(resultSet.getDate("scheduleDate").getTime());
  328 + return String.format(info_format, xlName, DateFormatUtils.format(scheduleDate, "yyyy年MM月dd日"));
321 329 }
322   - }
  330 + });
323 331  
324   - return destroy_infos;
  332 + return infoList;
325 333 }
326 334  
327 335 @Transactional
... ...
src/main/java/com/bsth/service/schedule/impl/TTInfoDetailServiceImpl.java
... ... @@ -3,8 +3,11 @@ package com.bsth.service.schedule.impl;
3 3 import com.alibaba.fastjson.JSONArray;
4 4 import com.alibaba.fastjson.JSONObject;
5 5 import com.bsth.common.ResponseCode;
6   -import com.bsth.entity.*;
  6 +import com.bsth.entity.CarPark;
  7 +import com.bsth.entity.Line;
  8 +import com.bsth.entity.LineInformation;
7 9 import com.bsth.entity.schedule.GuideboardInfo;
  10 +import com.bsth.entity.schedule.TTInfo;
8 11 import com.bsth.entity.schedule.TTInfoDetail;
9 12 import com.bsth.repository.CarParkRepository;
10 13 import com.bsth.repository.LineRepository;
... ... @@ -19,20 +22,20 @@ import com.bsth.service.LineService;
19 22 import com.bsth.service.StationRouteService;
20 23 import com.bsth.service.schedule.GuideboardInfoService;
21 24 import com.bsth.service.schedule.TTInfoDetailService;
  25 +import com.bsth.service.schedule.datatools.Excel2007PoiOperator;
  26 +import com.bsth.service.schedule.datatools.ExcelPoiOperator;
22 27 import com.bsth.service.schedule.datatools.TTInfoDetailForEdit;
23 28 import com.bsth.service.schedule.datatools.TTinfoDetailDynamicData;
24 29 import com.bsth.service.schedule.exception.ScheduleException;
25 30 import com.bsth.service.schedule.timetable.ExcelData;
26 31 import com.bsth.service.schedule.timetable.ExcelFormatType;
27   -import com.bsth.service.schedule.utils.DataToolsFile;
28   -import com.bsth.service.schedule.utils.DataToolsFileType;
29   -import com.bsth.service.schedule.utils.DataToolsService;
30   -import com.bsth.service.schedule.utils.PoiUtils;
  32 +import com.bsth.service.schedule.utils.*;
31 33 import org.apache.commons.lang3.StringUtils;
32   -import org.apache.poi.ss.usermodel.Cell;
33   -import org.apache.poi.ss.usermodel.Row;
34   -import org.apache.poi.ss.usermodel.Sheet;
35   -import org.apache.poi.ss.usermodel.Workbook;
  34 +import org.apache.commons.lang3.time.DateFormatUtils;
  35 +import org.apache.poi.ss.usermodel.*;
  36 +import org.apache.poi.ss.util.CellRangeAddress;
  37 +import org.apache.poi.xssf.usermodel.XSSFCell;
  38 +import org.joda.time.DateTime;
36 39 import org.slf4j.Logger;
37 40 import org.slf4j.LoggerFactory;
38 41 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -42,13 +45,10 @@ import org.springframework.stereotype.Service;
42 45 import org.springframework.transaction.annotation.Transactional;
43 46 import org.springframework.util.CollectionUtils;
44 47  
  48 +import java.awt.Color;
45 49 import java.io.File;
46   -import java.util.ArrayList;
47   -import java.util.HashMap;
  50 +import java.util.*;
48 51 import java.util.List;
49   -import java.util.Map;
50   -import java.util.regex.Matcher;
51   -import java.util.regex.Pattern;
52 52  
53 53 /**
54 54 * Created by xu on 17/1/3.
... ... @@ -149,6 +149,192 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
149 149 return tTinfoDetailDynamicData.exportDynamicTTinfo(dtInfos, type);
150 150 }
151 151  
  152 + @Autowired
  153 + private DataToolsProperties dataToolsProperties;
  154 +
  155 + @Transactional
  156 + @Override
  157 + public DataToolsFile exportPvInfo(Long ttInfoId) throws ScheduleException {
  158 + // 1、获取时刻表,时刻表明细数据
  159 + TTInfo ttInfo = this.infoRepository.findOneExtend(ttInfoId);
  160 + List<TTInfoDetail> ttInfoDetailList = this.ttInfoDetailRepository.findByTtinfoId(ttInfoId);
  161 + LOGGER.info("----------------- 开始导出时刻表[{}]预览视图信息---------------", ttInfo.getName());
  162 +
  163 + // 2、构造导出信息
  164 + try {
  165 + // 使用excel2007格式(xlsx)
  166 + ExcelPoiOperator excelPoiOperator = new Excel2007PoiOperator();
  167 + Workbook wb = excelPoiOperator.createWorkBook(); // 创建workbook
  168 + Sheet sheet = excelPoiOperator.createWorkBookSheet(wb, "预览信息"); // 创建sheet
  169 +
  170 + // 创建表头(从第2行开始,第1行需要合并单元格显示站点名字)
  171 + int[] headColNums = new int[] {0, 1, 2, 3, 4, 7, 8, 9, 10, 11};
  172 + String[] headColLabels = new String[] {"序号", "路牌", "发车时间", "到达时间", "备注", "序号", "路牌", "发车时间", "到达时间", "备注"};
  173 + int[] headColWidth = new int[] {10, 10, 20, 20, 35, 10, 10, 20, 20, 35};
  174 +
  175 + Row headRow = excelPoiOperator.createSheetRow(sheet, 1);
  176 + headRow.setHeight((short) (35 * 20)); // 单位:1/20个点
  177 + for (int i = 0; i < headColNums.length; i ++) {
  178 + excelPoiOperator.createCell(
  179 + wb, headRow, (short) headColNums[i],
  180 + headColLabels[i], XSSFCell.CELL_TYPE_STRING,
  181 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  182 + BorderStyle.THIN, new java.awt.Color(0x000000),
  183 + (short) 14, new java.awt.Color(0xffffff), "宋体",
  184 + new Color(0x857F7F), FillPatternType.SOLID_FOREGROUND);
  185 + sheet.setColumnWidth(headColNums[i], headColWidth[i] * 256); // 单位:1/256个字符宽度
  186 + }
  187 +
  188 + // 获取上行线路并按照时间排序
  189 + List<TTInfoDetail> upBcList = sortedByBcsjAsc(ttInfoDetailList, true);
  190 + List<TTInfoDetail> downBcList = sortedByBcsjAsc(ttInfoDetailList, false);
  191 + int rowDiff = upBcList.size() - downBcList.size();
  192 + int rowSize;
  193 + if (rowDiff >= 0) { // 上行班次多
  194 + rowSize = downBcList.size();
  195 + } else { // 下行班次多
  196 + rowSize = upBcList.size();
  197 + }
  198 + for (int i = 0; i < rowSize; i++) {
  199 + Row bcRow = excelPoiOperator.createSheetRow(sheet, i + 2);
  200 + // 上行班次
  201 + excelPoiOperator.createIntegerCell(wb, bcRow, (short) 0, i + 1);
  202 + String lpName = upBcList.get(i).getLp().getLpName();
  203 + if (StringUtils.isNumeric(lpName)) {
  204 + excelPoiOperator.createIntegerCell(wb, bcRow, (short) 1, Integer.valueOf(lpName));
  205 + } else {
  206 + excelPoiOperator.createStringCell(wb, bcRow, (short) 1, lpName);
  207 + }
  208 + excelPoiOperator.createStringCell(wb, bcRow, (short) 2, upBcList.get(i).getFcsj());
  209 + Date ddsj_up = MyDateUtils.hhssTimePlusMinunits(upBcList.get(i).getFcsj(), upBcList.get(i).getBcsj(), 0);
  210 + excelPoiOperator.createStringCell(wb, bcRow, (short) 3, DateFormatUtils.format(ddsj_up, "HH:mm"));
  211 + excelPoiOperator.createStringCell(wb, bcRow, (short) 4, StringUtils.trimToEmpty(upBcList.get(i).getRemark()));
  212 +
  213 + // 下行班次
  214 + excelPoiOperator.createIntegerCell(wb, bcRow, (short) 7, i + 1);
  215 + lpName = downBcList.get(i).getLp().getLpName();
  216 + if (StringUtils.isNumeric(lpName)) {
  217 + excelPoiOperator.createIntegerCell(wb, bcRow, (short) 8, Integer.valueOf(lpName));
  218 + } else {
  219 + excelPoiOperator.createStringCell(wb, bcRow, (short) 8, lpName);
  220 + }
  221 + excelPoiOperator.createStringCell(wb, bcRow, (short) 9, downBcList.get(i).getFcsj());
  222 + Date ddsj_down = MyDateUtils.hhssTimePlusMinunits(downBcList.get(i).getFcsj(), downBcList.get(i).getBcsj(), 0);
  223 + excelPoiOperator.createStringCell(wb, bcRow, (short) 10, DateFormatUtils.format(ddsj_down, "HH:mm"));
  224 + excelPoiOperator.createStringCell(wb, bcRow, (short) 11, StringUtils.trimToEmpty(downBcList.get(i).getRemark()));
  225 + }
  226 +
  227 + List<TTInfoDetail> rowDiffBcList; // 剩下的班次
  228 + int rowDiffColIndexStart;
  229 + if (rowDiff >= 0) { // 上行班次多
  230 + rowDiffBcList = upBcList;
  231 + rowDiffColIndexStart = 0;
  232 + } else { // 下行班次多
  233 + rowDiffBcList = downBcList;
  234 + rowDiffColIndexStart = 7;
  235 + }
  236 + for (int i = rowSize; i < rowSize + Math.abs(rowDiff); i++) {
  237 + Row bcRow = excelPoiOperator.createSheetRow(sheet, i + 2);
  238 + excelPoiOperator.createIntegerCell(wb, bcRow, (short) (rowDiffColIndexStart + 0), i + 1);
  239 + String lpName = rowDiffBcList.get(i).getLp().getLpName();
  240 + if (StringUtils.isNumeric(lpName)) {
  241 + excelPoiOperator.createIntegerCell(wb, bcRow, (short) (rowDiffColIndexStart + 1), Integer.valueOf(lpName));
  242 + } else {
  243 + excelPoiOperator.createStringCell(wb, bcRow, (short) (rowDiffColIndexStart + 1), lpName);
  244 + }
  245 + excelPoiOperator.createStringCell(wb, bcRow, (short) (rowDiffColIndexStart + 2), rowDiffBcList.get(i).getFcsj());
  246 + Date ddsj = MyDateUtils.hhssTimePlusMinunits(rowDiffBcList.get(i).getFcsj(), rowDiffBcList.get(i).getBcsj(), 0);
  247 + excelPoiOperator.createStringCell(wb, bcRow, (short) (rowDiffColIndexStart + 3), DateFormatUtils.format(ddsj, "HH:mm"));
  248 + excelPoiOperator.createStringCell(wb, bcRow, (short) (rowDiffColIndexStart + 4), StringUtils.trimToEmpty(rowDiffBcList.get(i).getRemark()));
  249 +
  250 + }
  251 +
  252 + // 创建第一行,合并列
  253 + sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 4));
  254 + sheet.addMergedRegion(new CellRangeAddress(0, 0, 7, 11));
  255 + Row firstRow = excelPoiOperator.createSheetRow(sheet, 0);
  256 + firstRow.setHeight((short) (50 * 20)); // 单位:1/20个点
  257 + if (upBcList.size() > 0 && downBcList.size() > 0) {
  258 + String upBcLabel = "";
  259 + for (TTInfoDetail ttInfoDetail : upBcList) {
  260 + if ("normal".equals(ttInfoDetail.getBcType())) {
  261 + upBcLabel = "上行站点:" + ttInfoDetail.getQdzName() + " >> " + ttInfoDetail.getZdzName();
  262 + break;
  263 + }
  264 + }
  265 + String downBcLabel = "";
  266 + for (TTInfoDetail ttInfoDetail : downBcList) {
  267 + if ("normal".equals(ttInfoDetail.getBcType())) {
  268 + downBcLabel = "下行站点:" + ttInfoDetail.getQdzName() + " >> " + ttInfoDetail.getZdzName();
  269 + break;
  270 + }
  271 + }
  272 +
  273 + excelPoiOperator.createCell(
  274 + wb, firstRow, (short) 0,
  275 + upBcLabel, XSSFCell.CELL_TYPE_STRING,
  276 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  277 + BorderStyle.NONE, new java.awt.Color(0x000000),
  278 + (short) 20, new java.awt.Color(0xffffff), "宋体",
  279 + new Color(0x857F7F), FillPatternType.SOLID_FOREGROUND);
  280 +
  281 + excelPoiOperator.createCell(
  282 + wb, firstRow, (short) 7,
  283 + downBcLabel, XSSFCell.CELL_TYPE_STRING,
  284 + HorizontalAlignment.CENTER, VerticalAlignment.CENTER,
  285 + BorderStyle.NONE, new java.awt.Color(0x000000),
  286 + (short) 20, new java.awt.Color(0xffffff), "宋体",
  287 + new Color(0x857F7F), FillPatternType.SOLID_FOREGROUND);
  288 + }
  289 +
  290 + // 锁定第1第2行
  291 + sheet.createFreezePane(0, 2);
  292 +
  293 + // wb内存写入文件
  294 + String filepath = dataToolsProperties.getFileoutputDir() +
  295 + File.separator +
  296 + ttInfo.getName() + "预览信息-" +
  297 + new DateTime().toString("yyyyMMddHHmmss") + ".xlsx";
  298 + File file = new File(filepath);
  299 + excelPoiOperator.writeExcel(file, wb);
  300 +
  301 + DataToolsFile dataToolsFile = new DataToolsFile();
  302 + dataToolsFile.setFileType(DataToolsFileType.XLSX);
  303 + dataToolsFile.setFile(file);
  304 +
  305 + return dataToolsFile;
  306 +
  307 + } catch (Exception exp) {
  308 + LOGGER.error("----------------- 导出时刻表[{}]预览视图信息失败---------------", ttInfo.getName());
  309 + throw new ScheduleException(exp);
  310 + }
  311 + }
  312 + private List<TTInfoDetail> sortedByBcsjAsc(List<TTInfoDetail> bcList, boolean isUp) {
  313 + List<TTInfoDetail> sortedList = new ArrayList<>();
  314 + for (TTInfoDetail ttInfoDetail : bcList) {
  315 + if (isUp) {
  316 + if ("0".equals(ttInfoDetail.getXlDir())) {
  317 + sortedList.add(ttInfoDetail);
  318 + }
  319 + } else {
  320 + if ("1".equals(ttInfoDetail.getXlDir())) {
  321 + sortedList.add(ttInfoDetail);
  322 + }
  323 + }
  324 + }
  325 + Collections.sort(sortedList, new Comparator<TTInfoDetail>() {
  326 + @Override
  327 + public int compare(TTInfoDetail o1, TTInfoDetail o2) {
  328 + Date d1 = MyDateUtils.hhssTimePlusMinunits(o1.getFcsj(), 0, 0);
  329 + Date d2 = MyDateUtils.hhssTimePlusMinunits(o2.getFcsj(), 0, 0);
  330 +
  331 + return d1.compareTo(d2);
  332 + }
  333 + });
  334 +
  335 + return sortedList;
  336 + }
  337 +
152 338 @Override
153 339 public TTInfoDetailForEdit.EditInfo getEditInfo(Integer xlid, Long ttid, Long maxfcno) throws ScheduleException {
154 340 return ttInfoDetailForEdit.getEditInfo(xlid, ttid, maxfcno);
... ... @@ -225,11 +411,11 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
225 411  
226 412 /**
227 413 * @description (TODO) 时刻表明细模型数据保存.
228   - *
  414 + *
229 415 * @param map
230   - *
  416 + *
231 417 * @return : 返回保存操作后的状态.
232   - *
  418 + *
233 419 * @exception 处理所有抛出来的异常.
234 420 * */
235 421 @Transactional
... ... @@ -241,7 +427,7 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
241 427 //boolean b = map.get("istidc") ==null ? false : Boolean.parseBoolean(map.get("istidc").toString());
242 428 Long ttinfoid = map.get("skb") ==null ? null : Long.parseLong(map.get("skb").toString());
243 429 Integer xlid = map.get("xl") ==null ? null : Integer.parseInt(map.get("xl").toString());
244   - if(xlid !=null && ttinfoid !=null)
  430 + if(xlid !=null && ttinfoid !=null)
245 431 ttInfoDetailRepository.deltidc(xlid,ttinfoid);
246 432 if(d!=null)
247 433 ttInfoDetailRepository.saveAll(jsonArrayToListEntity(d));// 2、保存.
... ... @@ -252,14 +438,14 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
252 438 rs_m.put("status", ResponseCode.SUCCESS);
253 439 return rs_m;
254 440 }
255   -
  441 +
256 442 /**
257 443 * @description : (TODO) json班次数据转list班次.
258   - *
  444 + *
259 445 * @param jsonStr 班次json字符串]
260   - *
  446 + *
261 447 * @return 返回一个list分装的班次数据.
262   - *
  448 + *
263 449 * @status OK.
264 450 * */
265 451 public List<TTInfoDetail> jsonArrayToListEntity(String jsonStr) throws Exception {
... ... @@ -274,14 +460,14 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
274 460 }
275 461 return listTd;
276 462 }
277   -
  463 +
278 464 /**
279 465 * @description : (TODO) 班次map对象转实体对象.
280   - *
  466 + *
281 467 * @param obj 班次map对象.
282   - *
  468 + *
283 469 * @return 返回一个班次实体对象.
284   - *
  470 + *
285 471 * @exception 异常暂先抛出去.
286 472 * */
287 473 public TTInfoDetail objToEntity(JSONObject obj) throws Exception {
... ... @@ -332,12 +518,12 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
332 518 // 22、返回实体对象.
333 519 return td;
334 520 }
335   -
  521 +
336 522 /**
337 523 * @description : (TODO) int转boolean类型.
338   - *
  524 + *
339 525 * @param value--int类型的数值]
340   - *
  526 + *
341 527 * @return : 返回一个布尔类型值.
342 528 * */
343 529 public Boolean intToBit(int value) {
... ... @@ -347,13 +533,13 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
347 533 else if(value ==1)
348 534 tag = true;
349 535 return tag;
350   - }
351   -
  536 + }
  537 +
352 538 /**
353 539 * @description (TODO) 获取路牌.
354   - *
  540 + *
355 541 * @param xl --线路,name--路牌名称,code--路牌编码,lpType--路牌类型]
356   - *
  542 + *
357 543 * @return 返回路牌.
358 544 * */
359 545 public GuideboardInfo getLp(Line xl,String name, int code, String lpType) throws Exception {
... ... @@ -380,18 +566,18 @@ public class TTInfoDetailServiceImpl extends BServiceImpl&lt;TTInfoDetail, Long&gt; im
380 566 entity.setUpdateBy(null);
381 567 // 8、保存路牌.
382 568 guideboardInfoRepository.save(entity);
383   - }
  569 + }
384 570 // 9、返回路牌.
385 571 return entity;
386 572 }
387   -
  573 +
388 574 /**
389 575 * @description : (TODO) 线路方向转代码.
390   - *
  576 + *
391 577 * @param str--方向字符串]
392   - *
  578 + *
393 579 * @return 返回方向代码.
394   - *
  580 + *
395 581 * @exception 异常暂先抛出.
396 582 * */
397 583 public String dirToCod(String str) throws Exception {
... ...
src/main/java/com/bsth/service/schedule/impl/plan/DroolsSchedulePlan.java
... ... @@ -326,6 +326,8 @@ public class DroolsSchedulePlan {
326 326 schedulePlan.setScheduleToTime(this.to);
327 327 schedulePlan.setCreateBy(this.schedulePlan.getCreateBy());
328 328 schedulePlan.setUpdateBy(this.schedulePlan.getUpdateBy());
  329 + schedulePlan.setCreateDate(this.schedulePlan.getCreateDate());
  330 + schedulePlan.setUpdateDate(this.schedulePlan.getUpdateDate());
329 331  
330 332 // 1-1、构造drools规则输入数据,输出数据
331 333 PlanCalcuParam_input planCalcuParam_input = new PlanCalcuParam_input(
... ...
src/main/java/com/bsth/service/schedule/utils/MyDateUtils.java 0 → 100644
  1 +package com.bsth.service.schedule.utils;
  2 +
  3 +import org.apache.commons.lang3.time.DateUtils;
  4 +import org.joda.time.DateTime;
  5 +
  6 +import java.util.Date;
  7 +
  8 +/**
  9 + * 日期处理工具类。
  10 + */
  11 +public class MyDateUtils {
  12 +
  13 + /**
  14 + * 将HH:mm格式的时间格式加上指定分钟后,生成新的日期返回。
  15 + * @param hhssDate
  16 + * @param minutes
  17 + * @param day 是否跨天
  18 + */
  19 + public static Date hhssTimePlusMinunits(String hhssDate, Integer minutes, Integer day) {
  20 + try {
  21 + DateTime newDate = new DateTime(DateUtils.parseDate("1980-01-01 " + hhssDate, "yyyy-MM-dd HH:mm"));
  22 + return newDate.plusDays(day).plusMinutes(minutes).toDate();
  23 + } catch (Exception exp) {
  24 + throw new RuntimeException(exp);
  25 + }
  26 + }
  27 +}
... ...
src/main/java/com/bsth/service/schedule/utils/MyHttpUtils.java 0 → 100644
  1 +package com.bsth.service.schedule.utils;
  2 +
  3 +import javax.servlet.http.HttpServletResponse;
  4 +import java.io.*;
  5 +import java.net.URLEncoder;
  6 +
  7 +/**
  8 + * 相关Http层的util工具类。
  9 + */
  10 +public class MyHttpUtils {
  11 + // 流输出文件
  12 + public static void responseStreamFile(HttpServletResponse response, File file) throws IOException {
  13 + // 流输出导出文件
  14 + response.setHeader("content-type", "application/octet-stream");
  15 + String fileName = file.getName();
  16 + if (MyStringUtils.isContainChinese(fileName)) {
  17 + response.setHeader("Content-Disposition", "attachment; filename*=" + URLEncoder.encode(fileName, "UTF-8"));
  18 + } else {
  19 + response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
  20 + }
  21 + response.setContentType("application/octet-stream");
  22 +
  23 + try (
  24 + OutputStream os = response.getOutputStream();
  25 + BufferedOutputStream bos = new BufferedOutputStream(os);
  26 + InputStream is = new FileInputStream(file);
  27 + BufferedInputStream bis = new BufferedInputStream(is)
  28 + ) {
  29 + int length;
  30 + byte[] temp = new byte[1024 * 10];
  31 + while ((length = bis.read(temp)) != -1) {
  32 + bos.write(temp, 0, length);
  33 + }
  34 + bos.flush();
  35 + }
  36 + }
  37 +}
... ...
src/main/resources/static/pages/home.html
... ... @@ -83,15 +83,24 @@
83 83 success: function(rs) {
84 84 if (rs && rs.status === "SUCCESS") {
85 85 if (rs.data && rs.data.length && rs.data.length > 0) {
86   - var text = "";
  86 + var htmlText = "";
  87 + var wrapData = [];
87 88 if (rs.data.length > 8) {
88   - text = "部分停用信息如下:</br>" + rs.data.slice(0, 8).join("</br>");
  89 + htmlText = "<span style='font-weight: bold; font-style: italic; '>部分停用信息如下:</span></br>";
  90 + wrapData = rs.data.slice(0, 8);
89 91 } else {
90   - text = "所有停用信息如下:</br>" + rs.data.join("</br>");
  92 + htmlText = "<span style='font-weight: bold; font-style: italic; '>所有停用信息如下:</span></br>";
  93 + wrapData = rs.data;
91 94 }
  95 + $.each(wrapData, function(index, value) {
  96 + wrapData[index] = "<span style='font-size: 14px;'>" + value + "</span>";
  97 + });
  98 +
  99 + htmlText += wrapData.join("</br>");
  100 +
92 101 swal({
93   - title: "人员配置停用信息",
94   - text: text,
  102 + title: "排班人员停用信息",
  103 + text: htmlText,
95 104 html: true,
96 105 type: "warning",
97 106 showCancelButton: true,
... ...
src/main/resources/static/pages/scheduleApp/module/common/prj-common-globalservice.js
... ... @@ -967,6 +967,33 @@ angular.module(&#39;ScheduleApp&#39;).factory(
967 967 }
968 968 }
969 969 ),
  970 +
  971 + pvInfoExport: $resource(
  972 + '/tidc/exportPvInfo/:id',
  973 + {id: '@id'},
  974 + {
  975 + do: {
  976 + method: 'GET',
  977 + responseType: "arraybuffer",
  978 + transformResponse: function(data, headers, status){
  979 + if (status != 200) {
  980 + return data;
  981 + }
  982 +
  983 + // console.log(headers("Content-Disposition"));
  984 + // 获取文件名,后台根据是否还有中文名字,返回filename=ascii编码的文件名 或 filename*=unicode编码的文件名
  985 + var fileName = headers("Content-Disposition").split(";")[1].split("filename=")[1];
  986 + var fileNameUnicode = headers("Content-Disposition").split("filename*=")[1];
  987 + if (fileNameUnicode) {//当存在 filename* 时,取filename* 并进行解码(为了解决中文乱码问题)
  988 + fileName = decodeURIComponent(fileNameUnicode);
  989 + }
  990 +
  991 + return {fileData : data, fileName: fileName};
  992 + }
  993 + }
  994 + }
  995 + ),
  996 +
970 997 edit: $resource(
971 998 '/tidc/edit/:xlid/:ttid',
972 999 {},
... ... @@ -1017,7 +1044,8 @@ angular.module(&#39;ScheduleApp&#39;).factory(
1017 1044 }
1018 1045  
1019 1046 ]
1020   -);
  1047 +);
  1048 +
1021 1049 // 时刻表日志管理service
1022 1050 angular.module('ScheduleApp').factory(
1023 1051 'TimetableLogManageService_g',
... ...
src/main/resources/static/pages/scheduleApp/module/core/schedulePlanManage/info/edit.html
... ... @@ -152,6 +152,39 @@
152 152 </div>
153 153  
154 154 <div class="form-group has-success has-feedback">
  155 + <label class="col-md-2 control-label">计划里程*:</label>
  156 + <div class="col-md-3">
  157 + <input type="text" class="form-control" name="jhlc"
  158 + ng-model="ctrl.schedulePlanInfoForSave.jhlc" required ng-pattern="ctrl.float_regex"
  159 + />
  160 + </div>
  161 + <!-- 隐藏块,显示验证信息 -->
  162 + <div class="alert alert-danger well-sm" ng-show="myForm.jhlc.$error.required">
  163 + 计划里程必须填写
  164 + </div>
  165 + <div class="alert alert-danger well-sm" ng-show="myForm.jhlc.$error.pattern">
  166 + 输入数字
  167 + </div>
  168 +
  169 + </div>
  170 + <div class="form-group has-success has-feedback">
  171 + <label class="col-md-2 control-label">班次历时*:</label>
  172 + <div class="col-md-3">
  173 + <input type="text" class="form-control" name="bcsj"
  174 + ng-model="ctrl.schedulePlanInfoForSave.bcsj" required ng-pattern="ctrl.number_regex"
  175 + />
  176 + </div>
  177 + <!-- 隐藏块,显示验证信息 -->
  178 + <div class="alert alert-danger well-sm" ng-show="myForm.bcsj.$error.required">
  179 + 班次时间必须填写
  180 + </div>
  181 + <div class="alert alert-danger well-sm" ng-show="myForm.bcsj.$error.pattern">
  182 + 输入整数
  183 + </div>
  184 +
  185 + </div>
  186 +
  187 + <div class="form-group has-success has-feedback">
155 188 <label class="col-md-2 control-label">车辆*:</label>
156 189 <div class="col-md-4">
157 190 <sa-Select5 name="cl"
... ...
src/main/resources/static/pages/scheduleApp/module/core/schedulePlanManage/info/module.js
... ... @@ -230,6 +230,11 @@ angular.module(&quot;ScheduleApp&quot;).controller(
230 230 $state.go("schedulePlanInfoManage", $stateParams);
231 231 };
232 232  
  233 + // 整数
  234 + self.number_regex = /^-?\d+$/;
  235 + // 小数
  236 + self.float_regex = /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/;
  237 +
233 238 // 线路版本描述
234 239 self.title_tip = "版本加载中...";
235 240  
... ...
src/main/resources/static/pages/scheduleApp/module/core/ttInfoManage/detailedit/edit3.html
... ... @@ -126,6 +126,12 @@
126 126 <i class="fa fa-refresh"></i>
127 127 刷新数据
128 128 </a>
  129 + <a href="javascript:" style="padding-right: 5px;"
  130 + ng-click="ctrl.exportPvInfo()"
  131 + ng-show="ctrl.currentView.btn6">
  132 + <i class="fa fa-file-excel-o" aria-hidden="true"></i>
  133 + 导出
  134 + </a>
129 135 </div>
130 136  
131 137  
... ...
src/main/resources/static/pages/scheduleApp/module/core/ttInfoManage/detailedit/timeTableDetailManage_old.js
... ... @@ -60,6 +60,10 @@ angular.module(&#39;ScheduleApp&#39;).factory(
60 60 );
61 61 },
62 62  
  63 + pvInfoExportPromise: function(ttInfoId) {
  64 + return service.pvInfoExport.do({id: ttInfoId}).$promise;
  65 + },
  66 +
63 67 /**
64 68 * 获取编辑用的时刻表明细数据。
65 69 * @param xlid 线路id
... ... @@ -357,7 +361,8 @@ angular.module(&#39;ScheduleApp&#39;).controller(
357 361 '$state',
358 362 '$scope',
359 363 '$window',
360   - function(service, $stateParams, $uibModal, $state, $scope, $window) {
  364 + 'FileDownload_g',
  365 + function(service, $stateParams, $uibModal, $state, $scope, $window, fileDownload) {
361 366 var self = this;
362 367 self.xlid = $stateParams.xlid; // 获取传过来的线路id
363 368 self.ttid = $stateParams.ttid; // 获取传过来的时刻表id
... ... @@ -444,7 +449,8 @@ angular.module(&#39;ScheduleApp&#39;).controller(
444 449 "preView" : {
445 450 viewId : 2,
446 451 switchBtnMsg : "切换编辑视图",
447   - btn5 : true
  452 + btn5 : true,
  453 + btn6 : true
448 454 }
449 455 };
450 456 self.currentView = self.viewInfos["editView"]; // 默认编辑视图
... ... @@ -639,6 +645,19 @@ angular.module(&#39;ScheduleApp&#39;).controller(
639 645 }
640 646 };
641 647  
  648 + // 导出pv预览视图数据
  649 + self.exportPvInfo = function() {
  650 + var promise = service.pvInfoExportPromise(self.ttid);
  651 + promise.then(
  652 + function(result) {
  653 + fileDownload.downloadFile(result.fileData, "application/octet-stream", result.fileName);
  654 + },
  655 + function(result) {
  656 + console.log("导出预览视图信息失败:" + result);
  657 + }
  658 + );
  659 + };
  660 +
642 661 }
643 662  
644 663 ]
... ...
src/main/resources/static/pages/scheduleApp/module/core/ttInfoManage/service.js
... ... @@ -207,6 +207,33 @@ angular.module(&#39;ScheduleApp&#39;).factory(
207 207 }
208 208 }
209 209 ),
  210 +
  211 + pvInfoExport: $resource(
  212 + '/tidc/exportPvInfo/:id',
  213 + {id: '@id'},
  214 + {
  215 + do: {
  216 + method: 'GET',
  217 + responseType: "arraybuffer",
  218 + transformResponse: function(data, headers, status){
  219 + if (status != 200) {
  220 + return data;
  221 + }
  222 +
  223 + // console.log(headers("Content-Disposition"));
  224 + // 获取文件名,后台根据是否还有中文名字,返回filename=ascii编码的文件名 或 filename*=unicode编码的文件名
  225 + var fileName = headers("Content-Disposition").split(";")[1].split("filename=")[1];
  226 + var fileNameUnicode = headers("Content-Disposition").split("filename*=")[1];
  227 + if (fileNameUnicode) {//当存在 filename* 时,取filename* 并进行解码(为了解决中文乱码问题)
  228 + fileName = decodeURIComponent(fileNameUnicode);
  229 + }
  230 +
  231 + return {fileData : data, fileName: fileName};
  232 + }
  233 + }
  234 + }
  235 + ),
  236 +
210 237 edit: $resource(
211 238 '/tidc/edit/:xlid/:ttid',
212 239 {},
... ... @@ -257,4 +284,4 @@ angular.module(&#39;ScheduleApp&#39;).factory(
257 284 }
258 285  
259 286 ]
260   -);
261 287 \ No newline at end of file
  288 +);
... ...