diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/vo/order/OrderGoodsPlateRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/vo/order/OrderGoodsPlateRespVO.java index 5396f1470..e3cc50467 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/vo/order/OrderGoodsPlateRespVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/vo/order/OrderGoodsPlateRespVO.java @@ -27,7 +27,7 @@ public class OrderGoodsPlateRespVO implements Comparable private String color; @Schema(description = "纹路") - private Integer texture; + private Boolean texture; @Schema(description = "宽度", requiredMode = Schema.RequiredMode.REQUIRED) private BigDecimal width; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java index c5d0ae2cf..7af9befd8 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java @@ -33,6 +33,7 @@ import com.cf.imes.module.system.api.dict.DictDataApi; import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO; import com.cf.imes.module.system.enums.DictTypeConstants; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -290,12 +291,10 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { seriesItem.put("id", entry.getKey()); // 材质-商品名称-颜色-纹理-宽-高-厚-品牌 OrderGoodsPlateRespVO orderGoodsPlateRespVO = entry.getValue(); - // 获取纹路描述 - DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(orderGoodsPlateRespVO.getTexture())).getData(); - String texture = ObjectUtil.isNotNull(grainDTO) ? grainDTO.getLabel() : ""; - seriesItem.put("name", orderGoodsPlateRespVO.getMaterial() + "-" + orderGoodsPlateRespVO.getGoodsName() + - "-" + orderGoodsPlateRespVO.getColor() + "-" + texture + "-" + stripTrailingZeros(orderGoodsPlateRespVO.getWidth()) + - "×" + stripTrailingZeros(orderGoodsPlateRespVO.getHeight()) + "×" + stripTrailingZeros(orderGoodsPlateRespVO.getThickness()) + "-" + orderGoodsPlateRespVO.getBrand()); + String specification = formatGoodsName('x', stripTrailingZeros(orderGoodsPlateRespVO.getWidth()), + stripTrailingZeros(orderGoodsPlateRespVO.getHeight()), stripTrailingZeros(orderGoodsPlateRespVO.getThickness())); + String goodsName = formatGoodsName('-', orderGoodsPlateRespVO.getMaterial(), orderGoodsPlateRespVO.getGoodsName(), orderGoodsPlateRespVO.getColor(), getTextureFromDict(orderGoodsPlateRespVO.getTexture()), specification, orderGoodsPlateRespVO.getBrand()); + seriesItem.put("name", goodsName); series.add(seriesItem); } resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, reqVO.getUnit())).toList()); @@ -362,12 +361,10 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { seriesItem.put("id", entry.getKey()); // 材质-商品名称-颜色-纹理-宽-高-厚-品牌 OrderGoodsPlateRespVO orderGoodsPlateRespVO = entry.getValue(); - // 获取纹路描述 - DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(orderGoodsPlateRespVO.getTexture())).getData(); - String texture = ObjectUtil.isNotNull(grainDTO) ? grainDTO.getLabel() : ""; - seriesItem.put("name", orderGoodsPlateRespVO.getMaterial() + "-" + orderGoodsPlateRespVO.getGoodsName() + - "-" + orderGoodsPlateRespVO.getColor() + "-" + texture + "-" + stripTrailingZeros(orderGoodsPlateRespVO.getWidth()) + - "×" + stripTrailingZeros(orderGoodsPlateRespVO.getHeight()) + "×" + stripTrailingZeros(orderGoodsPlateRespVO.getThickness()) + "-" + orderGoodsPlateRespVO.getBrand()); + String specification = formatGoodsName('x', stripTrailingZeros(orderGoodsPlateRespVO.getWidth()), + stripTrailingZeros(orderGoodsPlateRespVO.getHeight()), stripTrailingZeros(orderGoodsPlateRespVO.getThickness())); + String goodsName = formatGoodsName('-', orderGoodsPlateRespVO.getMaterial(), orderGoodsPlateRespVO.getGoodsName(), orderGoodsPlateRespVO.getColor(), getTextureFromDict(orderGoodsPlateRespVO.getTexture()), specification, orderGoodsPlateRespVO.getBrand()); + seriesItem.put("name", goodsName); series.add(seriesItem); } resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, reqVO.getUnit())).toList()); @@ -485,9 +482,10 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { } // 任意取一个类型 PlateGoodDO plateGoodDO = plateGoodDOList.get(0); - seriesItem.put("name", plateGoodDO.getMaterial() + "-" + plateGoodDO.getGoodsName() + - "-" + plateGoodDO.getColor() + "-" + getTextureFromDict(plateGoodDO) + "-" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getWidth())) + - "×" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getHeight())) + "×" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getThickness())) + "-" + plateGoodDO.getBrand()); + String specification = formatGoodsName('x', stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getWidth())), + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getHeight())), stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getThickness()))); + String goodsName = formatGoodsName('-', plateGoodDO.getMaterial(), plateGoodDO.getGoodsName(), plateGoodDO.getColor(), getTextureFromDict(plateGoodDO.getTexture()), specification, plateGoodDO.getBrand()); + seriesItem.put("name", goodsName); series.add(seriesItem); } resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, unit)).toList()); @@ -498,18 +496,44 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { return resultMap; } + /** + * 板材信息用-连接 + * + * @param connChar 连接符 + * @param texts 信息内容 + * @return 为空时不带connChar + */ + private String formatGoodsName(char connChar, String... texts) { + StringBuilder sb = new StringBuilder(); + for (String text : texts) { + if (StringUtils.isNotEmpty(text)) { + sb.append(text).append(connChar); + } + } + // 移除最后一个 - + if (sb.length() > 0 && sb.charAt(sb.length() - 1) == connChar) { + sb.deleteCharAt(sb.length() - 1); + } + return sb.toString(); + } + + /** * 根据纹路枚举获取字典中纹路描述 - * @param plateGoodDO + * + * @param texture * @return */ - private String getTextureFromDict(PlateGoodDO plateGoodDO) { + private String getTextureFromDict(Boolean texture) { + if (ObjectUtil.isNull(texture)) { + return "无"; + } // 获取纹路描述 - DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(plateGoodDO.getTexture())).getData(); + DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.PLATE_TEXTURE_TYPE, String.valueOf(texture)).getData(); if (ObjectUtil.isNotNull(grainDTO)) { - return grainDTO.getLabel(); + return Objects.equals("是", grainDTO.getLabel()) ? "有" : "无"; } else { - return ""; + return "无"; } } diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java index deef36ac7..8e9d6de5f 100644 --- a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java @@ -17,6 +17,8 @@ public final class ErrorCodeConstants { // ========== UREPORT datasource模块 1-003-002-000 ========== public static final ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在"); public static final ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_002, "报表数据源连接失败"); + public static final ErrorCode DATASOURCE_SPRINGBEAN_GET_FAIL = new ErrorCode(1_003_002_003, "无法获取springbean【{}】"); + public static final ErrorCode DATASOURCE_SPRINGBEAN_METHODS_GET_FAIL = new ErrorCode(1_003_002_004, "获取springbean方法列表失败,请检查】"); // ========== UREPORT dataset模块 1-003-003-000 ========== diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java index d0e31458e..6b882d43a 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java @@ -52,7 +52,7 @@ public class ReportDatasetController { @DeleteMapping("/dataset/{id}") @Operation(summary = "删除报表数据集") - @Parameter(name = "id", description = "编号", required = true) + @Parameter(name = "id", description = "数据集id", required = true) // @PreAuthorize("@ss.hasPermission('report:dataset:delete')") public CommonResult deleteDataset(@PathVariable("id") Long id) { datasetService.deleteDataset(id); @@ -61,7 +61,7 @@ public class ReportDatasetController { @GetMapping("/dataset/{id}") @Operation(summary = "获得报表数据集") - @Parameter(name = "id", description = "编号", required = true, example = "1") + @Parameter(name = "id", description = "数据集id", required = true, example = "1") // @PreAuthorize("@ss.hasPermission('report:dataset:query')") public CommonResult getDataset(@PathVariable("id") Long id) { ReportDatasetDO dataset = datasetService.getDataset(id); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java index c9f73d2da..a2124531d 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java @@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import java.util.List; import java.util.Map; @@ -69,7 +70,7 @@ public class ReportDatasourceController { @DeleteMapping("/datasource/{id}") @Operation(summary = "删除报表数据源") - @Parameter(name = "id", description = "编号", required = true, example = "1") + @Parameter(name = "id", description = "数据源id", required = true, example = "1") // @PreAuthorize("@ss.hasPermission('report:datasource:delete')") public CommonResult deleteDatasource(@PathVariable("id") Long id) { datasourceService.deleteDatasource(id); @@ -78,7 +79,7 @@ public class ReportDatasourceController { @GetMapping("/datasource/{id}") @Operation(summary = "获取报表数据源") - @Parameter(name = "id", description = "编号", required = true, example = "1") + @Parameter(name = "id", description = "数据源id", required = true, example = "1") // @PreAuthorize("@ss.hasPermission('report:datasource:query')") public CommonResult getDatasource(@PathVariable("id") Long id) { ReportDatasourceDO datasource = datasourceService.getDatasource(id); @@ -88,6 +89,7 @@ public class ReportDatasourceController { @GetMapping("/{templateId}/datasources") @Operation(summary = "获取报表模板下的报表数据源") // @PreAuthorize("@ss.hasPermission('report:datasource:query')") + @Parameter(name = "templateId", description = "模版id", required = true) public CommonResult> getDatasourcePage(@PathVariable(value = "templateId") Long templateId) { return success(BeanUtils.toBean(datasourceService.getTemplateDatasourceList(ReportDatasourceReqVO.builder().templateId(templateId).build()), ReportDatasourceRespVO.class)); } @@ -99,10 +101,18 @@ public class ReportDatasourceController { return success(datasourceService.getBeanDatasourceList()); } + @GetMapping("/springbean/result/clazz") + @Operation(summary = "获取springbean数据源返回对象") + @Parameter(name = "clazz", description = "返回对象类路径全名不能为空", required = true) + public List springbeanFieldList(@RequestParam(value = "clazz") @NotEmpty(message = "类路径全名不能为空") String clazz) { + return datasourceService.getSpringBeanResultFieldList(clazz); + } + @GetMapping("/datasource/bean/methods") @Operation(summary = "获取springbean数据源方法类表") // @PreAuthorize("@ss.hasPermission('report:datasource:query')") - public CommonResult> getBeanDatasourceList(@RequestParam(value = "beanId") String beanId) { + @Parameter(name = "beanId", description = "springbeanId", required = true) + public CommonResult> getBeanDatasourceList(@RequestParam(value = "beanId") @NotEmpty(message = "beanId不能为空") String beanId) { return success(datasourceService.loadBeanMethods(beanId)); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java index 0d9bee876..2311a4ef7 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java @@ -39,6 +39,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import java.io.OutputStream; import java.util.HashMap; @@ -79,7 +80,7 @@ public class ReportTemplateController { @DeleteMapping("/template/{id}") @Operation(summary = "删除报表模板信息") - @Parameter(name = "id", description = "编号", required = true) + @Parameter(name = "id", description = "模板id", required = true) // @PreAuthorize("@ss.hasPermission('report:template:delete')") public CommonResult deleteReportTemplate(@PathVariable("id") Long id) { templateService.deleteReportTemplate(id); @@ -88,7 +89,7 @@ public class ReportTemplateController { @GetMapping("/template/{id}") @Operation(summary = "获取报表模板信息") - @Parameter(name = "id", description = "编号", required = true, example = "1") + @Parameter(name = "id", description = "模板id", required = true, example = "1") // @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult getReportTemplate(@PathVariable("id") Long id) { return success(templateService.getReportTemplateDefinition(id)); @@ -141,7 +142,7 @@ public class ReportTemplateController { @GetMapping("/scriptValidation") @Operation(summary = "校验表达式") @Parameter(name = "content", description = "表达式", required = true) - public List scriptValidation(@Param("content") String content) { + public List scriptValidation(@Param("content") @NotEmpty(message = "表达式不能为空") String content) { content = StringUtils.decode(content); ANTLRInputStream antlrInputStream = new ANTLRInputStream(content); ReportParserLexer lexer = new ReportParserLexer(antlrInputStream); @@ -163,7 +164,7 @@ public class ReportTemplateController { @GetMapping("/parseDataSet") @Operation(summary = "解析表达式中的数据集") @Parameter(name = "expr", description = "表达式", required = true) - public Map parseDatasetName(@Param("expr") String expr) { + public Map parseDatasetName(@Param("expr") @NotEmpty(message = "表达式不能为空") String expr) { ANTLRInputStream antlrInputStream = new ANTLRInputStream(expr); ReportParserLexer lexer = new ReportParserLexer(antlrInputStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockSpringBeanDatasourceResult.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockSpringBeanDatasourceResult.java new file mode 100644 index 000000000..ab7334c59 --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockSpringBeanDatasourceResult.java @@ -0,0 +1,16 @@ +package com.cf.imes.module.report.framework.ureport.bean; + +import lombok.Data; +import org.springframework.stereotype.Component; + +/** + * @author Gqr + * @since 2024/8/30 11:21 + */ +@Component +@Data +public class MockSpringBeanDatasourceResult { + private String key; + + private String value; +} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java index a87036e9b..e459a74a3 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java @@ -78,5 +78,11 @@ public interface ReportDatasourceService { */ List getTableFields(PreviewParams previewParams); - + /** + * 获取数据源 + * + * @param clazz + * @return + */ + List getSpringBeanResultFieldList(String clazz); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java index 41c87841c..4f3dbeb49 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java @@ -1,9 +1,11 @@ package com.cf.imes.module.report.service.datasource; import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils; +import com.bstek.common.exception.ReportDesignException; import com.bstek.common.utils.MultipleJdbcTemplate; import com.bstek.datasource.bean.DataSourceInfo; import com.bstek.datasource.bean.PreviewParams; @@ -12,6 +14,7 @@ import com.bstek.ureport.definition.dataset.Parameter; import com.bstek.ureport.definition.dataset.SqlDatasetDefinition; import com.bstek.ureport.utils.ProcedureUtils; import com.cf.imes.framework.common.exception.ServiceException; +import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetReqVO; @@ -27,6 +30,7 @@ import com.cf.imes.module.report.service.dataset.ReportDatasetService; import com.cf.imes.module.report.util.SqlInjectionUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @@ -37,6 +41,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.sql.DataSource; +import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.ResultSetMetaData; @@ -51,6 +56,8 @@ import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_SQL_ILL import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_SQL_INJECTION_RISK; import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_SQL_REQUIRED; import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASOURCE_NOT_EXISTS; +import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASOURCE_SPRINGBEAN_GET_FAIL; +import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASOURCE_SPRINGBEAN_METHODS_GET_FAIL; /** * 报表数据源 Service 实现类 @@ -156,29 +163,39 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { @Override public List loadBeanMethods(String beanId) { - Object obj = applicationContext.getBean(beanId); - Class clazz = obj.getClass(); - Method[] methods = clazz.getMethods(); + Object obj; List result = new ArrayList(); - // ureport的springbean方法必须满足(String dsName, String datasetName, Map parameters) - for (Method method : methods) { - Class[] types = method.getParameterTypes(); - if (types.length != 3) { - continue; + try { + obj = applicationContext.getBean(beanId); + Class clazz = obj.getClass(); + Method[] methods = clazz.getMethods(); + + // ureport的springbean方法必须满足(String dsName, String datasetName, Map parameters) + for (Method method : methods) { + Class[] types = method.getParameterTypes(); + if (types.length != 3) { + continue; + } + Class typeClass1 = types[0]; + Class typeClass2 = types[1]; + Class typeClass3 = types[2]; + if (!String.class.isAssignableFrom(typeClass1)) { + continue; + } + if (!String.class.isAssignableFrom(typeClass2)) { + continue; + } + if (!Map.class.isAssignableFrom(typeClass3)) { + continue; + } + result.add(method.getName()); } - Class typeClass1 = types[0]; - Class typeClass2 = types[1]; - Class typeClass3 = types[2]; - if (!String.class.isAssignableFrom(typeClass1)) { - continue; - } - if (!String.class.isAssignableFrom(typeClass2)) { - continue; - } - if (!Map.class.isAssignableFrom(typeClass3)) { - continue; - } - result.add(method.getName()); + } catch (BeansException e) { + log.error("[ReportDatasourceService][loadBeanMethods]获取bean失败", e); + throw ServiceExceptionUtil.exception(DATASOURCE_SPRINGBEAN_GET_FAIL, beanId); + } catch (Exception e) { + log.error("[ReportDatasourceService][loadBeanMethods]方法列表获取异常", e); + throw ServiceExceptionUtil.exception(DATASOURCE_SPRINGBEAN_METHODS_GET_FAIL); } return result; } @@ -241,6 +258,26 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { } } + @Override + public List getSpringBeanResultFieldList(String clazz) { + List result = new ArrayList(); + try { + Class targetClass = Class.forName(clazz); + PropertyDescriptor[] propertyDescriptors = BeanUtil.getPropertyDescriptors(targetClass); + for (PropertyDescriptor pd : propertyDescriptors) { + String name = pd.getName(); + if ("class".equals(name)) { + continue; + } + result.add(new Field(name)); + } + return result; + + } catch (Exception ex) { + throw new ReportDesignException(ex); + } + } + /** * 查询数据源下的数据集 * diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index ed9ae8b6d..dd9c515b3 100644 Binary files a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar and b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar differ diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java index c90abdc77..b79a1396f 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java @@ -27,6 +27,7 @@ public interface DictTypeConstants { String SMS_RECEIVE_STATUS = "system_sms_receive_status"; // 短信接收状态 String TYPOGRAPHY_TYPE = "typographyType"; // 排版面 + String PLATE_TEXTURE_TYPE = "plate_texture_type";// 板材纹路:0有 1无 String GRAIN_TYPE = "grainType";//纹路类型 String DOOR_OPENING_DIRECTIONS = "doorOpeningDirections";//开门方向 String PRODUCT_TYPE = "productType";//产品类型 @@ -36,7 +37,6 @@ public interface DictTypeConstants { String HOLE_FACE = "hole_face";//孔加工面 String HOLE_DIR = "hole_direction";// 孔方向 String HOLE_TYPE = "hole_type";//孔类型 - String PLATE_TEXTURE_TYPE = "plateTextureType";//板件纹路类型 String PLATE_TEXTURE_TYPE_STATUS = "plateTextureTypeStatus";//板件纹路状态 String PLATE_TEXTURE_TYPE_STATUS_TYPE = "plateTextureTypeStatusType";//板件纹路状态类型 } diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 910f015b4..1d174cbc3 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -46,18 +46,15 @@ public interface ErrorCodeConstants { ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用"); ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过组织最大组织配额({})!"); ErrorCode USER_ME_ERROR = new ErrorCode(1_002_003_009, "不允许操作用户自身"); - - ErrorCode THE_PASSWORD_LENGTH_MUST_BE_AT_LEAST_6_CHARACTERS = new ErrorCode(1_002_003_010, "密码长度必须至少为6个字符"); - - ErrorCode THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_LETTER = new ErrorCode(1_002_003_011, "密码必须包含至少一个字母"); - + ErrorCode THE_PASSWORD_LENGTH_MUST_BE_AT_LEAST_8_CHARACTERS = new ErrorCode(1_002_003_010, "密码长度必须至少为8个字符"); + ErrorCode THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_LOWER_LETTER = new ErrorCode(1_002_003_011, "密码必须包含至少一个小写字母"); ErrorCode THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_NUMBER = new ErrorCode(1_002_003_012, "密码必须包含至少一个数字"); ErrorCode PASSWORDS_CAN_ONLY_CONTAIN_LETTERS_AND_NUMBERS = new ErrorCode(1_002_003_013, "密码只能包含字母和数字"); ErrorCode INSUFFICIENT_PERMISSIONS = new ErrorCode(1_002_003_014, "当前用户权限不足,无法修改开料状态"); ErrorCode USERNAME_MULTIPLE_ERROR = new ErrorCode(1_002_003_015,"存在【{}】重复用户,请联系系统管理员"); ErrorCode USER_OPERATE_SELF_STATUS_ERROR = new ErrorCode(1_002_003_016, "不允许操作用户自身状态"); - + ErrorCode THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_UPPER_LETTER = new ErrorCode(1_002_003_017, "密码必须包含至少一个大写字母"); // ========== 部门模块 1-002-004-000 ========== ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门"); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java index 35bd09bd0..3555a54fd 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java @@ -10,6 +10,7 @@ import com.cf.imes.framework.security.config.SecurityProperties; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; +import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO; import com.cf.imes.module.system.convert.auth.AuthConvert; @@ -85,16 +86,24 @@ public class AuthController { return success(authService.login(reqVO)); } - @PostMapping("/check") + @GetMapping("/login/check") @PermitAll @Operation(summary = "校验账号") - @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + @OperateLog(enable = false) @Parameter(name = "mobile", description = "手机号", required = true) public CommonResult loginCheck( @Param("mobile") @NotEmpty(message = "手机号不能为空") @Mobile String mobile) { return success(authService.loginCheck(mobile)); } + @PostMapping("/login/sms/check") + @PermitAll + @Operation(summary = "校验登录验证码") + @OperateLog(enable = false) + public CommonResult loginSmsCheck(@Valid @RequestBody AuthLoginSmsCheckReqVO reqVO) { + return success(authService.loginSmsCheck(reqVO)); + } + @PostMapping("/logout") @PermitAll @Operation(summary = "登出系统") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginSmsCheckReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginSmsCheckReqVO.java new file mode 100644 index 000000000..79f8853a1 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginSmsCheckReqVO.java @@ -0,0 +1,30 @@ +package com.cf.imes.module.system.controller.admin.auth.vo; + +import com.cf.imes.framework.common.validation.Mobile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; + +@Schema(description = "管理后台 - 短信验证码校验 ReqVo") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthLoginSmsCheckReqVO { + + @Schema(description = "手机号码", example = "15601691300") + @Length(min = 11, max = 11, message = "手机号长度必须 11 位") + @Mobile + @NotEmpty(message = "手机号不能为空") + private String mobile; + + @Schema(description = "验证码", example = "123456") + @Length(min = 6, max = 6, message = "验证码长度必须 6 位") + @NotEmpty(message = "短信验证码不能为空") + private String smsCaptchaVerification; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java index cc79ad4c7..754c573d7 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java @@ -13,6 +13,7 @@ import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.enums.OrderDeletedEnum; import com.cf.imes.module.system.controller.admin.user.vo.user.UserPageReqVO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; +import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; @@ -172,4 +173,13 @@ public interface AdminUserMapper extends BaseMapperX { */ @Select("SELECT username FROM system_users WHERE id = #{id} FOR UPDATE") AdminUserDO selectByIdForUpdate(@Param("id") Long id); + + /** + * 根据id物理删除user + * + * @param id + * @return 改动数量 + */ + @Delete("DELETE FROM system_users WHERE id = #{id}") + int physicalDeleteById(@Param("id") Long id); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java index d6d9acf26..7b9c3f191 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java @@ -2,6 +2,7 @@ package com.cf.imes.module.system.service.auth; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO; +import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsSendReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO; @@ -41,6 +42,13 @@ public interface AdminAuthService { */ boolean loginCheck(String mobile); + /** + * 登录短信验证码校验 + * + * @return true正确,false错误 + */ + boolean loginSmsCheck(AuthLoginSmsCheckReqVO reqVO); + /** * 基于 token 退出登录 * diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java index 469ea9859..218a60a1a 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java @@ -14,6 +14,7 @@ import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO; import com.cf.imes.module.system.api.social.dto.SocialUserRespDTO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO; +import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsSendReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO; @@ -165,6 +166,21 @@ public class AdminAuthServiceImpl implements AdminAuthService { return false; } + @Override + public boolean loginSmsCheck(AuthLoginSmsCheckReqVO reqVO) { + String mobile = reqVO.getMobile(); + // 查询账号 + AdminUserDO user = userService.getUserUniqueByUserName(mobile); + // 校验用户是否存在 + if (user == null) { + createLoginLog(null, mobile, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); + return false; + } + // 校验验证码正确性 + smsCodeService.validateSmsCode(reqVO); + return true; + } + @Override public void sendSmsCode(AuthSmsSendReqVO reqVO) { // 登录场景,验证是否存在 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeService.java index 6e3bd3734..2a90d2591 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeService.java @@ -4,6 +4,7 @@ import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; +import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO; import javax.validation.Valid; @@ -37,4 +38,10 @@ public interface SmsCodeService { */ void validateSmsCode(@Valid SmsCodeValidateReqDTO reqDTO); + /** + * 检查验证码是否有效 + * + * @param reqVO + */ + void validateSmsCode(@Valid AuthLoginSmsCheckReqVO reqVO); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java index 7c93141e2..d02a7e364 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java @@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; +import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO; import com.cf.imes.module.system.dal.dataobject.sms.SmsCodeDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.dal.mysql.sms.SmsCodeMapper; @@ -138,7 +139,7 @@ public class SmsCodeServiceImpl implements SmsCodeService { @Override public void useSmsCode(SmsCodeUseReqDTO reqDTO) { // 非修改手机号的场景时校验手机号是否存在 - AdminUserDO user = userService.getUserByUsernameAndOrganId(reqDTO.getMobile(), null); + AdminUserDO user = userService.getUserUniqueByUserName(reqDTO.getMobile()); if (ObjectUtil.isNull(user) && ObjectUtil.notEqual(SmsSceneEnum.USER_UPDATE_MOBILE.getScene(), reqDTO.getScene())) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS); } @@ -159,6 +160,28 @@ public class SmsCodeServiceImpl implements SmsCodeService { } } + @Override + public void validateSmsCode(AuthLoginSmsCheckReqVO reqVO) { + String mobile = reqVO.getMobile(); + // 非修改手机号的场景时校验手机号是否存在 + AdminUserDO user = userService.getUserUniqueByUserName(mobile); + if (ObjectUtil.isNull(user)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS); + } + String smsCodeKey = String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, mobile); + Object keyObj = redisTemplate.opsForValue().get(smsCodeKey); + if (ObjectUtil.isNotNull(keyObj)) { + // 校验码存在 + if (ObjectUtil.notEqual(String.valueOf(keyObj), reqVO.getSmsCaptchaVerification())) { + // 验证码不正确 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_NOT_CORRECT); + } + } else { + // 提示验证码不存在 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_NOT_FOUND); + } + } + @Override public void validateSmsCode(SmsCodeValidateReqDTO reqDTO) { validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java index 4c218da84..b9114ab9c 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java @@ -114,8 +114,9 @@ public class AdminUserServiceImpl implements AdminUserService { // 定义密码校验的正则表达式 - private static final String LENGTH_PATTERN = ".{6,}"; - private static final String LETTER_PATTERN = ".*[A-Za-z].*"; + private static final String LENGTH_PATTERN = ".{8,}"; + private static final String UPPER_LETTER_PATTERN = ".*[A-Z].*"; + private static final String LOWER_LETTER_PATTERN = ".*[a-z].*"; private static final String DIGIT_PATTERN = ".*\\d.*"; private static final String VALID_CHAR_PATTERN = "^[A-Za-z\\d]+$"; @@ -320,12 +321,14 @@ public class AdminUserServiceImpl implements AdminUserService { checkCurrentWhenOperate(id); // 校验用户存在 validateUserExists(id); - // 删除用户 - userMapper.deleteById(id); - // 删除用户关联数据 - permissionService.processUserDeleted(id); - // 删除用户岗位 - userPostMapper.deleteByUserId(id); + // 物理删除用户 + int deleteNum = userMapper.physicalDeleteById(id); + if (deleteNum > 0) { + // 删除用户关联数据 + permissionService.processUserDeleted(id); + // 删除用户岗位 + userPostMapper.deleteByUserId(id); + } } @Override @@ -463,11 +466,15 @@ public class AdminUserServiceImpl implements AdminUserService { // 检查密码长度 if (!Pattern.matches(LENGTH_PATTERN, password)) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.THE_PASSWORD_LENGTH_MUST_BE_AT_LEAST_6_CHARACTERS); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.THE_PASSWORD_LENGTH_MUST_BE_AT_LEAST_8_CHARACTERS); } - // 检查是否包含字母 - if (!Pattern.matches(LETTER_PATTERN, password)) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_LETTER); + // 检查是否包含大写字母 + if (!Pattern.matches(UPPER_LETTER_PATTERN, password)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_UPPER_LETTER); + } + // 检查是否包含小写字母 + if (!Pattern.matches(LOWER_LETTER_PATTERN, password)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_LOWER_LETTER); } // 检查是否包含数字 if (!Pattern.matches(DIGIT_PATTERN, password)) { diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml index 13d7cee08..ff3b4969c 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml @@ -161,7 +161,8 @@ chenfeng: - /admin-api/system/auth/logout - /admin-api/system/auth/sms-code - /admin-api/system/user/reset-password - - /admin-api/system/auth/check + - /admin-api/system/auth/login/check + - /admin-api/system/auth/login/sms/check - /rpc-api/** #- /admin-api/system/** #- /rpc-api/system/organ/valid # 防止递归。避免调用 /rpc-api/system/organ/valid 接口时,又去触发 /rpc-api/system/organ/valid 去校验