diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/constant/enums/ModelTemplateTypeEnum.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/constant/enums/ModelTemplateTypeEnum.java new file mode 100644 index 0000000..a103345 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/constant/enums/ModelTemplateTypeEnum.java @@ -0,0 +1,19 @@ +package com.ruoyi.cms.constant.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 模型模板类型枚举 + * + * @author 马宝龙 + * @date 2026/7/2 + */ +@Getter +@AllArgsConstructor +public enum ModelTemplateTypeEnum { + + MODEL_WARNING_INDICATOR_DATA("劳动力动态监测系统-就业失业预警指标数据"), + ; + private final String desc; +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/ModelCommonController.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/ModelCommonController.java new file mode 100644 index 0000000..c423510 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/ModelCommonController.java @@ -0,0 +1,70 @@ +package com.ruoyi.cms.controller; + +import com.ruoyi.cms.constant.enums.ModelTemplateTypeEnum; +import com.ruoyi.cms.domain.dto.ModelExportParamDto; +import com.ruoyi.cms.service.ModelCommonService; +import com.ruoyi.common.core.domain.AjaxResult; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; + +/** + * 模型通用 + * + * @author 马宝龙 + * @date 2026/7/2 + */ +@RestController +@RequestMapping("/model/common") +@RequiredArgsConstructor +public class ModelCommonController { + + private final ModelCommonService modelCommonService; + + /** + * 下载导入模板 + * + * @param response 响应体 + * @param modelTemplateType 模型模板类型 + */ + @GetMapping("/template") + public void template(HttpServletResponse response, + @RequestParam ModelTemplateTypeEnum modelTemplateType) { + modelCommonService.template(response, modelTemplateType); + } + + /** + * 导入数据 + * + * @param file 文件 + * @param modelTemplateType 模型模板类型 + * @return 导入结果 + */ + @PostMapping("/import") + public AjaxResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam ModelTemplateTypeEnum modelTemplateType) { + String message = modelCommonService.importExcel(file, modelTemplateType); + return AjaxResult.success(message); + } + + /** + * 导出数据 + * + * @param response 响应体 + * @param dto 导出参数 + * @return 导出结果 + */ + @PostMapping("/export") + public AjaxResult exportExcel(HttpServletResponse response, + @RequestBody ModelExportParamDto dto) { + modelCommonService.exportExcel(response, dto); + return AjaxResult.success(); + } +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/dto/ModelExportParamDto.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/dto/ModelExportParamDto.java new file mode 100644 index 0000000..bfa39be --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/dto/ModelExportParamDto.java @@ -0,0 +1,32 @@ +package com.ruoyi.cms.domain.dto; + +import com.ruoyi.cms.constant.enums.ModelTemplateTypeEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 模型数据导出参数 + * + * @author 马宝龙 + * @date 2026/7/2 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ModelExportParamDto implements Serializable { + private static final long serialVersionUID = 2273746043886980704L; + + /** + * 模型模板类型 + */ + private ModelTemplateTypeEnum modelTemplateType; + /** + * 指标编码 + */ + private String indicatorCode; +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelCommonService.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelCommonService.java new file mode 100644 index 0000000..d581c18 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelCommonService.java @@ -0,0 +1,45 @@ +package com.ruoyi.cms.service; + +import com.ruoyi.cms.constant.enums.ModelTemplateTypeEnum; +import com.ruoyi.cms.domain.dto.ModelExportParamDto; +import com.ruoyi.common.core.domain.AjaxResult; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; + +/** + * 模型通用 + * + * @author 马宝龙 + * @date 2026/7/2 + */ +public interface ModelCommonService { + + /** + * 下载导入模板 + * + * @param response 响应体 + * @param modelTemplateType 模型模板类型 + */ + void template(HttpServletResponse response, ModelTemplateTypeEnum modelTemplateType); + + /** + * 导入数据 + * + * @param file 文件 + * @param modelTemplateType 模型模板类型 + * @return 导入结果 + */ + String importExcel(MultipartFile file, + ModelTemplateTypeEnum modelTemplateType); + + /** + * 导出数据 + * + * @param response 响应体 + * @param dto 导出参数 + */ + void exportExcel(HttpServletResponse response,ModelExportParamDto dto); +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelWarningIndicatorDataService.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelWarningIndicatorDataService.java index 6af68cc..70c7f02 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelWarningIndicatorDataService.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/ModelWarningIndicatorDataService.java @@ -1,7 +1,11 @@ package com.ruoyi.cms.service; +import com.ruoyi.cms.constant.enums.ModelTemplateTypeEnum; import com.ruoyi.cms.domain.ModelWarningIndicatorData; +import com.ruoyi.cms.domain.dto.ModelExportParamDto; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.util.List; /** @@ -48,4 +52,21 @@ public interface ModelWarningIndicatorDataService { * @return 列表 */ List list(ModelWarningIndicatorData modelWarningIndicatorData); + + + /** + * 导入数据 + * + * @param file 文件 + * @return 导入结果 + */ + String importExcel(MultipartFile file); + + /** + * 导出数据 + * + * @param response 响应体 + * @param dto 导出参数 + */ + void exportExcel(HttpServletResponse response, ModelExportParamDto dto); } \ No newline at end of file diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelCommonServiceImpl.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelCommonServiceImpl.java new file mode 100644 index 0000000..09bb447 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelCommonServiceImpl.java @@ -0,0 +1,113 @@ +package com.ruoyi.cms.service.impl; + +import com.ruoyi.cms.constant.enums.ModelTemplateTypeEnum; +import com.ruoyi.cms.domain.dto.ModelExportParamDto; +import com.ruoyi.cms.service.ModelCommonService; +import com.ruoyi.cms.service.ModelWarningIndicatorDataService; +import com.ruoyi.common.exception.ServiceException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +/** + * 模型通用 + * + * @author 马宝龙 + * @date 2026/7/2 + */ +@Slf4j +@Service +@Validated +@RequiredArgsConstructor +public class ModelCommonServiceImpl implements ModelCommonService { + + private final ModelWarningIndicatorDataService modelWarningIndicatorDataService; + + @Override + public void template(HttpServletResponse response, + ModelTemplateTypeEnum modelTemplateType) { + // 1. 构建资源文件路径(固定在resources/template) + String pathFile = modelTemplateType.getDesc() + ".xlsx"; + String filePath = "template/" + pathFile; + Resource resource = new ClassPathResource(filePath); + + // 2. 校验文件是否存在 + if (!resource.exists()) { + throw new ServiceException("模板文件不存在"); + } + + try (InputStream in = resource.getInputStream(); OutputStream out = response.getOutputStream()) { + + // 3. 设置响应头,使用传入的文件名作为下载名称 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + // 对文件名编码,解决中文乱码 + String encodedFileName = URLEncoder.encode(pathFile, StandardCharsets.UTF_8.name()) + .replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName); + + // 4. 读取文件流并写入响应 + byte[] buffer = new byte[1024]; + int len; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + out.flush(); + } catch (IOException e) { + log.error("文件下载失败", e); + throw new ServiceException("文件下载失败"); + } + } + + @Override + public String importExcel(MultipartFile file, ModelTemplateTypeEnum modelTemplateType) { + if (Objects.isNull(modelTemplateType)) { + throw new ServiceException("模板类型不能为空"); + } + switch (modelTemplateType) { + case MODEL_WARNING_INDICATOR_DATA: + return modelWarningIndicatorDataService.importExcel(file); + default: + throw new ServiceException("模板类型错误"); + } + } + + @Override + public void exportExcel(HttpServletResponse response, ModelExportParamDto dto) { + + if (Objects.isNull(dto) || Objects.isNull(dto.getModelTemplateType())) { + throw new ServiceException("模板类型不能为空"); + } + switch (dto.getModelTemplateType()) { + case MODEL_WARNING_INDICATOR_DATA: + modelWarningIndicatorDataService.exportExcel(response, dto); + break; + default: + throw new ServiceException("模板类型错误"); + } + try { + String pathFile = dto.getModelTemplateType().getDesc() + ".xlsx"; + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + // 对文件名编码,解决中文乱码 + String encodedFileName = URLEncoder.encode(pathFile, StandardCharsets.UTF_8.name()) + .replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName); + } catch (Exception e) { + log.error("文件参数设置失败", e); + throw new ServiceException("文件参数设置失败"); + } + } +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelWarningIndicatorDataServiceImpl.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelWarningIndicatorDataServiceImpl.java index cb80dd9..8f8c55e 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelWarningIndicatorDataServiceImpl.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ModelWarningIndicatorDataServiceImpl.java @@ -1,15 +1,22 @@ package com.ruoyi.cms.service.impl; +import com.ruoyi.cms.constant.enums.ModelTemplateTypeEnum; import com.ruoyi.cms.domain.ModelWarningIndicatorData; +import com.ruoyi.cms.domain.dto.ModelExportParamDto; import com.ruoyi.cms.mapper.ModelWarningIndicatorDataMapper; import com.ruoyi.cms.service.ModelWarningIndicatorDataService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanValidators; +import com.ruoyi.common.utils.poi.ExcelUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Validator; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -27,6 +34,7 @@ import java.util.Optional; public class ModelWarningIndicatorDataServiceImpl implements ModelWarningIndicatorDataService { private final ModelWarningIndicatorDataMapper modelWarningIndicatorDataMapper; + private final Validator validator; @Override public void create(ModelWarningIndicatorData modelWarningIndicatorData) { @@ -126,4 +134,70 @@ public class ModelWarningIndicatorDataServiceImpl implements ModelWarningIndicat public List list(ModelWarningIndicatorData modelWarningIndicatorData) { return modelWarningIndicatorDataMapper.list(modelWarningIndicatorData); } + + @Override + public String importExcel(MultipartFile file) { + try { + ExcelUtil util = new ExcelUtil<>(ModelWarningIndicatorData.class); + List list = util.importExcel(file.getInputStream()); + + ModelWarningIndicatorData exists; + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + for (ModelWarningIndicatorData item : list) { + try { + exists = modelWarningIndicatorDataMapper.findUnique(item); + if (exists == null) { + BeanValidators.validateWithException(validator, item); + modelWarningIndicatorDataMapper.insert(item); + successNum++; + String msg = + "
" + successNum + "、" + "指标:" + item.getIndicatorCode() + "(" + item.getRegionName() + ")" + item.getYear() + "年" + item.getMonth() + "月数据导入成功。"; + successMsg.append(msg); + } else { + item.setId(exists.getId()); + BeanValidators.validateWithException(validator, item); + modelWarningIndicatorDataMapper.update(item); + successNum++; + String msg = + "
" + successNum + "、" + "指标:" + item.getIndicatorCode() + "(" + item.getRegionName() + ")" + item.getYear() + "年" + item.getMonth() + "月数据更新成功。"; + successMsg.append(msg); + } + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、" + item.getYear() + "年" + item.getMonth() + "月数据导入失败:"; + failureMsg.append(msg).append(e.getMessage()); + log.error(msg, e); + } + } + if (failureNum > 0) { + failureMsg.insert(0, "导入失败!共 " + failureNum + " 条数据出现问题,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else { + successMsg.insert(0, "数据已全部导入成功!共 " + successNum + " 条:"); + } + return successMsg.toString(); + } catch (Exception e) { + log.error("数据导入失败", e); + throw new ServiceException("数据导入失败"); + } + } + + @Override + public void exportExcel(HttpServletResponse response, ModelExportParamDto dto) { + try { + + List list = list(ModelWarningIndicatorData.builder() + .indicatorCode(dto.getIndicatorCode()) + .build()); + ExcelUtil util = new ExcelUtil<>(ModelWarningIndicatorData.class); + util.exportExcel(response, list, ModelTemplateTypeEnum.MODEL_WARNING_INDICATOR_DATA.getDesc()); + + } catch (Exception e) { + log.error("数据导出失败", e); + throw new ServiceException("数据导出失败"); + } + } } \ No newline at end of file diff --git a/ruoyi-bussiness/src/main/resources/template/劳动力动态监测系统-就业失业预警指标数据.xlsx b/ruoyi-bussiness/src/main/resources/template/劳动力动态监测系统-就业失业预警指标数据.xlsx new file mode 100644 index 0000000..8caf773 Binary files /dev/null and b/ruoyi-bussiness/src/main/resources/template/劳动力动态监测系统-就业失业预警指标数据.xlsx differ