ApiController.java 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. package com.ruoyi.biz.controller;
  2. import com.ruoyi.biz.domain.*;
  3. import com.ruoyi.biz.service.*;
  4. import com.ruoyi.biz.service.impl.AsyncServiceImpl;
  5. import com.ruoyi.biz.service.impl.BrokenYarnExportServiceImpl;
  6. import com.ruoyi.biz.tools.Tools;
  7. import com.ruoyi.common.constant.Constants;
  8. import com.ruoyi.common.core.controller.BaseController;
  9. import com.ruoyi.common.core.domain.R;
  10. import com.ruoyi.common.utils.CacheUtils;
  11. import com.ruoyi.common.utils.DateUtils;
  12. import io.swagger.annotations.Api;
  13. import io.swagger.annotations.ApiOperation;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.apache.poi.ss.usermodel.*;
  16. import org.apache.poi.ss.util.CellRangeAddress;
  17. import org.apache.poi.xddf.usermodel.chart.BarDirection;
  18. import org.apache.poi.xssf.usermodel.XSSFSheet;
  19. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  20. import org.springframework.beans.factory.annotation.Value;
  21. import org.springframework.web.bind.annotation.*;
  22. import javax.annotation.Resource;
  23. import javax.servlet.http.HttpServletResponse;
  24. import java.io.BufferedOutputStream;
  25. import java.io.FileInputStream;
  26. import java.io.IOException;
  27. import java.io.OutputStream;
  28. import java.math.BigDecimal;
  29. import java.math.RoundingMode;
  30. import java.net.URLEncoder;
  31. import java.text.ParseException;
  32. import java.time.*;
  33. import java.util.*;
  34. import java.util.concurrent.ExecutionException;
  35. import java.util.concurrent.Future;
  36. import java.util.concurrent.atomic.AtomicInteger;
  37. import java.util.concurrent.atomic.AtomicReference;
  38. import java.util.stream.Collectors;
  39. /**
  40. * swagger 用户测试方法
  41. *
  42. * @author ruoyi
  43. */
  44. @Api("数据接口")
  45. @RestController
  46. @Slf4j
  47. @RequestMapping("/api/")
  48. public class ApiController extends BaseController {
  49. @Resource
  50. private ITwinCalcDayService twinCalcDayService;
  51. @Resource
  52. private ITwinCalcStopService stopService;
  53. @Resource
  54. private ITwinCalcAlarmsService alarmsService;
  55. @Resource
  56. private ITwinDeviceService deviceService;
  57. @Resource
  58. private IIotService iotService;
  59. @Resource
  60. private AsyncServiceImpl asyncService;
  61. @Resource
  62. private BrokenYarnExportServiceImpl exportService;
  63. @Value("${excel.total}")
  64. private String totalExcelTemplate;
  65. @Value("${excel.formula}")
  66. private String formulaExcelTemplate;
  67. @Value("${excel.gram}")
  68. private String gramExcelTemplate;
  69. @Value("${excel.stops}")
  70. private String stopsExcelTemplate;
  71. @Value("${excel.stopsType}")
  72. private String stopsTypeExcelTemplate;
  73. @Value("${excel.alarms}")
  74. private String alarmsExcelTemplate;
  75. @Value("${excel.yarn}")
  76. private String yarnExcelTemplate;
  77. @Value("${excel.brokenYarn}")
  78. private String brokenYarnExcelTemplate;
  79. @ApiOperation("在线设备")
  80. @GetMapping("/device/online")
  81. @CrossOrigin(origins = "*")
  82. public R<List<String>> online() {
  83. TwinDevice searchDevice = new TwinDevice();
  84. searchDevice.setOnline("1");
  85. List<TwinDevice> list = deviceService.selectTwinDeviceList(searchDevice);
  86. List<String> devices = new ArrayList<>();
  87. list.forEach(d -> devices.add(d.getDeviceCode()));
  88. return R.ok(devices);
  89. }
  90. @ApiOperation("首页统计数据")
  91. @GetMapping("/index")
  92. @CrossOrigin(origins = "*")
  93. public R<IndexData> index() {
  94. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_CALC);
  95. if (d != null) {
  96. IndexData indexData = (IndexData) d;
  97. return R.ok(indexData);
  98. } else {
  99. return R.fail();
  100. }
  101. }
  102. @ApiOperation("首页告警数据")
  103. @GetMapping("/alarm")
  104. @CrossOrigin(origins = "*")
  105. public R<IndexData> alarm() {
  106. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_ALARM);
  107. if (d != null) {
  108. IndexData indexData = (IndexData) d;
  109. return R.ok(indexData);
  110. } else {
  111. return R.fail();
  112. }
  113. }
  114. @ApiOperation("设备具体数据")
  115. @GetMapping("/query/{device}")
  116. @CrossOrigin(origins = "*")
  117. public R<Map> query(@PathVariable String device, String week) {
  118. TwinDevice info = deviceService.selectTwinDeviceByCode(device);
  119. if (info == null) {
  120. return R.fail("该设备未接入");
  121. }
  122. iotService.getToken();
  123. Future<Map<String, Object>> future = asyncService.currData(info);
  124. Map<String, Object> result = new HashMap<>(16);
  125. try {
  126. result.put("data", future.get());
  127. } catch (InterruptedException e) {
  128. throw new RuntimeException(e);
  129. } catch (ExecutionException e) {
  130. throw new RuntimeException(e);
  131. }
  132. if (week != null) {
  133. /*
  134. *获取前面7天的数据
  135. */
  136. LocalDateTime ldt = LocalDateTime.now();
  137. if (ldt.getHour() < 7) {
  138. //7点前是属于前一生产天
  139. ldt = ldt.minusDays(1);
  140. }
  141. LocalDate localDate = ldt.toLocalDate().minusDays(7);
  142. Date date = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant());
  143. List<TwinCalcDay> list = twinCalcDayService.selectTwinCalcDayListByTime(date);
  144. List<Map<String, Object>> alarms = new ArrayList<>();
  145. Map<Date, List<TwinCalcDay>> stopDeviceGroup = list.stream().collect(Collectors.groupingBy(TwinCalcDay::getTime, LinkedHashMap::new, Collectors.toList()));
  146. for (Map.Entry<Date, List<TwinCalcDay>> entry : stopDeviceGroup.entrySet()) {
  147. Map<String, Object> temp = new HashMap<>(16);
  148. TwinCalcDay day = new TwinCalcDay(entry.getKey());
  149. List<TwinCalcDay> days = entry.getValue();
  150. day.calcDays(days);
  151. temp.put("time", DateUtils.parseDateToStr(entry.getKey()));
  152. temp.put("value", day.getAlarm());
  153. alarms.add(temp);
  154. }
  155. result.put("alarms", alarms);
  156. }
  157. return R.ok(result);
  158. }
  159. @ApiOperation("送经量")
  160. @GetMapping("/export/warp-run-in")
  161. @CrossOrigin(origins = "*")
  162. public void warpRunInExport(HttpServletResponse response) {
  163. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_WARP_RUN_IN);
  164. if (d != null) {
  165. List<WarpRunIn> list = (List<WarpRunIn>) d;
  166. try (Workbook wb = new XSSFWorkbook(); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  167. Sheet sheet = wb.createSheet("送经量明细");
  168. sheet.setDefaultColumnWidth(15);
  169. CellStyle style = wb.createCellStyle();
  170. style.setDataFormat(wb.createDataFormat().getFormat("0.00"));
  171. Row titleRow = sheet.createRow(0);
  172. Cell titleCell = titleRow.createCell(0);
  173. titleCell.setCellValue("设备名");
  174. titleCell = titleRow.createCell(1);
  175. titleCell.setCellValue("L1梳栉送经量");
  176. titleCell = titleRow.createCell(2);
  177. titleCell.setCellValue("L2梳栉送经量");
  178. titleCell = titleRow.createCell(3);
  179. titleCell.setCellValue("L3梳栉送经量");
  180. titleCell = titleRow.createCell(4);
  181. titleCell.setCellValue("L4梳栉送经量");
  182. titleCell = titleRow.createCell(5);
  183. titleCell.setCellValue("L5梳栉送经量");
  184. titleCell = titleRow.createCell(6);
  185. titleCell.setCellValue("牵拉密度");
  186. titleCell = titleRow.createCell(7);
  187. titleCell.setCellValue("卷曲张力系数");
  188. AtomicInteger rowNum = new AtomicInteger(1);
  189. list.forEach(warp -> {
  190. Row row = sheet.createRow(rowNum.get());
  191. Cell[] cells = new Cell[8];
  192. for (int i = 0; i < cells.length; i++) {
  193. cells[i] = row.createCell(i);
  194. }
  195. warp.setCells(cells, style);
  196. rowNum.getAndIncrement();
  197. });
  198. // 清空response
  199. response.reset();
  200. // 设置response的Header
  201. response.setCharacterEncoding("UTF-8");
  202. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  203. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  204. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  205. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("送经量明细导出" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  206. response.setContentType("application/octet-stream");
  207. wb.write(outputStream);
  208. outputStream.flush();
  209. } catch (IOException ex) {
  210. ex.printStackTrace();
  211. }
  212. }
  213. }
  214. @ApiOperation("纱线规格")
  215. @GetMapping("/export/yarn-specifications")
  216. @CrossOrigin(origins = "*")
  217. public void yarnSpecificationsExport(Integer day, HttpServletResponse response) {
  218. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_FORMULA_DETAIL);
  219. if (d != null) {
  220. List<FormulaDetail> list = (List<FormulaDetail>) d;
  221. list.sort(Comparator.comparing(FormulaDetail::getFormula_data_4).thenComparing(FormulaDetail::getFormula_data_5).thenComparing(FormulaDetail::getFormula_data_6)
  222. .thenComparing(FormulaDetail::getFormula_data_7).thenComparing(FormulaDetail::getFormula_data_8).thenComparing(FormulaDetail::getFormula_data_9)
  223. .thenComparing(FormulaDetail::getFormula_data_15));
  224. Map<String, List<FormulaDetail>> map = list.stream().collect(Collectors.groupingBy(FormulaDetail::getYarnD, LinkedHashMap::new, Collectors.toList()));
  225. LocalDateTime localDateTime = LocalDateTime.now();
  226. if (localDateTime.getHour() < 7) {
  227. //当天7点前,则是前天数据
  228. localDateTime = localDateTime.minusDays(2);
  229. } else {
  230. //7点后,就是昨日数据
  231. localDateTime = localDateTime.minusDays(1);
  232. }
  233. LocalDate localDate = localDateTime.toLocalDate();
  234. Date sd = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant());
  235. List<TwinCalcDay> calcDayList = twinCalcDayService.selectTwinCalcDayListByTime(sd, sd);
  236. Map<Long, BigDecimal> decimalMap = calcDayList.stream().collect(Collectors.toMap(TwinCalcDay::getDeviceId, TwinCalcDay::getLength));
  237. try (FileInputStream inputStream = new FileInputStream(yarnExcelTemplate); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  238. Sheet sheet = wb.getSheetAt(0);
  239. AtomicInteger rowNum = new AtomicInteger(2);
  240. CellStyle percentStyle = wb.createCellStyle();
  241. percentStyle.setDataFormat(wb.createDataFormat().getFormat("0.00%"));
  242. // 垂直居中
  243. percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  244. CellStyle p2 = wb.createCellStyle();
  245. p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
  246. for (String s : map.keySet()) {
  247. int sr = rowNum.get();
  248. List<FormulaDetail> fList = map.get(s);
  249. for (FormulaDetail detail : fList) {
  250. Row row = sheet.createRow(rowNum.get());
  251. Cell[] cells = new Cell[39];
  252. for (int i = 0; i < cells.length; i++) {
  253. cells[i] = row.createCell(i);
  254. }
  255. detail.setYarnCells(cells, p2);
  256. rowNum.getAndIncrement();
  257. }
  258. if (fList.size() > 1) {
  259. int er = sr + fList.size() - 1;
  260. sheet.addMergedRegion(new CellRangeAddress(sr, er, 0, 0));
  261. sheet.addMergedRegion(new CellRangeAddress(sr, er, 1, 1));
  262. sheet.addMergedRegion(new CellRangeAddress(sr, er, 2, 2));
  263. }
  264. }
  265. XSSFSheet sheet2 = wb.getSheetAt(1);
  266. wb.setSheetName(1, "未来产能预期(" + day + "天)");
  267. AtomicInteger rn = new AtomicInteger(2);
  268. //1.先按底纱分组
  269. Map<String, List<FormulaDetail>> map2 = list.stream().collect(Collectors.groupingBy(FormulaDetail::getYarnDd, LinkedHashMap::new, Collectors.toList()));
  270. for (String s : map2.keySet()) {
  271. int sr = rn.get();
  272. List<FormulaDetail> l12list = map2.get(s);
  273. //2.再按规格分组
  274. Map<Integer, List<FormulaDetail>> d1map = l12list.stream().collect(Collectors.groupingBy(FormulaDetail::getFormula_data_6, LinkedHashMap::new, Collectors.toList()));
  275. for (Integer l3d : d1map.keySet()) {
  276. int ssr = rn.get();
  277. List<FormulaDetail> l3list = d1map.get(l3d);
  278. //3.再按盘头根数和毛高分组
  279. Map<String, List<FormulaDetail>> d2map = l3list.stream().collect(Collectors.groupingBy(FormulaDetail::getYarnPt, LinkedHashMap::new, Collectors.toList()));
  280. for (String pt : d2map.keySet()) {
  281. List<FormulaDetail> ptList = d2map.get(pt);
  282. FormulaDetail detail = ptList.get(0);
  283. String device = "";
  284. BigDecimal length = BigDecimal.ZERO;
  285. for (FormulaDetail dd : ptList) {
  286. BigDecimal temp = decimalMap.get(dd.getDeviceId());
  287. if (temp != null) {
  288. length = length.add(temp);
  289. }
  290. // device += dd.getDevice() + "/";
  291. }
  292. BigDecimal yLength = length.multiply(BigDecimal.valueOf(day));
  293. Row row = sheet2.createRow(rn.get());
  294. Cell[] cells = new Cell[12];
  295. for (int i = 0; i < cells.length; i++) {
  296. cells[i] = row.createCell(i);
  297. }
  298. cells[0].setCellValue(rn.get() - 1);
  299. cells[1].setCellValue(detail.getFormula_data_4());
  300. cells[2].setCellValue(detail.getFormula_data_5());
  301. cells[3].setCellValue(detail.getFormula_data_6());
  302. cells[4].setCellValue(detail.getFormula_data_10());
  303. cells[5].setCellValue(detail.getFormula_data_11());
  304. cells[6].setCellValue(detail.getFormula_data_12());
  305. cells[7].setCellValue(detail.getFormula_data_15());
  306. cells[8].setCellValue(length.doubleValue());
  307. cells[8].setCellStyle(p2);
  308. cells[9].setCellValue(yLength.doubleValue());
  309. cells[9].setCellStyle(p2);
  310. //规格占比
  311. BigDecimal percent1 = BigDecimal.valueOf(ptList.size()).divide(BigDecimal.valueOf(list.size()), 4, RoundingMode.HALF_UP);
  312. cells[10].setCellValue(percent1.doubleValue());
  313. cells[10].setCellStyle(percentStyle);
  314. //底纱占比
  315. BigDecimal percent2 = BigDecimal.valueOf(l12list.size()).divide(BigDecimal.valueOf(list.size()), 4, RoundingMode.HALF_UP);
  316. cells[11].setCellValue(percent2.doubleValue());
  317. cells[11].setCellStyle(percentStyle);
  318. rn.getAndIncrement();
  319. }
  320. if (d2map.size() > 1) {
  321. int er = rn.get() - 1;
  322. sheet2.addMergedRegion(new CellRangeAddress(ssr, er, 1, 1));
  323. sheet2.addMergedRegion(new CellRangeAddress(ssr, er, 2, 2));
  324. sheet2.addMergedRegion(new CellRangeAddress(ssr, er, 3, 3));
  325. }
  326. }
  327. if (d1map.size() > 1) {
  328. int er = rn.get() - 1;
  329. sheet2.addMergedRegion(new CellRangeAddress(sr, er, 11, 11));
  330. }
  331. }
  332. int endRn = rn.get() - 1;
  333. int[] pos = {13, 1, 20, endRn + 1};
  334. int[] xdata = {2, endRn, 0, 0};
  335. int[] data = {2, endRn, 10, 10};
  336. exportService.drawBar(sheet2, "规格占比", "规格序号", pos, xdata, data, BarDirection.COL);
  337. // 清空response
  338. response.reset();
  339. // 设置response的Header
  340. response.setCharacterEncoding("UTF-8");
  341. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  342. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  343. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  344. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("纱线规格导出" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  345. response.setContentType("application/octet-stream");
  346. wb.write(outputStream);
  347. outputStream.flush();
  348. } catch (IOException ex) {
  349. ex.printStackTrace();
  350. }
  351. }
  352. }
  353. @ApiOperation("平方米克重")
  354. @GetMapping("/gram-mass/total")
  355. @CrossOrigin(origins = "*")
  356. public R<List<GramMass>> gramMass() {
  357. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_GRAM_MASS);
  358. if (d != null) {
  359. List<GramMass> list = (List<GramMass>) d;
  360. return R.ok(list);
  361. } else {
  362. return R.fail();
  363. }
  364. }
  365. @ApiOperation("平方米克重详情")
  366. @GetMapping("/gram-mass/detail/{gramMass}")
  367. @CrossOrigin(origins = "*")
  368. public R<List<GramMassDetail>> gramMassDetail(@PathVariable Float gramMass) {
  369. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_GRAM_MASS_DETAIL);
  370. if (d != null) {
  371. List<GramMassDetail> list = (List<GramMassDetail>) d;
  372. list = list.stream().filter(detail -> detail.getGramMass().equals(gramMass)).collect(Collectors.toList());
  373. return R.ok(list);
  374. } else {
  375. return R.fail();
  376. }
  377. }
  378. @ApiOperation("平方米克重导出")
  379. @GetMapping("/export/gram-mass")
  380. @CrossOrigin(origins = "*")
  381. public void gramMassExport(HttpServletResponse response) {
  382. Object total = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_GRAM_MASS);
  383. Object detail = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_GRAM_MASS_DETAIL);
  384. if (total != null && detail != null) {
  385. List<GramMass> list = (List<GramMass>) total;
  386. List<GramMassDetail> details = (List<GramMassDetail>) detail;
  387. try (FileInputStream inputStream = new FileInputStream(gramExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  388. Sheet sheet = wb.getSheetAt(0);
  389. CreationHelper creationHelper = wb.getCreationHelper();
  390. CellStyle percentStyle = wb.createCellStyle();
  391. percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
  392. CellStyle p2 = wb.createCellStyle();
  393. p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
  394. AtomicInteger rowNum = new AtomicInteger(1);
  395. list.forEach(gram -> {
  396. Row row = sheet.createRow(rowNum.get());
  397. Cell[] cells = new Cell[3];
  398. for (int i = 0; i < cells.length; i++) {
  399. cells[i] = row.createCell(i);
  400. }
  401. cells[0].setCellValue(gram.getGramMass());
  402. cells[0].setCellStyle(p2);
  403. cells[1].setCellValue(gram.getNum());
  404. cells[2].setCellValue(gram.getPercent());
  405. cells[2].setCellStyle(percentStyle);
  406. rowNum.getAndIncrement();
  407. Sheet ns = wb.cloneSheet(1);
  408. wb.setSheetName(wb.getSheetIndex(ns), gram.getGramMass() + "克明细");
  409. AtomicInteger detailRowNum = new AtomicInteger(2);
  410. details.stream().filter(d -> d.getGramMass().equals(gram.getGramMass())).forEach(d -> {
  411. Row dRow = ns.createRow(detailRowNum.get());
  412. Cell[] dCells = new Cell[24];
  413. for (int i = 0; i < dCells.length; i++) {
  414. dCells[i] = dRow.createCell(i);
  415. }
  416. dCells[2].setCellStyle(p2);
  417. d.setCells(dCells);
  418. detailRowNum.getAndIncrement();
  419. });
  420. });
  421. wb.removeSheetAt(1);
  422. // 清空response
  423. response.reset();
  424. // 设置response的Header
  425. response.setCharacterEncoding("UTF-8");
  426. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  427. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  428. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  429. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("平方米克重明细导出" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  430. response.setContentType("application/octet-stream");
  431. wb.write(outputStream);
  432. outputStream.flush();
  433. } catch (IOException ex) {
  434. ex.printStackTrace();
  435. }
  436. }
  437. }
  438. @ApiOperation("配方统计")
  439. @GetMapping("/formula/total")
  440. @CrossOrigin(origins = "*")
  441. public R<List<FormulaTotal>> formulaTotal() {
  442. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_FORMULA_TOTAL);
  443. if (d != null) {
  444. List<FormulaTotal> list = (List<FormulaTotal>) d;
  445. return R.ok(list);
  446. } else {
  447. return R.fail();
  448. }
  449. }
  450. @ApiOperation("配方详情")
  451. @GetMapping("/formula/detail/{height}")
  452. @CrossOrigin(origins = "*")
  453. public R<List<FormulaDetail>> formulaDetail(@PathVariable Float height) {
  454. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_FORMULA_DETAIL);
  455. if (d != null) {
  456. List<FormulaDetail> list = (List<FormulaDetail>) d;
  457. list = list.stream().filter(detail -> detail.getFormula_data_15().equals(height)).collect(Collectors.toList());
  458. return R.ok(list);
  459. } else {
  460. return R.fail();
  461. }
  462. }
  463. @ApiOperation("配方详情导出")
  464. @GetMapping("/formula/export/{height}")
  465. @CrossOrigin(origins = "*")
  466. public void formulaExport(@PathVariable Float height, HttpServletResponse response) {
  467. Object d = CacheUtils.get(Constants.IOT_TOKEN, Constants.INDEX_FORMULA_DETAIL);
  468. if (d != null) {
  469. List<FormulaDetail> list = (List<FormulaDetail>) d;
  470. list = list.stream().filter(detail -> detail.getFormula_data_15().equals(height)).collect(Collectors.toList());
  471. try (FileInputStream inputStream = new FileInputStream(formulaExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  472. Sheet sheet = wb.getSheetAt(0);
  473. AtomicInteger rowNum = new AtomicInteger(2);
  474. list.forEach(detail -> {
  475. Row row = sheet.createRow(rowNum.get());
  476. Cell[] cells = new Cell[26];
  477. for (int i = 0; i < cells.length; i++) {
  478. cells[i] = row.createCell(i);
  479. }
  480. detail.setCells(cells);
  481. rowNum.getAndIncrement();
  482. });
  483. // 清空response
  484. response.reset();
  485. // 设置response的Header
  486. response.setCharacterEncoding("UTF-8");
  487. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  488. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  489. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  490. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("毛高" + height + "设备明细导出" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  491. response.setContentType("application/octet-stream");
  492. wb.write(outputStream);
  493. outputStream.flush();
  494. } catch (IOException ex) {
  495. ex.printStackTrace();
  496. }
  497. }
  498. }
  499. @ApiOperation("导出产量数据")
  500. @GetMapping("/export/production")
  501. @CrossOrigin(origins = "*")
  502. public void productionExport(String start, String end, HttpServletResponse response) {
  503. LocalDate localDate = LocalDate.parse(start);
  504. Date sd = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant());
  505. localDate = LocalDate.parse(end);
  506. Date ed = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant());
  507. List<TwinCalcDay> list = twinCalcDayService.selectTwinCalcDayListByTime(sd, ed);
  508. try (FileInputStream inputStream = new FileInputStream(totalExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  509. CreationHelper creationHelper = wb.getCreationHelper();
  510. CellStyle percentStyle = wb.createCellStyle();
  511. percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
  512. CellStyle p2 = wb.createCellStyle();
  513. p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
  514. Map<Date, List<TwinCalcDay>> dayGroup = list.stream().collect(Collectors.groupingBy(TwinCalcDay::getTime, LinkedHashMap::new, Collectors.toList()));
  515. for (Map.Entry<Date, List<TwinCalcDay>> entry : dayGroup.entrySet()) {
  516. Sheet sheet = wb.cloneSheet(0);
  517. wb.setSheetName(wb.getSheetIndex(sheet), DateUtils.parseDateToStr("yyyy-MM-dd", entry.getKey()));
  518. List<TwinCalcDay> days = entry.getValue();
  519. AtomicInteger rowNum = new AtomicInteger(2);
  520. days.forEach(day -> {
  521. Row row = sheet.createRow(rowNum.get());
  522. Cell[] cells = new Cell[25];
  523. for (int i = 0; i < cells.length; i++) {
  524. cells[i] = row.createCell(i);
  525. }
  526. day.setCells(cells);
  527. rowNum.getAndIncrement();
  528. });
  529. }
  530. wb.removeSheetAt(0);
  531. // 清空response
  532. response.reset();
  533. // 设置response的Header
  534. response.setCharacterEncoding("UTF-8");
  535. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  536. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  537. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  538. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("最近7天产量统计" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  539. response.setContentType("application/octet-stream");
  540. wb.write(outputStream);
  541. outputStream.flush();
  542. } catch (IOException ex) {
  543. ex.printStackTrace();
  544. }
  545. }
  546. @ApiOperation("导出断纱分析")
  547. @GetMapping("/export/broken-yarn")
  548. @CrossOrigin(origins = "*")
  549. public void brokenYarnExport(String date, HttpServletResponse response) throws ParseException {
  550. LocalDate localDate = LocalDate.parse(date);
  551. try (FileInputStream inputStream = new FileInputStream(brokenYarnExcelTemplate); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  552. //1.基本信息表
  553. exportService.base(wb, localDate);
  554. //2.停机原因分析
  555. exportService.stop(wb, localDate);
  556. //4.断纱停机TOP排名
  557. exportService.top(wb, localDate);
  558. // 清空response
  559. response.reset();
  560. // 设置response的Header
  561. response.setCharacterEncoding("UTF-8");
  562. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  563. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  564. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  565. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("断纱分析日报" + localDate + ".xlsx", "UTF-8"));
  566. response.setContentType("application/octet-stream");
  567. wb.write(outputStream);
  568. outputStream.flush();
  569. } catch (IOException ex) {
  570. ex.printStackTrace();
  571. }
  572. }
  573. @ApiOperation("导出停机数据")
  574. @GetMapping("/export/stops")
  575. @CrossOrigin(origins = "*")
  576. public void stopsExport(String start, String end, HttpServletResponse response) throws ParseException {
  577. Date sTime = DateUtils.parseDate(start, DateUtils.YYYY_MM_DD_HH_MM_SS);
  578. Date eTime = DateUtils.parseDate(end, DateUtils.YYYY_MM_DD_HH_MM_SS);
  579. List<TwinCalcStop> list = stopService.selectTwinCalcStopListByDate(sTime, eTime);
  580. Map<Integer, List<TwinCalcStop>> stopDeviceGroup = list.stream().collect(Collectors.groupingBy(TwinCalcStop::getStopType, LinkedHashMap::new, Collectors.toList()));
  581. //1停经片停机,2-CCD停机(相机号+断纱/故障),3-人工停机,4-断电停机,5-设备故障停机,6-落布米数达到停机,7-盘头剩余圈数达到停机
  582. String[] stopStr = {"停经片停机", "CCD停机(相机号+断纱/故障)", "人工停机", "断电停机", "设备故障停机", "落布米数达到停机", "盘头剩余圈数达到停机"};
  583. //停机次数
  584. Integer[] stopNum = new Integer[7];
  585. Integer totalNum = 0;
  586. //停机时间
  587. Long[] stopTime = new Long[7];
  588. Arrays.fill(stopTime, 0L);
  589. AtomicReference<Long> totalTime = new AtomicReference<>(0L);
  590. Map<Long, TwinDevice> deviceMap = deviceService.deviceMap();
  591. for (Map.Entry<Integer, List<TwinCalcStop>> entry : stopDeviceGroup.entrySet()) {
  592. Integer stopType = entry.getKey();
  593. int pos = stopType - 1;
  594. List<TwinCalcStop> stops = entry.getValue();
  595. stopNum[pos] = stops.size();
  596. totalNum += stops.size();
  597. stops.forEach(stop -> {
  598. // 调整停机时间
  599. if (stop.getEndTime().compareTo(eTime) > 0) {
  600. stop.setEndTime(eTime);
  601. }
  602. //调整开机时间
  603. if (stop.getStartTime().compareTo(sTime) < 0) {
  604. stop.setStartTime(sTime);
  605. }
  606. long t = (stop.getEndTime().getTime() - stop.getStartTime().getTime()) / 1000;
  607. stopTime[pos] += t;
  608. totalTime.updateAndGet(v -> v + t);
  609. });
  610. }
  611. try (FileInputStream inputStream = new FileInputStream(stopsExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  612. CreationHelper creationHelper = wb.getCreationHelper();
  613. CellStyle percentStyle = wb.createCellStyle();
  614. percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
  615. CellStyle timeStyle = wb.createCellStyle();
  616. timeStyle.setDataFormat(creationHelper.createDataFormat().getFormat(DateUtils.YYYY_MM_DD_HH_MM_SS));
  617. CellStyle rightStyle = wb.createCellStyle();
  618. rightStyle.setAlignment(HorizontalAlignment.RIGHT);
  619. Sheet sheetAt = wb.getSheetAt(0);
  620. Row title = sheetAt.getRow(0);
  621. Cell cell = title.getCell(0);
  622. cell.setCellValue("停机原因分析(" + start + "至" + end + ")");
  623. for (int i = 0; i < stopStr.length; i++) {
  624. Row row = sheetAt.createRow(i + 2);
  625. Cell[] cells = new Cell[5];
  626. for (int j = 0; j < cells.length; j++) {
  627. cells[j] = row.createCell(j);
  628. }
  629. cells[0].setCellValue(stopStr[i]);
  630. cells[1].setCellValue(stopNum[i]);
  631. cells[2].setCellValue(Tools.convertHMS(stopTime[i]));
  632. cells[2].setCellStyle(rightStyle);
  633. float percentNum = BigDecimal.valueOf(stopNum[i]).divide(BigDecimal.valueOf(totalNum), 4, RoundingMode.HALF_UP).floatValue();
  634. float percentTimes = BigDecimal.valueOf(stopTime[i]).divide(BigDecimal.valueOf(totalTime.get()), 4, RoundingMode.HALF_UP).floatValue();
  635. cells[3].setCellValue(percentNum);
  636. cells[3].setCellStyle(percentStyle);
  637. cells[4].setCellValue(percentTimes);
  638. cells[4].setCellStyle(percentStyle);
  639. }
  640. Sheet sheet = wb.getSheetAt(1);
  641. AtomicInteger rowNum = new AtomicInteger(1);
  642. list.forEach(stop -> {
  643. Row row = sheet.createRow(rowNum.get());
  644. Cell[] cells = new Cell[5];
  645. for (int j = 0; j < cells.length; j++) {
  646. cells[j] = row.createCell(j);
  647. }
  648. cells[0].setCellValue(deviceMap.get(stop.getDeviceId()).getDeviceName());
  649. cells[1].setCellValue(stopStr[stop.getStopType() - 1]);
  650. cells[2].setCellValue(stop.getStartTime());
  651. cells[2].setCellStyle(timeStyle);
  652. cells[3].setCellValue(stop.getEndTime());
  653. cells[3].setCellStyle(timeStyle);
  654. Duration duration = Duration.between(stop.getStartTime().toInstant(), stop.getEndTime().toInstant());
  655. cells[4].setCellValue(Tools.convertHMS(duration.getSeconds()));
  656. cells[4].setCellStyle(rightStyle);
  657. rowNum.getAndIncrement();
  658. });
  659. // 清空response
  660. response.reset();
  661. // 设置response的Header
  662. response.setCharacterEncoding("UTF-8");
  663. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  664. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  665. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  666. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("停机分析" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  667. response.setContentType("application/octet-stream");
  668. wb.write(outputStream);
  669. outputStream.flush();
  670. } catch (IOException ex) {
  671. ex.printStackTrace();
  672. }
  673. }
  674. @ApiOperation("停机分类导出")
  675. @GetMapping("/export/stops/type/{type}")
  676. @CrossOrigin(origins = "*")
  677. public void stopsTypeExport(@PathVariable Integer type, String start, String end, Integer st, Integer et, HttpServletResponse response) {
  678. LocalDate s = LocalDate.parse(start);
  679. LocalDate e = LocalDate.parse(end);
  680. List<TwinCalcStop> list = new ArrayList<>();
  681. do {
  682. LocalDateTime ldtS = LocalDateTime.of(s, LocalTime.MIN).plusHours(st);
  683. LocalDateTime ldtE = LocalDateTime.of(s, LocalTime.MIN).plusHours(et);
  684. Date date = Date.from(ldtS.toLocalDate().atStartOfDay(ZoneOffset.of("+8")).toInstant());
  685. Date sTime = Date.from(ldtS.atZone(ZoneId.systemDefault()).toInstant());
  686. Date eTime = Date.from(ldtE.atZone(ZoneId.systemDefault()).toInstant());
  687. List<TwinCalcStop> stopList = stopService.selectTwinCalcStopListByDate(sTime, eTime);
  688. stopList.forEach(stop -> {
  689. stop.setDataDate(date);
  690. });
  691. list.addAll(stopList);
  692. s = s.plusDays(1);
  693. } while (!s.isAfter(e));
  694. List<TwinCalcStop> stopList = list.stream().filter(stop -> stop.getStopType().equals(type)).collect(Collectors.toList());
  695. Map<Long, TwinDevice> deviceMap = deviceService.deviceMap();
  696. Map<Date, List<TwinCalcStop>> stopDateGroup = stopList.stream().collect(Collectors.groupingBy(TwinCalcStop::getDataDate, LinkedHashMap::new, Collectors.toList()));
  697. //1停经片停机,2-CCD停机(相机号+断纱/故障),3-人工停机,4-断电停机,5-设备故障停机,6-落布米数达到停机,7-盘头剩余圈数达到停机
  698. String[] stopStr = {"断纱", "断纱", "人工停机", "断电停机", "设备故障停机", "下卷", "叫料"};
  699. try (FileInputStream inputStream = new FileInputStream(stopsTypeExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  700. CreationHelper creationHelper = wb.getCreationHelper();
  701. CellStyle percentStyle = wb.createCellStyle();
  702. percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
  703. CellStyle timeStyle = wb.createCellStyle();
  704. timeStyle.setDataFormat(creationHelper.createDataFormat().getFormat(DateUtils.YYYY_MM_DD_HH_MM_SS));
  705. CellStyle dateStyle = wb.createCellStyle();
  706. dateStyle.setDataFormat(creationHelper.createDataFormat().getFormat(DateUtils.YYYY_MM_DD));
  707. CellStyle p2 = wb.createCellStyle();
  708. p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
  709. Sheet sheetAt = wb.getSheetAt(0);
  710. int rowNum = 1;
  711. AtomicInteger rs = new AtomicInteger(1);
  712. for (Map.Entry<Date, List<TwinCalcStop>> entry : stopDateGroup.entrySet()) {
  713. List<TwinCalcStop> stops = entry.getValue();
  714. Row row = sheetAt.createRow(rowNum);
  715. Cell[] cells = new Cell[7];
  716. for (int j = 0; j < cells.length; j++) {
  717. cells[j] = row.createCell(j);
  718. }
  719. cells[0].setCellValue(entry.getKey());
  720. cells[0].setCellStyle(dateStyle);
  721. cells[1].setCellValue(st + "-" + et);
  722. Map<Long, List<TwinCalcStop>> stopDeviceGroup = stops.stream().collect(Collectors.groupingBy(TwinCalcStop::getDeviceId, LinkedHashMap::new, Collectors.toList()));
  723. cells[2].setCellValue(stopDeviceGroup.size());
  724. int num = stops.size();
  725. cells[3].setCellValue(num);
  726. //0.最小,1.最大,2.总时间
  727. final long[] time = {999999L, 0, 0};
  728. Sheet sheet = wb.getSheetAt(1);
  729. stops.forEach(stop -> {
  730. long t = (stop.getEndTime().getTime() - stop.getStartTime().getTime()) / 1000;
  731. if (t < time[0]) {
  732. time[0] = t;
  733. }
  734. if (t > time[1]) {
  735. time[1] = t;
  736. }
  737. time[2] += t;
  738. Row r1 = sheet.createRow(rs.get());
  739. Cell[] cs = new Cell[6];
  740. for (int j = 0; j < cs.length; j++) {
  741. cs[j] = r1.createCell(j);
  742. }
  743. cs[0].setCellValue(entry.getKey());
  744. cs[0].setCellStyle(dateStyle);
  745. cs[1].setCellValue(st + "-" + et);
  746. cs[2].setCellValue(deviceMap.get(stop.getDeviceId()).getDeviceName());
  747. cs[3].setCellValue(stopStr[stop.getStopType() - 1]);
  748. cs[4].setCellValue(stop.getStartTime());
  749. cs[4].setCellStyle(timeStyle);
  750. cs[5].setCellValue(stop.getEndTime());
  751. cs[5].setCellStyle(timeStyle);
  752. rs.getAndIncrement();
  753. });
  754. cells[4].setCellValue(time[1]);
  755. cells[5].setCellValue(time[0]);
  756. float avg = BigDecimal.valueOf(time[2]).divide(BigDecimal.valueOf(num), 2, RoundingMode.HALF_UP).floatValue();
  757. cells[6].setCellValue(avg);
  758. cells[6].setCellStyle(p2);
  759. rowNum++;
  760. }
  761. // 清空response
  762. response.reset();
  763. // 设置response的Header
  764. response.setCharacterEncoding("UTF-8");
  765. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  766. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  767. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  768. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("并发" + stopStr[type - 1] + "分析" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  769. response.setContentType("application/octet-stream");
  770. wb.write(outputStream);
  771. outputStream.flush();
  772. } catch (IOException ex) {
  773. ex.printStackTrace();
  774. }
  775. }
  776. @ApiOperation("告警统计导出")
  777. @GetMapping("/export/alarms")
  778. @CrossOrigin(origins = "*")
  779. public void alarmsExport(String start, String end, HttpServletResponse response) throws ParseException {
  780. Date sTime = DateUtils.parseDate(start, DateUtils.YYYY_MM_DD_HH_MM_SS);
  781. Date eTime = DateUtils.parseDate(end, DateUtils.YYYY_MM_DD_HH_MM_SS);
  782. List<TwinCalcAlarms> list = alarmsService.selectTwinCalcAlarmsListByDate(sTime, eTime);
  783. list.sort((Comparator.comparing(TwinCalcAlarms::getDeviceId)));
  784. Map<Long, TwinDevice> deviceMap = deviceService.deviceMap();
  785. Map<Long, List<TwinCalcAlarms>> alarmsGroup = list.stream().collect(Collectors.groupingBy(TwinCalcAlarms::getDeviceId, LinkedHashMap::new, Collectors.toList()));
  786. String[] alarmStr = {"GB1伺服通讯故障", "GB2伺服通讯故障", "GB3伺服通讯故障", "GB4伺服通讯故障", "GB5伺服通讯故障", "牵引伺服通讯故障", "卷曲伺服通讯故障", "断纱故障", "电源故障", "联动未完全啮合", "米长到达", "GB1剩余圈数报警", "GB2剩余圈数报警", "GB3剩余圈数报警", "GB4剩余圈数报警", "GB5剩余圈数报警", "主轴变频掉线", "主轴变频故障", "GB1伺服故障", "GB2伺服故障", "GB3伺服故障", "GB4伺服故障", "GB5伺服故障", "牵引伺服故障", "卷曲伺服故障", "拍照自停", "CCD位置报警信息显示"};
  787. try (FileInputStream inputStream = new FileInputStream(alarmsExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
  788. CreationHelper creationHelper = wb.getCreationHelper();
  789. CellStyle percentStyle = wb.createCellStyle();
  790. percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
  791. CellStyle timeStyle = wb.createCellStyle();
  792. timeStyle.setDataFormat(creationHelper.createDataFormat().getFormat(DateUtils.YYYY_MM_DD_HH_MM_SS));
  793. Sheet sheetAt = wb.getSheetAt(0);
  794. int rowNum = 2;
  795. for (Map.Entry<Long, List<TwinCalcAlarms>> entry : alarmsGroup.entrySet()) {
  796. List<TwinCalcAlarms> alarms = entry.getValue();
  797. Row row = sheetAt.createRow(rowNum);
  798. Cell[] cells = new Cell[29];
  799. for (int j = 0; j < cells.length; j++) {
  800. cells[j] = row.createCell(j);
  801. }
  802. cells[0].setCellValue(deviceMap.get(entry.getKey()).getDeviceName());
  803. cells[1].setCellValue(alarms.size());
  804. Map<Integer, Long> temp = alarms.stream().collect(Collectors.groupingBy(TwinCalcAlarms::getAlarmType, Collectors.counting()));
  805. for (Integer v : temp.keySet()) {
  806. cells[v + 1].setCellValue(temp.get(v));
  807. }
  808. rowNum++;
  809. }
  810. Sheet sheet = wb.getSheetAt(1);
  811. AtomicInteger rn = new AtomicInteger(1);
  812. list.forEach(alarms -> {
  813. Row row = sheet.createRow(rn.get());
  814. Cell[] cells = new Cell[3];
  815. for (int j = 0; j < cells.length; j++) {
  816. cells[j] = row.createCell(j);
  817. }
  818. cells[0].setCellValue(deviceMap.get(alarms.getDeviceId()).getDeviceName());
  819. cells[1].setCellValue(alarmStr[alarms.getAlarmType() - 1]);
  820. cells[2].setCellValue(alarms.getStartTime());
  821. cells[2].setCellStyle(timeStyle);
  822. rn.getAndIncrement();
  823. });
  824. // 清空response
  825. response.reset();
  826. // 设置response的Header
  827. response.setCharacterEncoding("UTF-8");
  828. //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
  829. //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
  830. // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
  831. response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("告警统计" + DateUtils.dateTimeNow() + ".xlsx", "UTF-8"));
  832. response.setContentType("application/octet-stream");
  833. wb.write(outputStream);
  834. outputStream.flush();
  835. } catch (IOException ex) {
  836. ex.printStackTrace();
  837. }
  838. }
  839. }