ApiController.java 40 KB

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