|
|
@@ -0,0 +1,360 @@
|
|
|
+package com.hotent.enterpriseDeclare.controller.material;
|
|
|
+
|
|
|
+import com.hotent.base.annotation.ApiGroup;
|
|
|
+import com.hotent.base.constants.ApiGroupConsts;
|
|
|
+import com.hotent.base.model.CommonResult;
|
|
|
+import com.hotent.base.util.StringUtil;
|
|
|
+import com.hotent.enterpriseDeclare.manager.CostSurveyTemplateUploadDataManager;
|
|
|
+import com.hotent.enterpriseDeclare.model.CostSurveyTemplateUploadData;
|
|
|
+import com.hotent.project.manager.CostProjectTaskMaterialManager;
|
|
|
+import com.hotent.project.model.CostProjectTaskMaterial;
|
|
|
+import com.hotent.surveyinfo.dao.CostSurveyTemplateHeadersDao;
|
|
|
+import com.hotent.surveyinfo.dao.CostSurveyTemplateItemsDao;
|
|
|
+import com.hotent.surveyinfo.manager.CostSurveyTemplateManager;
|
|
|
+import com.hotent.surveyinfo.manager.CostSurveyTemplateVersionManager;
|
|
|
+import com.hotent.surveyinfo.model.CostSurveyTemplate;
|
|
|
+import com.hotent.surveyinfo.model.CostSurveyTemplateHeaders;
|
|
|
+import com.hotent.surveyinfo.model.CostSurveyTemplateItems;
|
|
|
+import com.hotent.surveyinfo.model.CostSurveyTemplateVersion;
|
|
|
+import io.swagger.annotations.Api;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import io.swagger.annotations.ApiParam;
|
|
|
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
|
+import org.apache.poi.ss.usermodel.*;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 成本调查表
|
|
|
+ *
|
|
|
+ * @company 山西清众科技股份有限公司
|
|
|
+ * @author 超级管理员
|
|
|
+ * @since 2025-01-27
|
|
|
+ */
|
|
|
+@RestController
|
|
|
+@RequestMapping("/api/surveyTemplateExport/v1/")
|
|
|
+@Api(tags = "成本调查表")
|
|
|
+@ApiGroup(group = {ApiGroupConsts.GROUP_COST})
|
|
|
+public class CostProjectTaskSurveyTemplateExportController {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CostSurveyTemplateManager templateManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CostSurveyTemplateVersionManager versionManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CostSurveyTemplateHeadersDao headersDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CostSurveyTemplateItemsDao itemsDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CostSurveyTemplateUploadDataManager uploadDataManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CostProjectTaskMaterialManager costProjectTaskMaterialManager;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出成本调查表Excel
|
|
|
+ */
|
|
|
+ @GetMapping(value = "/exportExcel")
|
|
|
+ @ApiOperation(value = "导出成本调查表Excel", httpMethod = "GET")
|
|
|
+ public void exportExcel(
|
|
|
+ @ApiParam(name = "surveyTemplateId", value = "模板ID", required = true)
|
|
|
+ @RequestParam(required = true) String surveyTemplateId,
|
|
|
+ @ApiParam(name = "versionId", value = "版本ID", required = false)
|
|
|
+ @RequestParam(required = false) String versionId,
|
|
|
+ HttpServletResponse response) throws Exception {
|
|
|
+
|
|
|
+ CostSurveyTemplate template = templateManager.get(surveyTemplateId);
|
|
|
+ if (template == null) {
|
|
|
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到指定的调查模板");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ CostSurveyTemplateVersion currentVersion = StringUtil.isNotEmpty(versionId) ?
|
|
|
+ versionManager.get(versionId) : versionManager.selectCurrentVersion(surveyTemplateId);
|
|
|
+
|
|
|
+ if (currentVersion == null) {
|
|
|
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到指定的模板版本");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CostSurveyTemplateHeaders> headersList = headersDao.selectBySurveyTemplateIdAndVersion(
|
|
|
+ surveyTemplateId, currentVersion.getId()).stream()
|
|
|
+ .filter(header -> StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible()))
|
|
|
+ .sorted(Comparator.comparing(header -> {
|
|
|
+ String orderNum = header.getOrderNum();
|
|
|
+ return StringUtil.isEmpty(orderNum) ? Integer.MAX_VALUE :
|
|
|
+ Integer.parseInt(orderNum.replaceAll("\\D", "0"));
|
|
|
+ }))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (headersList.isEmpty()) {
|
|
|
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到表头信息");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CostSurveyTemplateItems> itemsList = itemsDao.selectBySurveyTemplateIdAndVersion(
|
|
|
+ surveyTemplateId, currentVersion.getId());
|
|
|
+
|
|
|
+ Workbook workbook = new XSSFWorkbook();
|
|
|
+ String sheetName = currentVersion.getSurveyTemplateName() != null ?
|
|
|
+ currentVersion.getSurveyTemplateName() : "成本调查表";
|
|
|
+ Sheet sheet = workbook.createSheet(sheetName);
|
|
|
+
|
|
|
+ Row headerRow = sheet.createRow(0);
|
|
|
+ for (int i = 0; i < headersList.size(); i++) {
|
|
|
+ headerRow.createCell(i).setCellValue(headersList.get(i).getFieldName());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (itemsList != null && !itemsList.isEmpty()) {
|
|
|
+ Map<String, Integer> headerIndexMap = new HashMap<>();
|
|
|
+ for (int i = 0; i < headersList.size(); i++) {
|
|
|
+ headerIndexMap.put(headersList.get(i).getId(), i);
|
|
|
+ }
|
|
|
+ fillExcelData(sheet, itemsList, headerIndexMap, template.getTemplateType());
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < headersList.size(); i++) {
|
|
|
+ sheet.autoSizeColumn(i);
|
|
|
+ sheet.setColumnWidth(i, Math.max(sheet.getColumnWidth(i), 3000));
|
|
|
+ }
|
|
|
+
|
|
|
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
|
+ response.setCharacterEncoding("utf-8");
|
|
|
+ String fileName = sheetName + "_" + System.currentTimeMillis() + ".xlsx";
|
|
|
+ response.setHeader("Content-Disposition", "attachment; filename=" +
|
|
|
+ URLEncoder.encode(fileName, "UTF-8"));
|
|
|
+
|
|
|
+ workbook.write(response.getOutputStream());
|
|
|
+ workbook.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导入成本调查表Excel数据
|
|
|
+ */
|
|
|
+ @PostMapping(value = "/importExcel")
|
|
|
+ @ApiOperation(value = "导入成本调查表Excel数据", httpMethod = "POST")
|
|
|
+ public CommonResult<String> importExcel(
|
|
|
+ @ApiParam(name = "file", value = "Excel文件", required = true)
|
|
|
+ @RequestParam("file") MultipartFile file,
|
|
|
+ @ApiParam(name = "surveyTemplateId", value = "模板ID", required = true)
|
|
|
+ @RequestParam(required = true) String surveyTemplateId,
|
|
|
+ @ApiParam(name = "taskId", value = "任务ID", required = true)
|
|
|
+ @RequestParam(required = true) String taskId,
|
|
|
+ @ApiParam(name = "materialId", value = "材料ID", required = true)
|
|
|
+ @RequestParam(required = true) String materialId,
|
|
|
+ @ApiParam(name = "periodRecordId", value = "监审期间记录ID", required = false)
|
|
|
+ @RequestParam(required = false) String periodRecordId) throws Exception {
|
|
|
+
|
|
|
+ if (file == null || file.isEmpty()) {
|
|
|
+ return CommonResult.<String>error().message("上传文件不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String fileName = file.getOriginalFilename();
|
|
|
+ if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
|
|
|
+ return CommonResult.<String>error().message("文件格式不正确,请上传Excel文件");
|
|
|
+ }
|
|
|
+
|
|
|
+ CostSurveyTemplate template = templateManager.get(surveyTemplateId);
|
|
|
+ if (template == null) {
|
|
|
+ return CommonResult.<String>error().message("未找到指定的调查模板");
|
|
|
+ }
|
|
|
+
|
|
|
+ CostSurveyTemplateVersion currentVersion = versionManager.selectCurrentVersion(surveyTemplateId);
|
|
|
+ if (currentVersion == null) {
|
|
|
+ return CommonResult.<String>error().message("未找到启用的模板版本");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CostSurveyTemplateHeaders> headersList = headersDao.selectBySurveyTemplateIdAndVersion(
|
|
|
+ surveyTemplateId, currentVersion.getId()).stream()
|
|
|
+ .filter(header -> StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (headersList.isEmpty()) {
|
|
|
+ return CommonResult.<String>error().message("未找到表头信息");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, CostSurveyTemplateHeaders> headerNameMap = headersList.stream()
|
|
|
+ .filter(header -> StringUtil.isNotEmpty(header.getFieldName()))
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ header -> header.getFieldName().trim(),
|
|
|
+ header -> header
|
|
|
+ ));
|
|
|
+
|
|
|
+ Workbook workbook = null;
|
|
|
+ try (InputStream inputStream = file.getInputStream()) {
|
|
|
+ workbook = fileName.endsWith(".xlsx") ?
|
|
|
+ new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream);
|
|
|
+
|
|
|
+ Sheet sheet = workbook.getSheetAt(0);
|
|
|
+ if (sheet == null || sheet.getPhysicalNumberOfRows() < 2) {
|
|
|
+ return CommonResult.<String>error().message("Excel文件没有数据");
|
|
|
+ }
|
|
|
+
|
|
|
+ Row headerRow = sheet.getRow(0);
|
|
|
+ if (headerRow == null) {
|
|
|
+ return CommonResult.<String>error().message("Excel文件第一行为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Integer, CostSurveyTemplateHeaders> columnIndexMap = new HashMap<>();
|
|
|
+ for (int i = 0; i < headerRow.getLastCellNum(); i++) {
|
|
|
+ Cell cell = headerRow.getCell(i);
|
|
|
+ if (cell != null) {
|
|
|
+ String cellValue = getCellStringValue(cell);
|
|
|
+ if (StringUtil.isNotEmpty(cellValue)) {
|
|
|
+ CostSurveyTemplateHeaders header = headerNameMap.get(cellValue.trim());
|
|
|
+ if (header != null) {
|
|
|
+ columnIndexMap.put(i, header);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (columnIndexMap.isEmpty()) {
|
|
|
+ return CommonResult.<String>error().message("Excel表头与模板表头不匹配");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CostSurveyTemplateUploadData> dataList = new ArrayList<>();
|
|
|
+ int dataRowCount = 0;
|
|
|
+
|
|
|
+ for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
+ Row dataRow = sheet.getRow(rowIndex);
|
|
|
+ if (dataRow == null || isEmptyRow(dataRow)) continue;
|
|
|
+
|
|
|
+ String currentRowId = "1".equals(template.getTemplateType()) ?
|
|
|
+ "row_" + System.currentTimeMillis() : "row_" + rowIndex;
|
|
|
+
|
|
|
+ for (Map.Entry<Integer, CostSurveyTemplateHeaders> entry : columnIndexMap.entrySet()) {
|
|
|
+ Cell cell = dataRow.getCell(entry.getKey());
|
|
|
+ String cellValue = getCellStringValue(cell);
|
|
|
+
|
|
|
+ if (StringUtil.isNotEmpty(cellValue)) {
|
|
|
+ CostSurveyTemplateUploadData uploadData = createUploadData(
|
|
|
+ surveyTemplateId, taskId, materialId, currentRowId,
|
|
|
+ entry.getValue(), cellValue, periodRecordId);
|
|
|
+ dataList.add(uploadData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dataRowCount++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dataList.isEmpty()) {
|
|
|
+ return CommonResult.<String>error().message("Excel文件中没有有效数据");
|
|
|
+ }
|
|
|
+
|
|
|
+ uploadDataManager.saveData(dataList);
|
|
|
+ CostProjectTaskMaterial material = costProjectTaskMaterialManager.getById(materialId);
|
|
|
+ material.setIsUpload("1");
|
|
|
+ costProjectTaskMaterialManager.updateById(material);
|
|
|
+
|
|
|
+ return CommonResult.<String>ok().message("导入成功,共导入 " + dataRowCount + " 行数据");
|
|
|
+ } catch (Exception e) {
|
|
|
+ return CommonResult.<String>error().message("导入失败:" + e.getMessage());
|
|
|
+ } finally {
|
|
|
+ if (workbook != null) {
|
|
|
+ workbook.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void fillExcelData(Sheet sheet, List<CostSurveyTemplateItems> itemsList,
|
|
|
+ Map<String, Integer> headerIndexMap, String templateType) {
|
|
|
+ if ("1".equals(templateType)) {
|
|
|
+ Row dataRow = sheet.createRow(1);
|
|
|
+ for (CostSurveyTemplateItems item : itemsList) {
|
|
|
+ Integer colIndex = headerIndexMap.get(item.getHeadersId());
|
|
|
+ if (colIndex != null) {
|
|
|
+ dataRow.createCell(colIndex).setCellValue(getItemValue(item));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Map<String, List<CostSurveyTemplateItems>> itemsByRowId = itemsList.stream()
|
|
|
+ .filter(item -> StringUtil.isNotEmpty(item.getRowid()))
|
|
|
+ .collect(Collectors.groupingBy(CostSurveyTemplateItems::getRowid));
|
|
|
+
|
|
|
+ int rowNum = 1;
|
|
|
+ for (Map.Entry<String, List<CostSurveyTemplateItems>> entry : itemsByRowId.entrySet()) {
|
|
|
+ Row dataRow = sheet.createRow(rowNum++);
|
|
|
+ for (CostSurveyTemplateItems item : entry.getValue()) {
|
|
|
+ Integer colIndex = headerIndexMap.get(item.getHeadersId());
|
|
|
+ if (colIndex != null) {
|
|
|
+ dataRow.createCell(colIndex).setCellValue(getItemValue(item));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getItemValue(CostSurveyTemplateItems item) {
|
|
|
+ return StringUtil.isNotEmpty(item.getRvalue()) ? item.getRvalue() :
|
|
|
+ StringUtil.isNotEmpty(item.getJsonStr()) ? item.getJsonStr() : "";
|
|
|
+ }
|
|
|
+
|
|
|
+ private CostSurveyTemplateUploadData createUploadData(String surveyTemplateId, String taskId,
|
|
|
+ String materialId, String rowid,
|
|
|
+ CostSurveyTemplateHeaders header,
|
|
|
+ String value, String periodRecordId) {
|
|
|
+ CostSurveyTemplateUploadData uploadData = new CostSurveyTemplateUploadData();
|
|
|
+ uploadData.setSurveyTemplateId(surveyTemplateId);
|
|
|
+ uploadData.setTaskId(taskId);
|
|
|
+ uploadData.setRowid(rowid);
|
|
|
+ uploadData.setRkey(StringUtil.isNotEmpty(header.getFieldEname()) ?
|
|
|
+ header.getFieldEname() : header.getFieldName());
|
|
|
+ uploadData.setRvalue(value);
|
|
|
+ if (StringUtil.isNotEmpty(periodRecordId)) {
|
|
|
+ uploadData.setPeriodRecordId(periodRecordId);
|
|
|
+ }
|
|
|
+ uploadData.setIsDeleted("0");
|
|
|
+ return uploadData;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getCellStringValue(Cell cell) {
|
|
|
+ if (cell == null) return "";
|
|
|
+
|
|
|
+ switch (cell.getCellType()) {
|
|
|
+ case STRING: return cell.getStringCellValue();
|
|
|
+ case NUMERIC:
|
|
|
+ if (DateUtil.isCellDateFormatted(cell)) {
|
|
|
+ return cell.getDateCellValue().toString();
|
|
|
+ } else {
|
|
|
+ double numericValue = cell.getNumericCellValue();
|
|
|
+ return numericValue == (long) numericValue ?
|
|
|
+ String.valueOf((long) numericValue) : String.valueOf(numericValue);
|
|
|
+ }
|
|
|
+ case BOOLEAN: return String.valueOf(cell.getBooleanCellValue());
|
|
|
+ case FORMULA:
|
|
|
+ try {
|
|
|
+ return cell.getStringCellValue();
|
|
|
+ } catch (Exception e) {
|
|
|
+ try {
|
|
|
+ return String.valueOf(cell.getNumericCellValue());
|
|
|
+ } catch (Exception ex) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default: return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isEmptyRow(Row row) {
|
|
|
+ for (int colIndex = 0; colIndex < row.getLastCellNum(); colIndex++) {
|
|
|
+ Cell cell = row.getCell(colIndex);
|
|
|
+ if (cell != null && StringUtil.isNotEmpty(getCellStringValue(cell))) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|