refactor(ticket): 优化工单审核状态逻辑

This commit is contained in:
曹鹏飞 2025-04-01 08:47:13 +08:00
parent bb944f9ed6
commit f9a5c61d90
3 changed files with 318 additions and 0 deletions

View File

@ -120,6 +120,11 @@
<artifactId>tinypinyin</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>
<build>

View File

@ -23,6 +23,12 @@ import com.nflg.mobilebroken.repository.entity.*;
import com.nflg.mobilebroken.repository.service.*;
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@ -39,7 +45,9 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
@ -842,4 +850,309 @@ public class TicketController extends ControllerBase {
List<AdminTicketVO> datas = ticketService.exportSearch(request);
EecExcelUtil.export("工单报表", "sheet1", Convert.toList(AdminTicketReportVO.class, datas), response);
}
/**
* 导出工单详情为excel
* @param ticketId 工单编号
*/
@GetMapping("/exportTicketExcel")
@ApiMark(moduleName = "工单管理", apiName = "导出工单详情为excel")
public void exportExcel(HttpServletResponse response,@Valid @RequestParam @NotNull Integer ticketId) throws Exception {
Ticket ticket = ticketService.getById(ticketId);
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在");
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Sheet1");
sheet.setDefaultColumnWidth(8);
sheet.setDefaultRowHeightInPoints(20);
CellStyle centerStyle = getCenterStyle(workbook);
CellStyle normalStyle = getNormalStyle(workbook);
ClassPathResource resource = new ClassPathResource("images/logo.png");
InputStream inputStream = resource.getInputStream();
float height = 20;
byte[] imageBytes = IOUtils.toByteArray(inputStream);
int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
inputStream.close();
// 创建绘图对象
Drawing<?> drawing = sheet.createDrawingPatriarch();
// 创建锚点用于定位图片位置
ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
anchor.setCol1(0); // 起始列 0 开始
anchor.setRow1(0); // 起始行 0 开始
anchor.setCol2(3); // 结束列
anchor.setRow2(1); // 结束行
// 插入图片
drawing.createPicture(anchor, pictureIdx);
//标题行
Row row0 = sheet.createRow(0);
row0.setHeightInPoints(25);
row0.createCell(0).setCellStyle(centerStyle);
addMergedRegion(sheet,0, 0, 0, 2);
addMergedRegion(sheet,0, 0, 3, 11);
createCell(row0, 3, getTitleStyle(workbook), "CSF系统问题解决方案");
//第一行
Row row1 = sheet.createRow(1);
row1.setHeightInPoints(height);
createCell(row1, 0, centerStyle, "主题");
addMergedRegion(sheet,1, 1, 1, 4);
createCell(row1, 1, normalStyle, ticket.getTitle());
createCell(row1, 5, centerStyle, "事故等级");
createCell(row1, 6, centerStyle, "一般" + (Objects.equals(ticket.getAccidentLevel(), Byte.valueOf("0")) ? "\u2611" : "\u2610"));
createCell(row1, 7, normalStyle, "");
createCell(row1, 8, centerStyle, "较严重" + (Objects.equals(ticket.getAccidentLevel(), Byte.valueOf("1")) ? "\u2611" : "\u2610"));
createCell(row1, 9, normalStyle, "");
createCell(row1, 10, centerStyle, "严重" + (Objects.equals(ticket.getAccidentLevel(), Byte.valueOf("2")) ? "\u2611" : "\u2610"));
createCell(row1, 11, normalStyle, "");
//第二行
Row row2 = sheet.createRow(2);
row2.setHeightInPoints(height);
createCell(row2, 0, centerStyle, "工单编号");
addMergedRegion(sheet,2, 2, 1, 4);
createCell(row2, 1, normalStyle, ticket.getNo());
createCell(row2, 5, centerStyle, "设备编号");
addMergedRegion(sheet,2, 2, 6, 11);
createCell(row2, 6, normalStyle, ticket.getDeviceNo());
//第三行
Row row3 = sheet.createRow(3);
createCell(row3, 0, centerStyle, "提交人");
addMergedRegion(sheet,3, 3, 1, 4);
AppUser user = appUserService.getById(ticket.getUserId());
createCell(row3, 1, normalStyle, user.getName());
createCell(row3, 5, centerStyle, "反馈日期");
addMergedRegion(sheet,3, 3, 6, 11);
createCell(row3, 6, normalStyle, DateTimeUtil.format(ticket.getCreateTime()));
//第四行
Row row4 = sheet.createRow(4);
row4.setHeightInPoints(height);
createCell(row4, 0, centerStyle, "设备地点");
addMergedRegion(sheet,4, 4, 1, 4);
createCell(row4, 1, normalStyle, ticket.getDeviceAddress());
createCell(row4, 5, centerStyle, "处理人员");
addMergedRegion(sheet,4, 4, 6, 11);
createCell(row4, 6, normalStyle, ticket.getHandleName());
//第五行
Row row5 = sheet.createRow(5);
row5.setHeightInPoints(height);
createCell(row5, 0, centerStyle, "问题类型");
addMergedRegion(sheet,5, 5, 1, 4);
createCell(row5, 1, normalStyle, ticket.getQuestion());
createCell(row5, 5, centerStyle, "问题部位");
addMergedRegion(sheet,5, 5, 6, 11);
createCell(row5, 6, normalStyle, ticket.getComponent());
//第六行
Row row6 = sheet.createRow(6);
row6.setHeightInPoints(height);
createCell(row6, 0, centerStyle, "问题描述");
addMergedRegion(sheet,6, 6, 1, 11);
createCell(row6, 1, normalStyle, ticket.getDescription());
//第七行
Row row7 = sheet.createRow(7);
row7.setHeightInPoints(height);
List<FileInfo> images = new ArrayList<>();
if (StrUtil.isNotBlank(ticket.getAttachments())) {
StrUtil.split(ticket.getAttachments(), ",").forEach(item -> {
if (item.endsWith(".jpg") || item.endsWith(".png") || item.endsWith(".jpeg")) {
images.add(new FileInfo(item.substring(item.lastIndexOf("/") + 1), urlEncode(item)));
}
});
}
if (StrUtil.isNotBlank(ticket.getImages())) {
StrUtil.split(ticket.getImages(), ",").forEach(item -> {
images.add(new FileInfo(item.substring(item.lastIndexOf("/") + 1), item));
});
}
int rowIndex = 6;
int rows = images.size() % 2 == 0 ? images.size() / 2 : images.size() / 2 + 1;
if (rows > 1) {
addMergedRegion(sheet,rowIndex + 1, rowIndex + rows, 0, 0);
}
createCell(row7, 0, centerStyle, "案例照片");
if (rows == 0) {
addMergedRegion(sheet,rowIndex + 1, rowIndex + 1, 1, 5);
addMergedRegion(sheet,rowIndex + 1, rowIndex + 1, 6, 11);
rowIndex++;
} else {
for (int i = 0; i < images.size(); i++) {
if (i % 2 == 0) {
rowIndex++;
bindPic(images.get(i).getUrl(), workbook, sheet, rowIndex, 1, 6);
} else {
bindPic(images.get(i).getUrl(), workbook, sheet, rowIndex, 6, 12);
}
}
if (images.size() % 2 != 0) {
addMergedRegion(sheet,rowIndex, rowIndex, 6, 11);
}
}
rowIndex++;
Row row8 = sheet.createRow(rowIndex);
row8.setHeightInPoints(height);
addMergedRegion(sheet,rowIndex, rowIndex, 0, 11);
createCell(row8, 0, normalStyle, "根本原因分析");
rowIndex++;
Row row9 = sheet.createRow(rowIndex);
row9.setHeightInPoints(height);
addMergedRegion(sheet,rowIndex, rowIndex, 0, 11);
createCell(row9, 0, normalStyle, ticket.getReason());
//解决方案
List<TicketSolution> solutions = ticketSolutionService.lambdaQuery().eq(TicketSolution::getTicketId,ticketId).orderByAsc(TicketSolution::getId).list();
if (CollectionUtil.isNotEmpty(solutions)) {
Map<String, List<TicketSolution>> map=solutions.stream().collect(Collectors.groupingBy(TicketSolution::getDictionaryItemName, LinkedHashMap::new, Collectors.toList()));
for (Map.Entry<String, List<TicketSolution>> item : map.entrySet()) {
rowIndex++;
Row row10 = sheet.createRow(rowIndex);
row10.setHeightInPoints(height);
createCell(row10, 0, centerStyle, "No.");
addMergedRegion(sheet,rowIndex, rowIndex, 1, 6);
createCell(row10, 1, centerStyle, item.getKey());
createCell(row10, 7, centerStyle, "负责人");
createCell(row10, 8, centerStyle, "计划日期");
createCell(row10, 9, centerStyle, "确认日期");
addMergedRegion(sheet,rowIndex, rowIndex, 10, 11);
createCell(row10, 10, centerStyle, "备注");
for (int i = 0; i < item.getValue().size(); i++) {
rowIndex++;
TicketSolution solution = item.getValue().get(i);
Row row11 = sheet.createRow(rowIndex);
row11.setHeightInPoints(height);
createCell(row11, 0, centerStyle, String.valueOf(i + 1));
addMergedRegion(sheet,rowIndex, rowIndex, 1, 6);
createCell(row11, 1, normalStyle, solution.getDescription());
createCell(row11, 7, centerStyle, solution.getSuperintendent());
createCell(row11, 8, centerStyle, solution.getScheduleDate());
createCell(row11, 9, centerStyle, solution.getConfirmedDate());
addMergedRegion(sheet,rowIndex, rowIndex, 10, 11);
createCell(row11, 10, normalStyle, solution.getRemark());
}
}
}
//解决方案审核
List<SolutionReviewDepartmentVO> reviewDepartments = ticketSolutionAuditService.getByTicket(ticketId)
.stream()
.filter(vo -> StrUtil.isNotBlank(vo.getUserName()))
.collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(reviewDepartments)) {
rowIndex++;
Row row12 = sheet.createRow(rowIndex);
row12.setHeightInPoints(height);
addMergedRegion(sheet,rowIndex, rowIndex, 0, 11);
createCell(row12, 0, normalStyle, "相关部门审核确认");
rowIndex++;
Row row13 = sheet.createRow(rowIndex);
row13.setHeightInPoints(height);
Row row14 = sheet.createRow(rowIndex + 1);
row14.setHeightInPoints(height);
for (int i = 0; i < reviewDepartments.size(); i++) {
SolutionReviewDepartmentVO reviewDepartment = reviewDepartments.get(i);
addMergedRegion(sheet,rowIndex, rowIndex, i * 2, i * 2 + 1);
createCell(row13, i * 2, centerStyle, reviewDepartment.getDeptName() + "(" + reviewDepartment.getUserName() + ")");
addMergedRegion(sheet,rowIndex + 1, rowIndex + 1, i * 2, i * 2 + 1);
createCell(row14, i * 2, centerStyle, Objects.isNull(reviewDepartment.getState()) ? "" : (Objects.equals(reviewDepartment.getState(), 1) ? "通过" : "不通过"));
}
}
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=ticket.xlsx");
try (OutputStream outputStream = response.getOutputStream()) {
workbook.write(outputStream);
} finally {
workbook.close();
}
}
private void addMergedRegion(Sheet sheet,int firstRow, int lastRow, int firstCol, int lastCol){
CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
sheet.addMergedRegion(region);
RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet);
RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet);
RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet);
RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet);
}
private void createCell(Row row,int index,CellStyle style,String value){
Cell cell =row.createCell(index);
cell.setCellValue(value);
cell.setCellStyle(style);
}
private void bindPic(String url, Workbook workbook,Sheet sheet, int rowIndex, int colStart, int colEnd){
try {
byte[] imageBytes;
try (InputStream inputStream = new URL(url).openStream()) {
imageBytes = IOUtils.toByteArray(inputStream);
}
int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
Drawing<?> drawing = sheet.createDrawingPatriarch();
addMergedRegion(sheet,rowIndex,rowIndex,colStart,colEnd-1);
ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
anchor.setCol1(colStart);
anchor.setRow1(rowIndex);
anchor.setCol2(colEnd);
anchor.setRow2(rowIndex+1);
drawing.createPicture(anchor, pictureIdx);
Row row = sheet.getRow(rowIndex);
if (row == null) {
row = sheet.createRow(rowIndex);
}
row.setHeightInPoints(200);
}catch (Exception ex){
log.error("图片加载失败",ex);
}
}
private CellStyle getNormalStyle(Workbook workbook){
CellStyle centerStyle = workbook.createCellStyle();
centerStyle.setAlignment(HorizontalAlignment.LEFT);
centerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
Font normalFont = workbook.createFont();
normalFont.setFontName("DejaVu Sans"); // 设置字体名称
normalFont.setFontHeightInPoints((short) 8); // 设置字体大小单位为点
centerStyle.setFont(normalFont);
centerStyle.setBorderTop(BorderStyle.THIN); // 上边框
centerStyle.setBorderBottom(BorderStyle.THIN); // 下边框
centerStyle.setBorderLeft(BorderStyle.THIN); // 左边框
centerStyle.setBorderRight(BorderStyle.THIN); // 右边框
centerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框颜色
centerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框颜色
centerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框颜色
centerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框颜色
return centerStyle;
}
private CellStyle getCenterStyle(Workbook workbook){
CellStyle centerStyle = workbook.createCellStyle();
centerStyle.setAlignment(HorizontalAlignment.CENTER);
centerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
Font normalFont = workbook.createFont();
normalFont.setFontName("DejaVu Sans"); // 设置字体名称
normalFont.setFontHeightInPoints((short) 8); // 设置字体大小单位为点
centerStyle.setFont(normalFont);
centerStyle.setBorderTop(BorderStyle.THIN); // 上边框
centerStyle.setBorderBottom(BorderStyle.THIN); // 下边框
centerStyle.setBorderLeft(BorderStyle.THIN); // 左边框
centerStyle.setBorderRight(BorderStyle.THIN); // 右边框
centerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框颜色
centerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框颜色
centerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框颜色
centerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框颜色
return centerStyle;
}
private CellStyle getTitleStyle(Workbook workbook){
CellStyle titleStyle = workbook.createCellStyle();
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
Font fontTitle = workbook.createFont();
fontTitle.setFontName("DejaVu Sans"); // 设置字体名称
fontTitle.setFontHeightInPoints((short) 15); // 设置字体大小单位为点
fontTitle.setBold(true);
titleStyle.setFont(fontTitle);
titleStyle.setBorderTop(BorderStyle.THIN); // 上边框
titleStyle.setBorderBottom(BorderStyle.THIN); // 下边框
titleStyle.setBorderLeft(BorderStyle.THIN); // 左边框
titleStyle.setBorderRight(BorderStyle.THIN); // 右边框
titleStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框颜色
titleStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框颜色
titleStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框颜色
titleStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框颜色
return titleStyle;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB