diff --git a/README.md b/README.md new file mode 100644 index 0000000..185a4bd --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +**项目说明** +- 这是根据renren框架重新修改出来的框架 +- 采用SpringBoot、MyBatis、spring security框架 +- 提供了代码生成器,只需编写30%左右代码,其余的代码交给系统自动生成,可快速完成开发任务 +- 代码生成器是用的Velocity模版引擎,如果需要可以在ym-generator模块中进行vm模板的修改和一些包名等基础修改 +
+ +**新增业务模块需要注意** +- 新增业务模块时,业务模块需要依赖ym-admin,并且ym-gateway模块maven需要依赖新建模块 +- 自动生成的controller接口都带鉴权注解,如果开发阶段可以先注释掉,后面开发完成之后再把鉴权添加到数据库 +
+ +**技术选型:** +- 核心框架:Spring Boot 2.7 +- 安全框架:Spring Security +- 持久层框架:MyBatis 3.5 +- 定时器:Quartz 2.3 +- 数据库连接池:HikariCP +- 日志管理:log4j2 +- 页面交互:Vue2.x + +
+ +**软件需求** +- JDK1.8 +- Maven3.0+ +- MySQL8.0 +- redis6.0+ +
\ No newline at end of file diff --git a/pom.xml b/pom.xml index a12076f..8c3fc54 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 1.8 4.13.2 4.2.2 - + 1.2.9 3.5.1 4.0 11.2.0.3 @@ -136,9 +136,14 @@ postgresql - org.springframework.boot - spring-boot-starter-data-jdbc + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + cn.afterturn diff --git a/ym-admin/db/mysql.sql b/ym-admin/db/mysql.sql index c326a9d..627f6cd 100644 --- a/ym-admin/db/mysql.sql +++ b/ym-admin/db/mysql.sql @@ -15,6 +15,7 @@ CREATE TABLE sys_user ( create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), unique key uk_username (username), key idx_create_date (create_date) @@ -31,6 +32,7 @@ CREATE TABLE sys_dept ( create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_pid (pid), key idx_sort (sort) @@ -47,6 +49,7 @@ create table sys_role create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_dept_id (dept_id) )ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='角色管理'; @@ -66,6 +69,7 @@ create table sys_menu create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_pid (pid), key idx_sort (sort) @@ -79,6 +83,7 @@ create table sys_role_user user_id bigint COMMENT '用户ID', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_role_id (role_id), key idx_user_id (user_id) @@ -92,6 +97,7 @@ create table sys_role_menu menu_id bigint COMMENT '菜单ID', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_role_id (role_id), key idx_menu_id (menu_id) @@ -105,6 +111,7 @@ create table sys_role_data_scope dept_id bigint COMMENT '部门ID', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_role_id (role_id) )ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='角色数据权限'; @@ -121,6 +128,7 @@ create table sys_params create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), unique key uk_param_code (param_code), key idx_create_date (create_date) @@ -138,6 +146,7 @@ create table sys_dict_type create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), UNIQUE KEY(dict_type) )ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='字典类型'; @@ -155,6 +164,7 @@ create table sys_dict_data create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), unique key uk_dict_type_value (dict_type_id, dict_value), key idx_sort (sort) @@ -171,6 +181,7 @@ create table sys_log_login creator_name varchar(50) COMMENT '用户名', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_status (status), key idx_create_date (create_date) @@ -191,6 +202,7 @@ create table sys_log_operation creator_name varchar(50) COMMENT '用户名', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_create_date (create_date) )ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='操作日志'; @@ -207,6 +219,7 @@ create table sys_log_error error_info text COMMENT '异常信息', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', primary key (id), key idx_create_date (create_date) )ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='异常日志'; @@ -218,6 +231,7 @@ CREATE TABLE sys_oss ( url varchar(200) COMMENT 'URL地址', creator bigint COMMENT '创建者', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', PRIMARY KEY (id), key idx_create_date (create_date) ) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='文件上传'; @@ -234,6 +248,7 @@ CREATE TABLE schedule_job ( create_date datetime COMMENT '创建时间', updater bigint COMMENT '更新者', update_date datetime COMMENT '更新时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', PRIMARY KEY (id), key idx_create_date (create_date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='定时任务'; @@ -248,6 +263,7 @@ CREATE TABLE schedule_job_log ( error varchar(2000) DEFAULT NULL COMMENT '失败信息', times int NOT NULL COMMENT '耗时(单位:毫秒)', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', PRIMARY KEY (id), key idx_job_id (job_id), key idx_create_date (create_date) @@ -261,6 +277,7 @@ CREATE TABLE sys_user_token ( expire_date datetime COMMENT '过期时间', update_date datetime COMMENT '更新时间', create_date datetime COMMENT '创建时间', + valid tinyint COMMENT '删除标识,是否有效:1可用 0不可用', PRIMARY KEY (id), UNIQUE KEY user_id (user_id), UNIQUE KEY token (token) diff --git a/ym-admin/src/main/java/com/cnbm/admin/aspect/LogOperationAspect.java b/ym-admin/src/main/java/com/cnbm/admin/aspect/LogOperationAspect.java index 619c43f..e55c8c5 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/aspect/LogOperationAspect.java +++ b/ym-admin/src/main/java/com/cnbm/admin/aspect/LogOperationAspect.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; +import java.util.Date; /** * @Author weihongyang @@ -78,6 +79,7 @@ public class LogOperationAspect { LoginUser loginUser = (LoginUser) authentication.getPrincipal(); if(loginUser != null){ log.setCreatorName(loginUser.getUsername()); + log.setCreator(loginUser.getSysUserEntity().getCreator()); } log.setStatus(status); @@ -89,6 +91,7 @@ public class LogOperationAspect { log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); log.setRequestUri(request.getRequestURI()); log.setRequestMethod(request.getMethod()); + log.setCreateDate(new Date()); //请求参数 Object[] args = joinPoint.getArgs(); diff --git a/ym-admin/src/main/java/com/cnbm/admin/config/MybatisPlusConfig.java b/ym-admin/src/main/java/com/cnbm/admin/config/MybatisPlusConfig.java new file mode 100644 index 0000000..3f5b021 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/config/MybatisPlusConfig.java @@ -0,0 +1,29 @@ +package com.cnbm.admin.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.cnbm.common.interceptor.DataFilterInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); + // 数据权限 + mybatisPlusInterceptor.addInnerInterceptor(new DataFilterInterceptor()); + // 分页插件 + mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + // 乐观锁 + mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + // 防止全表更新与删除 + mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + + return mybatisPlusInterceptor; + } + +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/controller/LoginController.java b/ym-admin/src/main/java/com/cnbm/admin/controller/LoginController.java index 85abb6a..14d31ca 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/controller/LoginController.java +++ b/ym-admin/src/main/java/com/cnbm/admin/controller/LoginController.java @@ -6,6 +6,7 @@ import com.cnbm.admin.service.CaptchaService; import com.cnbm.admin.service.LoginService; import com.cnbm.admin.utils.ResponseResult; import com.cnbm.common.exception.ErrorCode; +import com.cnbm.common.utils.Result; import com.cnbm.common.validator.AssertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -52,13 +53,16 @@ public class LoginController { @PostMapping("/login") @ApiOperation(value = "登录") - public ResponseResult login(HttpServletRequest request, @RequestBody LoginParam loginParam) { + public Result login(HttpServletRequest request, @RequestBody LoginParam loginParam) { return loginService.login(request,loginParam); } - @PostMapping("/doLogout") + @PostMapping("logout") @ApiOperation(value = "退出") - public void logout(){ + public Result logout(HttpServletRequest request){ + loginService.logout(request); + return new Result(); } + } diff --git a/ym-admin/src/main/java/com/cnbm/admin/controller/SysDictDataController.java b/ym-admin/src/main/java/com/cnbm/admin/controller/SysDictDataController.java index 982d63d..3f5fce7 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/controller/SysDictDataController.java +++ b/ym-admin/src/main/java/com/cnbm/admin/controller/SysDictDataController.java @@ -40,10 +40,11 @@ public class SysDictDataController { @ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) , @ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) , @ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) , + @ApiImplicitParam(name = "dictTypeId", value = "字典类型id", paramType = "query", dataTypeClass = String.class), @ApiImplicitParam(name = "dictLabel", value = "字典标签", paramType = "query", dataTypeClass=String.class), @ApiImplicitParam(name = "dictValue", value = "字典值", paramType = "query", dataTypeClass=String.class) }) - @PreAuthorize("@ex.hasAuthority('sys:dept:page')") + @PreAuthorize("@ex.hasAuthority('sys:dict:page')") public Result> page(@ApiIgnore @RequestParam Map params){ //字典类型 PageData page = sysDictDataService.page(params); diff --git a/ym-admin/src/main/java/com/cnbm/admin/controller/SysLogLoginController.java b/ym-admin/src/main/java/com/cnbm/admin/controller/SysLogLoginController.java new file mode 100644 index 0000000..8234ffa --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/controller/SysLogLoginController.java @@ -0,0 +1,69 @@ +package com.cnbm.admin.controller; + +import com.cnbm.admin.annotation.LogOperation; +import com.cnbm.admin.dto.SysLogLoginDTO; +import com.cnbm.admin.execl.SysLogLoginExcel; +import com.cnbm.admin.service.SysLogLoginService; +import com.cnbm.common.constant.Constant; +import com.cnbm.common.page.PageData; +import com.cnbm.common.utils.ExcelUtils; +import com.cnbm.common.utils.Result; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.annotations.ApiIgnore; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("sys/log/login") +@Api(tags="登录日志") +@Log4j2 +public class SysLogLoginController { + @Autowired + private SysLogLoginService sysLogLoginService; + + @GetMapping("page") + @ApiOperation("分页") + @ApiImplicitParams({ + @ApiImplicitParam(name = Constant.PAGE, value = "当前页码,从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) , + @ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) , + @ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) , + @ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) , + @ApiImplicitParam(name = "status", value = "状态 0:失败 1:成功 2:账号已锁定", paramType = "query", dataTypeClass=Integer.class), + @ApiImplicitParam(name = "creatorName", value = "用户名", paramType = "query", dataTypeClass=String.class) + }) + @PreAuthorize("@ex.hasAuthority('sys:log:login')") + public Result> page(@ApiIgnore @RequestParam Map params){ + PageData page = sysLogLoginService.page(params); + + log.info("PageData====={}",page.toString()); + + return new Result>().ok(page); + } + + @GetMapping("export") + @ApiOperation("导出") + @LogOperation("导出") + @ApiImplicitParams({ + @ApiImplicitParam(name = "status", value = "状态 0:失败 1:成功 2:账号已锁定", paramType = "query", dataTypeClass=Integer.class), + @ApiImplicitParam(name = "creatorName", value = "用户名", paramType = "query", dataTypeClass=String.class) + }) + @PreAuthorize("@ex.hasAuthority('sys:log:login')") + public void export(@ApiIgnore @RequestParam Map params, HttpServletResponse response) throws Exception { + List list = sysLogLoginService.list(params); + + ExcelUtils.exportExcelToTarget(response, null, list, SysLogLoginExcel.class); + } + +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/dao/SysLogLoginDao.java b/ym-admin/src/main/java/com/cnbm/admin/dao/SysLogLoginDao.java new file mode 100644 index 0000000..c4a9ddb --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/dao/SysLogLoginDao.java @@ -0,0 +1,10 @@ +package com.cnbm.admin.dao; + +import com.cnbm.admin.entity.SysLogLoginEntity; +import com.cnbm.common.dao.BaseDao; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysLogLoginDao extends BaseDao { + +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/dto/SysLogLoginDTO.java b/ym-admin/src/main/java/com/cnbm/admin/dto/SysLogLoginDTO.java new file mode 100644 index 0000000..c52d0c4 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/dto/SysLogLoginDTO.java @@ -0,0 +1,36 @@ +package com.cnbm.admin.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@ApiModel(value = "登录日志") +public class SysLogLoginDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "id") + private Long id; + + @ApiModelProperty(value = "用户操作 0:用户登录 1:用户退出") + private Integer operation; + + @ApiModelProperty(value = "状态 0:失败 1:成功 2:账号已锁定") + private Integer status; + + @ApiModelProperty(value = "用户代理") + private String userAgent; + + @ApiModelProperty(value = "操作IP") + private String ip; + + @ApiModelProperty(value = "用户名") + private String creatorName; + + @ApiModelProperty(value = "创建时间") + private Date createDate; + +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/entity/LoginUser.java b/ym-admin/src/main/java/com/cnbm/admin/entity/LoginUser.java index 6729ecd..21569dd 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/entity/LoginUser.java +++ b/ym-admin/src/main/java/com/cnbm/admin/entity/LoginUser.java @@ -1,16 +1,19 @@ package com.cnbm.admin.entity; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import lombok.Data; -import lombok.NoArgsConstructor; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.Data; +import lombok.NoArgsConstructor; /** * @Author weihongyang @@ -20,7 +23,9 @@ import java.util.stream.Collectors; @Data @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) -public class LoginUser implements UserDetails { +public class LoginUser implements UserDetails,Serializable { + + private static final long serialVersionUID = 1L; private SysUserEntity sysUserEntity; diff --git a/ym-admin/src/main/java/com/cnbm/admin/entity/SysLogLoginEntity.java b/ym-admin/src/main/java/com/cnbm/admin/entity/SysLogLoginEntity.java new file mode 100644 index 0000000..45b6848 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/entity/SysLogLoginEntity.java @@ -0,0 +1,35 @@ +package com.cnbm.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.cnbm.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_log_login") +public class SysLogLoginEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 用户操作 0:用户登录 1:用户退出 + */ + private Integer operation; + /** + * 状态 0:失败 1:成功 2:账号已锁定 + */ + private Integer status; + /** + * 用户代理 + */ + private String userAgent; + /** + * 操作IP + */ + private String ip; + /** + * 用户名 + */ + private String creatorName; + +} \ No newline at end of file diff --git a/ym-admin/src/main/java/com/cnbm/admin/enums/LoginOperationEnum.java b/ym-admin/src/main/java/com/cnbm/admin/enums/LoginOperationEnum.java new file mode 100644 index 0000000..dea9804 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/enums/LoginOperationEnum.java @@ -0,0 +1,22 @@ +package com.cnbm.admin.enums; + +public enum LoginOperationEnum { + /** + * 用户登录 + */ + LOGIN(0), + /** + * 用户退出 + */ + LOGOUT(1); + + private int value; + + LoginOperationEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/enums/LoginStatusEnum.java b/ym-admin/src/main/java/com/cnbm/admin/enums/LoginStatusEnum.java new file mode 100644 index 0000000..e30d1b3 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/enums/LoginStatusEnum.java @@ -0,0 +1,26 @@ +package com.cnbm.admin.enums; + +public enum LoginStatusEnum { + /** + * 失败 + */ + FAIL(0), + /** + * 成功 + */ + SUCCESS(1), + /** + * 账号已锁定 + */ + LOCK(2); + + private int value; + + LoginStatusEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/enums/WhetherEnum.java b/ym-admin/src/main/java/com/cnbm/admin/enums/WhetherEnum.java new file mode 100644 index 0000000..b1b2fc3 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/enums/WhetherEnum.java @@ -0,0 +1,52 @@ +package com.cnbm.admin.enums; + +/** + *

+ * 是、否有效枚举 + *

+ * + * @author xcc + * @date 2022年7月5日 + * @since 1.0 + */ +public enum WhetherEnum { + + NO(0, "否"), + + YES(1, "是"); + + private final Integer value; + private final String label; + private final String remark; + + WhetherEnum(final int value, final String label) { + this(value, label, null); + } + + WhetherEnum(final int value, final String label, final String remark) { + this.value = value; + this.label = label; + this.remark = remark; + } + + /** + * @return 数据值 + */ + public Integer getValue() { + return value; + } + + /** + * @return 标签名 + */ + public String getLabel() { + return label; + } + + /** + * @return 备注 + */ + public String getRemark() { + return remark; + } +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/execl/SysLogLoginExcel.java b/ym-admin/src/main/java/com/cnbm/admin/execl/SysLogLoginExcel.java new file mode 100644 index 0000000..8230aa2 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/execl/SysLogLoginExcel.java @@ -0,0 +1,24 @@ +package com.cnbm.admin.execl; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +import java.util.Date; + +@Data +public class SysLogLoginExcel { + @Excel(name = "用户操作") + private String operation; + @Excel(name = "状态", replace = {"失败_0", "成功_1", "账号已锁定_1"}) + private Integer status; + @Excel(name = "User-Agent") + private String userAgent; + @Excel(name = "操作IP") + private String ip; + @Excel(name = "用户名") + private String creatorName; + @Excel(name = "创建时间", format = "yyyy-MM-dd HH:mm:ss") + private Date createDate; + +} + diff --git a/ym-admin/src/main/java/com/cnbm/admin/service/LoginService.java b/ym-admin/src/main/java/com/cnbm/admin/service/LoginService.java index 9f93524..c5bd308 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/service/LoginService.java +++ b/ym-admin/src/main/java/com/cnbm/admin/service/LoginService.java @@ -1,7 +1,7 @@ package com.cnbm.admin.service; import com.cnbm.admin.params.LoginParam; -import com.cnbm.admin.utils.ResponseResult; +import com.cnbm.common.utils.Result; import javax.servlet.http.HttpServletRequest; @@ -12,6 +12,8 @@ import javax.servlet.http.HttpServletRequest; */ public interface LoginService { - ResponseResult login(HttpServletRequest request, LoginParam loginParam); + Result login(HttpServletRequest request, LoginParam loginParam); + + void logout(HttpServletRequest request); } diff --git a/ym-admin/src/main/java/com/cnbm/admin/service/SysLogLoginService.java b/ym-admin/src/main/java/com/cnbm/admin/service/SysLogLoginService.java new file mode 100644 index 0000000..2fec755 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/service/SysLogLoginService.java @@ -0,0 +1,18 @@ +package com.cnbm.admin.service; + +import com.cnbm.admin.dto.SysLogLoginDTO; +import com.cnbm.admin.entity.SysLogLoginEntity; +import com.cnbm.common.page.PageData; +import com.cnbm.common.service.BaseService; + +import java.util.List; +import java.util.Map; + +public interface SysLogLoginService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + void save(SysLogLoginEntity entity); +} \ No newline at end of file diff --git a/ym-admin/src/main/java/com/cnbm/admin/service/impl/LoginServiceImpl.java b/ym-admin/src/main/java/com/cnbm/admin/service/impl/LoginServiceImpl.java index ada95af..27468aa 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/service/impl/LoginServiceImpl.java +++ b/ym-admin/src/main/java/com/cnbm/admin/service/impl/LoginServiceImpl.java @@ -1,14 +1,22 @@ package com.cnbm.admin.service.impl; import com.cnbm.admin.entity.LoginUser; +import com.cnbm.admin.entity.SysLogLoginEntity; +import com.cnbm.admin.enums.LoginOperationEnum; +import com.cnbm.admin.enums.LoginStatusEnum; import com.cnbm.admin.params.LoginParam; import com.cnbm.admin.service.CaptchaService; +import com.cnbm.admin.service.SysLogLoginService; import com.cnbm.admin.utils.JwtUtil; import com.cnbm.admin.service.LoginService; import com.cnbm.admin.utils.ResponseResult; import com.cnbm.common.exception.ErrorCode; +import com.cnbm.common.utils.IpUtils; +import com.cnbm.common.utils.Result; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -16,6 +24,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; +import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -37,16 +46,30 @@ public class LoginServiceImpl implements LoginService { @Autowired private CaptchaService captchaService; + @Autowired + private SysLogLoginService sysLogLoginService; + @Override - public ResponseResult login(HttpServletRequest request, LoginParam loginParam) { + public Result login(HttpServletRequest request, LoginParam loginParam) { //验证码是否正确 boolean flag = captchaService.validate(loginParam.getUuid(), loginParam.getCaptcha()); if(!flag){ - return new ResponseResult(ErrorCode.CAPTCHA_ERROR,"验证码错误"); + return new Result<>().error(ErrorCode.CAPTCHA_ERROR, "验证码错误"); } UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginParam.getUsername(),loginParam.getPassword()); Authentication authenticate = authenticationManager.authenticate(authenticationToken); + //登录日志 + SysLogLoginEntity log = new SysLogLoginEntity(); + log.setOperation(LoginOperationEnum.LOGIN.value()); + log.setCreateDate(new Date()); + log.setIp(IpUtils.getIpAddr(request)); + log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); + log.setCreatorName(loginParam.getUsername()); + if (Objects.isNull(authenticate)) { + log.setStatus(LoginStatusEnum.FAIL.value()); + log.setCreatorName(loginParam.getUsername()); + sysLogLoginService.save(log); throw new RuntimeException("登录失败"); } //如果认证通过了,使用userid生成一个jwt jwt存入ResponseResult返回 @@ -57,7 +80,33 @@ public class LoginServiceImpl implements LoginService { map.put("token",jwt); //把完整的用户信息存入redis userid作为key redisTemplate.opsForValue().set("login:"+userid,loginUser); - return new ResponseResult(200,"登录成功",map); + //登录成功 + log.setStatus(LoginStatusEnum.SUCCESS.value()); + log.setCreator(loginUser.getSysUserEntity().getId()); + log.setCreatorName(loginUser.getUsername()); + sysLogLoginService.save(log); + return new Result<>().ok(map); + } + + @Override + public void logout(HttpServletRequest request) { + //获取SecurityContextHolder中的用户id + UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + Long userid = loginUser.getSysUserEntity().getId(); + //日志 + SysLogLoginEntity log = new SysLogLoginEntity(); + log.setOperation(LoginOperationEnum.LOGOUT.value()); + log.setIp(IpUtils.getIpAddr(request)); + log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); + log.setIp(IpUtils.getIpAddr(request)); + log.setStatus(LoginStatusEnum.SUCCESS.value()); + log.setCreator(userid); + log.setCreatorName(loginUser.getUsername()); + log.setCreateDate(new Date()); + sysLogLoginService.save(log); + //删除redis中的值 + redisTemplate.delete("login:"+userid); } } diff --git a/ym-admin/src/main/java/com/cnbm/admin/service/impl/SysLogLoginServiceImpl.java b/ym-admin/src/main/java/com/cnbm/admin/service/impl/SysLogLoginServiceImpl.java new file mode 100644 index 0000000..e233466 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/service/impl/SysLogLoginServiceImpl.java @@ -0,0 +1,59 @@ +package com.cnbm.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cnbm.admin.dao.SysLogLoginDao; +import com.cnbm.admin.dto.SysLogLoginDTO; +import com.cnbm.admin.entity.SysLogLoginEntity; +import com.cnbm.admin.service.SysLogLoginService; +import com.cnbm.common.constant.Constant; +import com.cnbm.common.page.PageData; +import com.cnbm.common.service.impl.BaseServiceImpl; +import com.cnbm.common.utils.ConvertUtils; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +@Service +@Log4j2 +public class SysLogLoginServiceImpl extends BaseServiceImpl implements SysLogLoginService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + log.info("page======{}",page.toString()); + + return getPageData(page, SysLogLoginDTO.class); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, SysLogLoginDTO.class); + } + + private QueryWrapper getWrapper(Map params){ + String status = (String) params.get("status"); + String creatorName = (String) params.get("creatorName"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(StringUtils.isNotBlank(status), "status", status); + wrapper.like(StringUtils.isNotBlank(creatorName), "creator_name", creatorName); + return wrapper; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysLogLoginEntity entity) { + insert(entity); + } + +} diff --git a/ym-admin/src/main/java/com/cnbm/admin/service/impl/UserDetailsServiceImpl.java b/ym-admin/src/main/java/com/cnbm/admin/service/impl/UserDetailsServiceImpl.java index 389c4c9..0204aa6 100644 --- a/ym-admin/src/main/java/com/cnbm/admin/service/impl/UserDetailsServiceImpl.java +++ b/ym-admin/src/main/java/com/cnbm/admin/service/impl/UserDetailsServiceImpl.java @@ -5,23 +5,24 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.cnbm.admin.dto.SysMenuDTO; import com.cnbm.admin.dto.SysUserDTO; import com.cnbm.admin.entity.LoginUser; +import com.cnbm.admin.entity.SysLogLoginEntity; import com.cnbm.admin.entity.SysMenuEntity; import com.cnbm.admin.entity.SysUserEntity; +import com.cnbm.admin.enums.LoginOperationEnum; import com.cnbm.admin.exception.LoginStatusException; import com.cnbm.admin.service.SysMenuService; import com.cnbm.common.utils.ConvertUtils; +import com.cnbm.common.utils.IpUtils; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.DisabledException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -45,6 +46,7 @@ public class UserDetailsServiceImpl implements UserDetailsService { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(SysUserEntity::getUsername,username); SysUserEntity sysUserEntity = userDao.selectOne(lambdaQueryWrapper); + if (Objects.isNull(sysUserEntity)) { throw new UsernameNotFoundException("用户名不存在"); } diff --git a/ym-admin/src/main/java/com/cnbm/admin/utils/BaseSupportUtils.java b/ym-admin/src/main/java/com/cnbm/admin/utils/BaseSupportUtils.java new file mode 100644 index 0000000..4f86c50 --- /dev/null +++ b/ym-admin/src/main/java/com/cnbm/admin/utils/BaseSupportUtils.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2018. + * http://www.ulabcare.com + */ + +package com.cnbm.admin.utils; + +import com.cnbm.admin.entity.LoginUser; +import com.cnbm.admin.entity.SysUserEntity; +import com.cnbm.admin.enums.WhetherEnum; +import lombok.Builder; +import lombok.Data; +import org.springframework.beans.BeanUtils; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 接口支持基类 + * + * @author jiff + * @date 2018/11/1 + * @since 1.0 + */ +public abstract class BaseSupportUtils { + + /** + * 获取当前登录用户信息 + * + * @return + */ + private static SysUserEntity getLoginUser() { + //登录用户信息 + UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + return loginUser.getSysUserEntity(); + } + + /** + * 设置公共字段值,一般用于创建新记录,包含以下字段: + * + *

+ * {@link CommonField#enabled}
+ * {@link CommonField#valid}
+ * {@link CommonField#creatorId}
+ * {@link CommonField#creatorName}
+ * {@link CommonField#createTime}
+ * {@link CommonField#updaterId}
+ * {@link CommonField#updaterName}
+ * {@link CommonField#updateTime}
+ *

+ * + * @param t 需要设置的对象 + * @param ignoreProperties 忽略的字段 + * @param + */ + public static T setCommonField(T t, String... ignoreProperties) { + CommonField commonField = CommonField.builder() + .enabled(WhetherEnum.YES.getValue()) + .valid(WhetherEnum.YES.getValue()) + .createTime(LocalDateTime.now()) + .creatorId(getLoginUser().getId()) + .creatorName(getLoginUser().getUsername()) + .updateTime(LocalDateTime.now()) + .updaterId(getLoginUser().getId()) + .updaterName(getLoginUser().getUsername()) + .build(); + BeanUtils.copyProperties(commonField, t, ignoreProperties); + return t; + } + + /** + * 设置更新的公共字段值,一般用于更新记录,包含以下字段: + * + *

+ * {@link CommonField#updaterId}
+ * {@link CommonField#updaterName}
+ * {@link CommonField#updateTime}
+ *

+ * + * @param t 需要设置的对象 + * @param + */ + public static T setUpdateCommonField(T t) { + CommonField commonField = CommonField.builder() + .updaterId(getLoginUser().getId()) + .updaterName(getLoginUser().getUsername()) + .updateTime(LocalDateTime.now()) + .build(); + BeanUtils.copyProperties(commonField, t, "enabled", "valid"); + return t; + } + + @Data + @Builder + private static class CommonField implements Serializable { + /** + * 启用状态:0 、停用,1、启用 + */ + private Integer enabled; + /** + * 删除标志,是否有效:1 可用 0不可用 + */ + private Integer valid; + + + /** + * 创建人 + */ + private Long creatorId; + /** + * 创建人 + */ + private String creatorName; + /** + * 创建时间 + */ + private LocalDateTime createTime; + + + /** + * 更新人 + */ + private Long updaterId; + /** + * 更新人 + */ + private String updaterName; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + } +} diff --git a/ym-admin/src/main/resources/mapper/SysLogLoginDao.xml b/ym-admin/src/main/resources/mapper/SysLogLoginDao.xml new file mode 100644 index 0000000..587044e --- /dev/null +++ b/ym-admin/src/main/resources/mapper/SysLogLoginDao.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ym-baisc/src/main/java/com/cnbm/basic/controller/FactoryController.java b/ym-baisc/src/main/java/com/cnbm/basic/controller/FactoryController.java index ba8637b..d205682 100644 --- a/ym-baisc/src/main/java/com/cnbm/basic/controller/FactoryController.java +++ b/ym-baisc/src/main/java/com/cnbm/basic/controller/FactoryController.java @@ -89,9 +89,7 @@ public class FactoryController { public Result update(@RequestBody FactoryDTO dto){ //效验数据 ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); - factoryService.update(dto); - return new Result(); } diff --git a/ym-baisc/src/main/java/com/cnbm/basic/controller/ProductController.java b/ym-baisc/src/main/java/com/cnbm/basic/controller/ProductController.java index 1fa1532..0e03f88 100644 --- a/ym-baisc/src/main/java/com/cnbm/basic/controller/ProductController.java +++ b/ym-baisc/src/main/java/com/cnbm/basic/controller/ProductController.java @@ -70,7 +70,7 @@ public class ProductController { return new Result().ok(data); } - @PostMapping + @PostMapping("save") @ApiOperation("保存") //@LogOperation("保存") //@PreAuthorize("@ex.hasAuthority('code:product:save')") @@ -83,7 +83,7 @@ public class ProductController { return new Result(); } - @PutMapping + @PutMapping("update") @ApiOperation("修改") //@LogOperation("修改") //@PreAuthorize("@ex.hasAuthority('code:product:update')") @@ -96,7 +96,7 @@ public class ProductController { return new Result(); } - @DeleteMapping + @DeleteMapping("delete") @ApiOperation("删除") //@LogOperation("删除") //@PreAuthorize("@ex.hasAuthority('code:product:delete')") diff --git a/ym-common/src/main/java/com/cnbm/common/interceptor/DataFilterInterceptor.java b/ym-common/src/main/java/com/cnbm/common/interceptor/DataFilterInterceptor.java new file mode 100644 index 0000000..9c8db8d --- /dev/null +++ b/ym-common/src/main/java/com/cnbm/common/interceptor/DataFilterInterceptor.java @@ -0,0 +1,76 @@ +package com.cnbm.common.interceptor; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.PluginUtils; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import java.util.Map; + +public class DataFilterInterceptor implements InnerInterceptor { + + @Override + public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { + DataScope scope = getDataScope(parameter); + // 不进行数据过滤 + if(scope == null || StrUtil.isBlank(scope.getSqlFilter())){ + return; + } + + // 拼接新SQL + String buildSql = getSelect(boundSql.getSql(), scope); + + // 重写SQL + PluginUtils.mpBoundSql(boundSql).sql(buildSql); + } + + private DataScope getDataScope(Object parameter){ + if (parameter == null){ + return null; + } + + // 判断参数里是否有DataScope对象 + if (parameter instanceof Map) { + Map parameterMap = (Map) parameter; + for (Map.Entry entry : parameterMap.entrySet()) { + if (entry.getValue() != null && entry.getValue() instanceof DataScope) { + return (DataScope) entry.getValue(); + } + } + } else if (parameter instanceof DataScope) { + return (DataScope) parameter; + } + + return null; + } + + private String getSelect(String buildSql, DataScope scope){ + try { + Select select = (Select) CCJSqlParserUtil.parse(buildSql); + PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); + + Expression expression = plainSelect.getWhere(); + if(expression == null){ + plainSelect.setWhere(new StringValue(scope.getSqlFilter())); + }else{ + AndExpression andExpression = new AndExpression(expression, new StringValue(scope.getSqlFilter())); + plainSelect.setWhere(andExpression); + } + + return select.toString().replaceAll("'", ""); + }catch (JSQLParserException e){ + return buildSql; + } + } +} diff --git a/ym-common/src/main/java/com/cnbm/common/interceptor/DataScope.java b/ym-common/src/main/java/com/cnbm/common/interceptor/DataScope.java new file mode 100644 index 0000000..1f7f8a2 --- /dev/null +++ b/ym-common/src/main/java/com/cnbm/common/interceptor/DataScope.java @@ -0,0 +1,22 @@ +package com.cnbm.common.interceptor; + +public class DataScope { + private String sqlFilter; + + public DataScope(String sqlFilter) { + this.sqlFilter = sqlFilter; + } + + public String getSqlFilter() { + return sqlFilter; + } + + public void setSqlFilter(String sqlFilter) { + this.sqlFilter = sqlFilter; + } + + @Override + public String toString() { + return this.sqlFilter; + } +} diff --git a/ym-common/src/main/java/com/cnbm/common/spc/util/DataUtils.java b/ym-common/src/main/java/com/cnbm/common/spc/util/DataUtils.java index 613f75b..15ac26e 100644 --- a/ym-common/src/main/java/com/cnbm/common/spc/util/DataUtils.java +++ b/ym-common/src/main/java/com/cnbm/common/spc/util/DataUtils.java @@ -23,7 +23,45 @@ public class DataUtils { } + public List> split(List value) { + List> result = new ArrayList<>(); + int day = value.iterator().next().getDate(); + List newListEntry = new ArrayList<>(); + + for (Date date : value) { + if (date.getDate() == day) { + newListEntry.add(date); + } + else { + day = date.getDate(); + result.add(newListEntry); + newListEntry = new ArrayList<>(); + newListEntry.add(date); + } + } + result.add(newListEntry);//because the last sublist was not added + + return result; + } + + public static String splitToNeed(String s,Integer type){ + String[] s1 = s.split(" "); + String[] split = s1[0].split("-"); + String year = split[0]; + String mon = split[1]; + String day = split[2]; + if(type == 1 ){ + //年 + return year; + }else if(type == 2 ){ + //月 + return year+"-"+mon; + }else { + //日 + return s1[0]; + } + } public static Date getBeforeDate(Integer number){ Date date = new Date();//获取当前日期 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");//格式化一下 @@ -37,6 +75,19 @@ public class DataUtils { Date day = calendar1.getTime(); return day; } + public static Date getAfterDate(Integer number){ + Date date = new Date();//获取当前日期 + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");//格式化一下 + Calendar calendar1 = Calendar.getInstance();//获取对日期操作的类对象 + //两种写法都可以获取到前三天的日期 + // calendar1.set(Calendar.DAY_OF_YEAR,calendar1.get(Calendar.DAY_OF_YEAR) -3); + //在当前时间的基础上获取前三天的日期 + calendar1.add(Calendar.DATE, 0+number); + //add方法 参数也可传入 月份,获取的是前几月或后几月的日期 + //calendar1.add(Calendar.MONTH, -3); + Date day = calendar1.getTime(); + return day; + } /** * 将一组数据固定分组,每组n个元素 diff --git a/ym-gateway/src/main/resources/application-dev.yml b/ym-gateway/src/main/resources/application-dev.yml index 39984e5..be3f5ed 100644 --- a/ym-gateway/src/main/resources/application-dev.yml +++ b/ym-gateway/src/main/resources/application-dev.yml @@ -20,10 +20,36 @@ spring: # url: jdbc:postgresql://192.168.10.10:5432/postgres # username: postgres # password: 123456 - hikari: - pool-name: GrowUpHikariCP - minimum-idle: 1 - maximum-pool-size: 10 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 60000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + #validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + filter: + stat: + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: false + wall: + config: + multi-statement-allow: true +# hikari: +# pool-name: GrowUpHikariCP +# minimum-idle: 1 +# maximum-pool-size: 10 ##多数据源的配置,需要引用renren-dynamic-datasource #dynamic: diff --git a/ym-gateway/src/main/resources/logback-spring.xml b/ym-gateway/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..7111d2f --- /dev/null +++ b/ym-gateway/src/main/resources/logback-spring.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ym-generator/src/main/resources/templates/controller.java.vm b/ym-generator/src/main/resources/templates/controller.java.vm index fc2f2b1..ebd19b7 100644 --- a/ym-generator/src/main/resources/templates/controller.java.vm +++ b/ym-generator/src/main/resources/templates/controller.java.vm @@ -68,26 +68,26 @@ public class ${table.controllerName} { @ApiOperation("保存") @LogOperation("保存") @PreAuthorize("@ex.hasAuthority('${package.ModuleName}:${table.entityPath}:save')") - public Result save(@RequestBody ${entity}DTO dto){ + public Result save(@RequestBody ${entity}DTO dto){ //效验数据 ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); ${table.entityPath}Service.save(dto); - return new Result(); + return new Result().ok(dto.getId()); } @PutMapping @ApiOperation("修改") @LogOperation("修改") @PreAuthorize("@ex.hasAuthority('${package.ModuleName}:${table.entityPath}:update')") - public Result update(@RequestBody ${entity}DTO dto){ + public Result update(@RequestBody ${entity}DTO dto){ //效验数据 ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); ${table.entityPath}Service.update(dto); - return new Result(); + return new Result().ok(dto.getId()); } @DeleteMapping diff --git a/ym-generator/src/main/resources/templates/mapper.xml.vm b/ym-generator/src/main/resources/templates/mapper.xml.vm index b0909e8..49be86c 100644 --- a/ym-generator/src/main/resources/templates/mapper.xml.vm +++ b/ym-generator/src/main/resources/templates/mapper.xml.vm @@ -1,39 +1,10 @@ - -#if(${enableCache}) - - - -#end -#if(${baseResultMap}) - - -#foreach($field in ${table.fields}) -#if(${field.keyFlag})##生成主键排在第一位 - -#end -#end -#foreach($field in ${table.commonFields})##生成公共字段 - -#end -#foreach($field in ${table.fields}) -#if(!${field.keyFlag})##生成普通字段 - -#end -#end + + #foreach($field in ${table.fields}) + + #end -#end -#if(${baseColumnList}) - - -#foreach($field in ${table.commonFields}) - ${field.columnName}, -#end - ${table.fieldNames} - - -#end diff --git a/ym-influx/src/main/java/com/cnbm/influx/Main.java b/ym-influx/src/main/java/com/cnbm/influx/Main.java index 5cc916c..1a6fbbb 100644 --- a/ym-influx/src/main/java/com/cnbm/influx/Main.java +++ b/ym-influx/src/main/java/com/cnbm/influx/Main.java @@ -27,7 +27,7 @@ public class Main { public static void main(String[] args) throws InterruptedException { char[] token = "lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw==".toCharArray(); String org = "qgs"; - String bucket = "mytest"; + String bucket = "qgs-bucket"; InfluxDBClient influxDBClient = InfluxDBClientFactory.create("http://192.168.0.170:8086", token, org, bucket); @@ -105,24 +105,24 @@ public class Main { // } - String flux = "from(bucket:\"mytest\") |> range(start: -6000000000000000m)"; - flux += "|> filter(fn: (r) =>\n" + - " r._measurement == \"ASProcessCompleteEvent\" and \n" + -// " r._field == \"type\" and \n" + //对应 Field key - " r.argName == \"arg3\"\n" + //对应 Tags key (Tag 信息无法在FluxRecord 里面获取。) - " )"; - QueryApi queryApi = influxDBClient.getQueryApi(); - - List tables = queryApi.query(flux); - for (FluxTable fluxTable : tables) { - List records = fluxTable.getRecords(); - for (FluxRecord fluxRecord : records) { - Double o = (Double)fluxRecord.getValueByKey("_value"); - System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); -// System.out.println("time: "+fluxRecord.getTime() +" key:"++" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); - - } - } +// String flux = "from(bucket:\"mytest\") |> range(start: -6000000000000000m)"; +// flux += "|> filter(fn: (r) =>\n" + +// " r._measurement == \"ASProcessCompleteEvent\" and \n" + +//// " r._field == \"type\" and \n" + //对应 Field key +// " r.argName == \"arg3\"\n" + //对应 Tags key (Tag 信息无法在FluxRecord 里面获取。) +// " )"; +// QueryApi queryApi = influxDBClient.getQueryApi(); +// +// List tables = queryApi.query(flux); +// for (FluxTable fluxTable : tables) { +// List records = fluxTable.getRecords(); +// for (FluxRecord fluxRecord : records) { +// Double o = (Double)fluxRecord.getValueByKey("_value"); +// System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); +//// System.out.println("time: "+fluxRecord.getTime() +" key:"++" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); +// +// } +// } // from(bucket: "mytest") @@ -133,34 +133,40 @@ public class Main { // |> sort(columns: ["_time"], desc: true) // 取前10条数据 // |> limit(n: 10, offset: 0) - +// // 取 10-20 条数据 // |> limit(n: 10, offset: 10) - +// // 取 20-30 条数据 // |> limit(n: 10, offset: 20) -// QueryDataParam queryDataParam = new QueryDataParam(); -// queryDataParam.setBucket("mytest"); -// queryDataParam.setRange(new Range(getDate().toInstant(),new Date().toInstant())); -// queryDataParam.setMeasurement("ASProcessCompleteEvent"); -// queryDataParam.setTag(new Tag("argName","arg4")); + QueryDataParam queryDataParam = new QueryDataParam(); + queryDataParam.setBucket("qgs-bucket"); + queryDataParam.setRange(new Range(getDate().toInstant(),new Date().toInstant())); + queryDataParam.setMeasurement("WeightHeiHei"); + queryDataParam.setTag(new Tag("argName","LTWeight")); // queryDataParam.setDropedTagName("transationId"); -// queryDataParam.setPageInfo(new PageInfo(1,100)); -// -// List tables = query(queryDataParam,influxDBClient); -// List records1 = tables.get(0).getRecords(); + List dropNames = new ArrayList<>(); + dropNames.add("transationId"); + dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); + queryDataParam.setDropedTagNames(dropNames); + queryDataParam.setPageInfo(new PageInfo(1,10000)); + + List tables = query(queryDataParam,influxDBClient); + List records1 = tables.get(0).getRecords(); // List> lists = Utils.fixedGroup(records1, 10); -// for (FluxTable fluxTable : tables) { -// List records = fluxTable.getRecords(); -// for (FluxRecord fluxRecord : records) { -// System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); -// -// } -// } + for (FluxTable fluxTable : tables) { + List records = fluxTable.getRecords(); + for (FluxRecord fluxRecord : records) { + Instant timms = fluxRecord.getTime(); + System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); + + } + } influxDBClient.close(); } @@ -173,7 +179,7 @@ public class Main { //两种写法都可以获取到前三天的日期 // calendar1.set(Calendar.DAY_OF_YEAR,calendar1.get(Calendar.DAY_OF_YEAR) -3); //在当前时间的基础上获取前三天的日期 - calendar1.add(Calendar.DATE, -3); + calendar1.add(Calendar.DATE, -1000); //add方法 参数也可传入 月份,获取的是前几月或后几月的日期 //calendar1.add(Calendar.MONTH, -3); Date day = calendar1.getTime(); @@ -197,6 +203,7 @@ public class Main { flux += "|> drop(columns: [\""+ dropName +"\"]) \n"; } flux += "|> sort(columns: [\"_time\"], desc: true) \n"; + flux += "|> window(every: 1y) \n"; if(pageInfo!=null){ flux += "|> limit(n: "+pageInfo.getSize()+", offset: "+(pageInfo.getCurrent()-1)* pageInfo.getSize()+")"; } diff --git a/ym-influx/src/main/java/com/cnbm/influx/config/InfluxClient.java b/ym-influx/src/main/java/com/cnbm/influx/config/InfluxClient.java index bc14755..f88342c 100644 --- a/ym-influx/src/main/java/com/cnbm/influx/config/InfluxClient.java +++ b/ym-influx/src/main/java/com/cnbm/influx/config/InfluxClient.java @@ -2,6 +2,7 @@ package com.cnbm.influx.config; import com.cnbm.influx.constant.Constant; import com.cnbm.influx.param.PageInfo; +import com.cnbm.influx.param.QueryDataGroupByTimeParam; import com.cnbm.influx.param.QueryDataParam; import com.cnbm.influx.param.Range; import com.cnbm.influx.template.Event; @@ -94,6 +95,7 @@ public enum InfluxClient { Point point = Point.measurement(measurement) .addTag("transationId", event.getTransationId()) .addTag("inspectionSheetId", event.getInspectionSheetId()) + .addTag("batchNum", event.getBatchNum().toString()) .addTag("argName", event.getArgName()) .addField("argValue", event.getArgValue()) .time(event.getTime().toEpochMilli(), WritePrecision.MS); @@ -125,6 +127,47 @@ public enum InfluxClient { } +// List tables = queryApi.query(flux); +// for (FluxTable fluxTable : tables) { +// List records = fluxTable.getRecords(); +// for (FluxRecord fluxRecord : records) { +// System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement()); +// +// } +// } + return queryApi.query(flux); + } + + public List queryGroupByTime(QueryDataGroupByTimeParam param){ + String measurement = param.getMeasurement(); + List dropedTagNames = param.getDropedTagNames(); + Range range = param.getRange(); + String bucket = param.getBucket(); + String tagName = param.getTag().getTagName(); + String tagValue = param.getTag().getTagValue(); + PageInfo pageInfo = param.getPageInfo(); + + String flux = "from(bucket:\""+bucket+"\")"; + flux += "|> range(start: "+range.getBegin()+",stop:"+range.getEnd()+")"; + flux += "|> filter(fn: (r) => r[\"_measurement\"] == \""+measurement+"\")"; + flux += "|> filter(fn: (r) => r[\""+tagName+"\"] == \""+tagValue+"\")"; + for(String dropName:dropedTagNames){ + flux += "|> drop(columns: [\""+dropName+"\"])"; + } + //|> window(every: 1mo) + if(param.getTimeType() == 1){ + flux += "|> window(every: 1y)"; + }else if(param.getTimeType() == 2 ){ + flux += "|> window(every: 1mo)"; + }else{ + flux += "|> window(every: 1d)"; + } + flux += "|> sort(columns: [\"_time\"], desc: true)"; + if(pageInfo!=null){ + flux += "|> limit(n: "+pageInfo.getSize()+", offset: "+(pageInfo.getCurrent()-1)* pageInfo.getSize()+")"; + } + + // List tables = queryApi.query(flux); // for (FluxTable fluxTable : tables) { // List records = fluxTable.getRecords(); diff --git a/ym-influx/src/main/java/com/cnbm/influx/constant/Constant.java b/ym-influx/src/main/java/com/cnbm/influx/constant/Constant.java index 113d69f..ebf4cbf 100644 --- a/ym-influx/src/main/java/com/cnbm/influx/constant/Constant.java +++ b/ym-influx/src/main/java/com/cnbm/influx/constant/Constant.java @@ -18,7 +18,7 @@ public class Constant { public static final LogLevel readTimeout = LogLevel.BODY; public static final LogLevel writeTimeout = LogLevel.BODY; public static final LogLevel connectTimeout = LogLevel.BODY; - public static final String measurement = "Weight"; + public static final String measurement = "WeightHeiHei"; } diff --git a/ym-influx/src/main/java/com/cnbm/influx/controller/S7DemoController.java b/ym-influx/src/main/java/com/cnbm/influx/controller/S7DemoController.java index 1ee0a24..aadadcc 100644 --- a/ym-influx/src/main/java/com/cnbm/influx/controller/S7DemoController.java +++ b/ym-influx/src/main/java/com/cnbm/influx/controller/S7DemoController.java @@ -16,8 +16,11 @@ import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; + +import java.text.DateFormat; import java.time.Instant; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Random; @@ -49,21 +52,49 @@ public class S7DemoController { public void insertBatchJYD() throws InterruptedException { List list = new ArrayList<>(); Random r = new Random(); + Instant instant = DataUtils.getBeforeDate(400).toInstant(); for(int j=0;j<10;j++){ for(int i=0;i<99;i++){ Thread.sleep(10); Event event = new Event(); - event.setTime(Instant.now()); + event.setTime(instant); event.setTransationId("asas"+i); event.setArgName("LTWeight"); Double d = r.nextDouble() * 2.5 + 66; event.setInspectionSheetId(j+""); event.setArgValue(d); + event.setBatchNum(i); list.add(event); } } - InfluxClient.Client.batchInsert(list,"Weight"); + InfluxClient.Client.batchInsert(list,"WeightHei"); + } + + @PostMapping("/insertBatchJYDForTest") + public void insertBatchJYDForTest() throws InterruptedException { + List list = new ArrayList<>(); + Random r = new Random(); + + for(int i=0;i<999;i++){ + Thread.sleep(10); + Event event = new Event(); + event.setTime(DataUtils.getAfterDate(i).toInstant()); + event.setTransationId("asas"+i); + event.setArgName("LostDays"); + int i1 = r.nextInt(10); + if(i1<4){ + event.setArgValue(new Double(0)); + }else { + event.setArgValue(new Double(1)); + } + + event.setInspectionSheetId(i+""); + + event.setBatchNum(i); + list.add(event); + } + InfluxClient.Client.batchInsert(list,"WeightHeiHei"); } /** @@ -139,8 +170,8 @@ public class S7DemoController { .addField("argValue", event.getArgValue()) .time(event.getTime().toEpochMilli(), WritePrecision.MS); return point; - } + @PostMapping("/insert") public void insert() throws InterruptedException { Event event = new Event(); diff --git a/ym-influx/src/main/java/com/cnbm/influx/param/QueryDataGroupByTimeParam.java b/ym-influx/src/main/java/com/cnbm/influx/param/QueryDataGroupByTimeParam.java new file mode 100644 index 0000000..0b4be8b --- /dev/null +++ b/ym-influx/src/main/java/com/cnbm/influx/param/QueryDataGroupByTimeParam.java @@ -0,0 +1,34 @@ +package com.cnbm.influx.param; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * @Desc: "influx 查询条件构造" + * @Author: caixiang + * @DATE: 2022/6/29 10:17 + * + * 注意: + * 必填 + * ① measurement 不能为空 + * ② 时间段 不能为空 + * ③ bucket 不能为空 + * 非必填 + * ① 分页信息可选 + * ② tag + * + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +public class QueryDataGroupByTimeParam extends BaseParam{ + private Tag tag; + //查询的时候,需要忽略的字段。(transationId是唯一标识会对 最终的查询结果集产生影响) + private List dropedTagNames; + private String bucket; + //1-按年分组; 2-按月分组; 3-按日分组 + private Integer timeType; +} diff --git a/ym-influx/src/main/java/com/cnbm/influx/template/Event.java b/ym-influx/src/main/java/com/cnbm/influx/template/Event.java index 59a54b4..d7ed0ae 100644 --- a/ym-influx/src/main/java/com/cnbm/influx/template/Event.java +++ b/ym-influx/src/main/java/com/cnbm/influx/template/Event.java @@ -24,4 +24,7 @@ public class Event { private String argName; private Double argValue; + + //批次号,可选的 + private Integer batchNum; } \ No newline at end of file diff --git a/ym-influx/src/main/java/com/cnbm/influx/template/EventForCount.java b/ym-influx/src/main/java/com/cnbm/influx/template/EventForCount.java index ebded4a..6c39adc 100644 --- a/ym-influx/src/main/java/com/cnbm/influx/template/EventForCount.java +++ b/ym-influx/src/main/java/com/cnbm/influx/template/EventForCount.java @@ -16,16 +16,18 @@ public class EventForCount { private String inspectionSheetId; - //n = 某个批次的样本数 - private Integer n; + private String transationId; - //failN = 某个批次不合格品数 - private String failN; + private String argName; + + + //如果是计数类型,,1 = 代表ok ;2 = nok + //todo 剩下样本量怎么估算。 + private Double argValue; + + //类型 : 1 计量型 ;2.计数型 + private Integer type; - //batchNum = 某个批次 - private String batchNum; - //检测名 - private String detectionName; } \ No newline at end of file diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/constant/Constant.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/constant/Constant.java new file mode 100644 index 0000000..e03f8fd --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/constant/Constant.java @@ -0,0 +1,10 @@ +package com.cnbm.processInspection.constant; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/8/3 10:01 + */ +public class Constant { + public String measureMent = "WeightHeiHei"; +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/controller/ProcessInspectionController.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/controller/ProcessInspectionController.java index 430d015..fb870b4 100644 --- a/ym-process-inspection/src/main/java/com/cnbm/processInspection/controller/ProcessInspectionController.java +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/controller/ProcessInspectionController.java @@ -7,9 +7,14 @@ import com.cnbm.common.spc.math.StandardDiviation; import com.cnbm.common.spc.util.DataUtils; import com.cnbm.common.vo.R; import com.cnbm.influx.constant.Constant; +import com.cnbm.influx.param.QueryDataGroupByTimeParam; import com.cnbm.influx.param.QueryDataParam; import com.cnbm.influx.param.Range; import com.cnbm.processInspection.dto.*; +import com.cnbm.processInspection.graphAnalyzed.forCount.c.CGraph; +import com.cnbm.processInspection.graphAnalyzed.forCount.np.NPGraph; +import com.cnbm.processInspection.graphAnalyzed.forCount.p.PGraph; +import com.cnbm.processInspection.graphAnalyzed.forCount.u.UGraph; import com.cnbm.processInspection.graphAnalyzed.forMeterage.mr.MeanRGraph; import com.cnbm.processInspection.graphAnalyzed.forMeterage.ms.MeanStandardDeviationGraph; import com.cnbm.processInspection.graphAnalyzed.forMeterage.xmr.XMRGraph; @@ -36,9 +41,6 @@ public class ProcessInspectionController { @PostMapping("/XbarSGraphTest") public R xbarSGraphTest() throws Exception { - ProductFeaturesDTO productFeaturesDTO = productFeaturesService.get(new Long(1)); - - ProductFeatures productFeatures = new ProductFeatures(); productFeatures.setSl(new Float(5)); productFeatures.setUsl(new Float(10)); @@ -55,7 +57,7 @@ public class ProcessInspectionController { QueryDataParam queryDataParam = new QueryDataParam(); - queryDataParam.setMeasurement("Weight"); + queryDataParam.setMeasurement(Constant.measurement); queryDataParam.setRange(new Range(DataUtils.getBeforeDate(10).toInstant(), Instant.now())); meanStandardDeviationGraph.initialDate(queryDataParam); @@ -89,7 +91,7 @@ public class ProcessInspectionController { QueryDataParam queryDataParam = new QueryDataParam(); - queryDataParam.setMeasurement("Weight"); + queryDataParam.setMeasurement(Constant.measurement); queryDataParam.setRange(new Range(DataUtils.getBeforeDate(10).toInstant(), Instant.now())); meanRGraph.initialDate(queryDataParam); @@ -122,7 +124,7 @@ public class ProcessInspectionController { QueryDataParam queryDataParam = new QueryDataParam(); - queryDataParam.setMeasurement("Weight"); + queryDataParam.setMeasurement(Constant.measurement); queryDataParam.setRange(new Range(DataUtils.getBeforeDate(10).toInstant(), Instant.now())); xmrGraph.initialDate(queryDataParam); @@ -137,6 +139,109 @@ public class ProcessInspectionController { return R.ok("成功",xmrGraphData); } + @PostMapping("/NPGraphTest") + public R NPGraphTest() throws Exception { + ProductFeatures productFeatures = new ProductFeatures(); + productFeatures.setSl(new Float(5)); + productFeatures.setUsl(new Float(10)); + productFeatures.setLsl(new Float(1)); + + productFeatures.setName("LostDays"); + NPGraph npGraph = new NPGraph(productFeatures); + + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( Instant.now() , DataUtils.getAfterDate(999).toInstant() )); + queryDataParam.setTimeType(1); + npGraph.initialDate(queryDataParam); + + NPGraphData npGraph1 = new NPGraphData( + npGraph.getList(), + npGraph.getSpecificationLimit(), + npGraph.getArgName() + ); + + return R.ok("成功",npGraph1); + } + @PostMapping("/PGraphTest") + public R PGraphTest() throws Exception { + ProductFeatures productFeatures = new ProductFeatures(); + productFeatures.setSl(new Float(5)); + productFeatures.setUsl(new Float(10)); + productFeatures.setLsl(new Float(1)); + + productFeatures.setName("LostDays"); + PGraph pGraph = new PGraph(productFeatures); + + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( Instant.now() , DataUtils.getAfterDate(999).toInstant() )); + queryDataParam.setTimeType(2); + pGraph.initialDate(queryDataParam); + + PGraphData npGraph1 = new PGraphData( + pGraph.getList(), + pGraph.getSpecificationLimit(), + pGraph.getArgName() + ); + + return R.ok("成功",npGraph1); + } + @PostMapping("/CGraphTest") + public R CGraphTest() throws Exception { + ProductFeatures productFeatures = new ProductFeatures(); + productFeatures.setSl(new Float(5)); + productFeatures.setUsl(new Float(10)); + productFeatures.setLsl(new Float(1)); + + productFeatures.setName("LostDays"); + CGraph cGraph = new CGraph(productFeatures); + + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( Instant.now() , DataUtils.getAfterDate(999).toInstant() )); + queryDataParam.setTimeType(2); + cGraph.initialDate(queryDataParam); + + CGraphData npGraph1 = new CGraphData( + cGraph.getList(), + cGraph.getSpecificationLimit(), + cGraph.getArgName() + ); + + return R.ok("成功",npGraph1); + } + + @PostMapping("/UGraphTest") + public R UGraphTest() throws Exception { + ProductFeatures productFeatures = new ProductFeatures(); + productFeatures.setSl(new Float(5)); + productFeatures.setUsl(new Float(10)); + productFeatures.setLsl(new Float(1)); + + productFeatures.setName("LostDays"); + UGraph uGraph = new UGraph(productFeatures); + + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( Instant.now() , DataUtils.getAfterDate(999).toInstant() )); + queryDataParam.setTimeType(2); + uGraph.initialDate(queryDataParam); + + UGraphData npGraph1 = new UGraphData( + uGraph.getList(), + uGraph.getSpecificationLimit(), + uGraph.getArgName() + ); + + return R.ok("成功",npGraph1); + } + + private ProductFeatures setRealSampleSize(GraphArg graphArg){ ProductFeaturesDTO productFeaturesDTO = productFeaturesService.get(graphArg.getProductFeaturesId()); @@ -235,4 +340,87 @@ public class ProcessInspectionController { return R.ok("成功",xmrGraphData); } + @PostMapping("/NPGraph") + public R NPGraph(@RequestBody GraphArg graphArg) throws Exception { + + ProductFeatures productFeatures = setRealSampleSize(graphArg); + + NPGraph npGraph = new NPGraph(productFeatures); + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( graphArg.getBegin().toInstant() , graphArg.getEnd().toInstant() )); + queryDataParam.setTimeType(graphArg.getGroupType()); + npGraph.initialDate(queryDataParam); + + NPGraphData npGraph1 = new NPGraphData( + npGraph.getList(), + npGraph.getSpecificationLimit(), + npGraph.getArgName() + ); + return R.ok("成功",npGraph1); + } + + @PostMapping("/PGraph") + public R PGraph(@RequestBody GraphArg graphArg) throws Exception { + + ProductFeatures productFeatures = setRealSampleSize(graphArg); + + PGraph pGraph = new PGraph(productFeatures); + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( graphArg.getBegin().toInstant() , graphArg.getEnd().toInstant() )); + queryDataParam.setTimeType(graphArg.getGroupType()); + pGraph.initialDate(queryDataParam); + + PGraphData npGraph1 = new PGraphData( + pGraph.getList(), + pGraph.getSpecificationLimit(), + pGraph.getArgName() + ); + return R.ok("成功",npGraph1); + } + @PostMapping("/CGraph") + public R CGraph(@RequestBody GraphArg graphArg) throws Exception { + + ProductFeatures productFeatures = setRealSampleSize(graphArg); + + CGraph cGraph = new CGraph(productFeatures); + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( graphArg.getBegin().toInstant() , graphArg.getEnd().toInstant() )); + queryDataParam.setTimeType(graphArg.getGroupType()); + cGraph.initialDate(queryDataParam); + + CGraphData npGraph1 = new CGraphData( + cGraph.getList(), + cGraph.getSpecificationLimit(), + cGraph.getArgName() + ); + return R.ok("成功",npGraph1); + } + + @PostMapping("/UGraph") + public R UGraph(@RequestBody GraphArg graphArg) throws Exception { + + ProductFeatures productFeatures = setRealSampleSize(graphArg); + + UGraph uGraph = new UGraph(productFeatures); + + QueryDataGroupByTimeParam queryDataParam = new QueryDataGroupByTimeParam(); + queryDataParam.setMeasurement(Constant.measurement); + queryDataParam.setRange(new Range( graphArg.getBegin().toInstant() , graphArg.getEnd().toInstant() )); + queryDataParam.setTimeType(graphArg.getGroupType()); + uGraph.initialDate(queryDataParam); + + UGraphData uGraphData = new UGraphData( + uGraph.getList(), + uGraph.getSpecificationLimit(), + uGraph.getArgName() + ); + return R.ok("成功",uGraphData); + } + } diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/CGraphData.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/CGraphData.java new file mode 100644 index 0000000..22ba9ad --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/CGraphData.java @@ -0,0 +1,32 @@ +package com.cnbm.processInspection.dto; + +import com.cnbm.qualityPlanning.entity.CPoint; +import com.cnbm.qualityPlanning.entity.PPoint; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/7/22 14:18 + */ +@Data +@ApiModel(value = "C控制图 结果类") +public class CGraphData { + @ApiModelProperty(value = "P控制图list数据") + private List list; + @ApiModelProperty(value = "P控制图 规格线") + private SpecificationLimit specificationLimit; + @ApiModelProperty(value = "P控制图 参数名") + private String argName; + + public CGraphData(List list, SpecificationLimit specificationLimit, String argName) { + this.list = list; + this.specificationLimit = specificationLimit; + this.argName = argName; + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/GraphArg.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/GraphArg.java index 5b1212d..086dd43 100644 --- a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/GraphArg.java +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/GraphArg.java @@ -32,5 +32,6 @@ public class GraphArg { @ApiModelProperty(value = "样本大小,不填的话用之前配置的") private Integer sampleSize; - + @ApiModelProperty(value = "分组类别(1=年 , 2=月 , 3=日)(用于计数型控制图)") + private Integer groupType; } diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/InterpretationListArgForCount.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/InterpretationListArgForCount.java new file mode 100644 index 0000000..0ef14a7 --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/InterpretationListArgForCount.java @@ -0,0 +1,22 @@ +package com.cnbm.processInspection.dto; + +import lombok.Data; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/7/27 15:56 + */ +@Data +public class InterpretationListArgForCount { + private Integer number; + private Integer arg; + + public InterpretationListArgForCount() { + } + + public InterpretationListArgForCount(Integer number, Integer arg) { + this.number = number; + this.arg = arg; + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/NPGraphData.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/NPGraphData.java new file mode 100644 index 0000000..769f247 --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/NPGraphData.java @@ -0,0 +1,35 @@ +package com.cnbm.processInspection.dto; + +import com.cnbm.common.spc.math.StandardDiviation; +import com.cnbm.processInspection.graphAnalyzed.forMeterage.xmr.XMRGraphEntity; +import com.cnbm.qualityPlanning.entity.ControlLimit; +import com.cnbm.qualityPlanning.entity.NPPoint; +import com.cnbm.qualityPlanning.entity.ProcessCapability; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/7/22 14:18 + */ +@Data +@ApiModel(value = "NP控制图 结果类") +public class NPGraphData { + @ApiModelProperty(value = "NP控制图list数据") + private List list; + @ApiModelProperty(value = "NP控制图 规格线") + private SpecificationLimit specificationLimit; + @ApiModelProperty(value = "NP控制图 参数名") + private String argName; + + public NPGraphData(List list, SpecificationLimit specificationLimit, String argName) { + this.list = list; + this.specificationLimit = specificationLimit; + this.argName = argName; + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/PGraphData.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/PGraphData.java new file mode 100644 index 0000000..e20ee46 --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/PGraphData.java @@ -0,0 +1,32 @@ +package com.cnbm.processInspection.dto; + +import com.cnbm.qualityPlanning.entity.NPPoint; +import com.cnbm.qualityPlanning.entity.PPoint; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/7/22 14:18 + */ +@Data +@ApiModel(value = "P控制图 结果类") +public class PGraphData { + @ApiModelProperty(value = "P控制图list数据") + private List list; + @ApiModelProperty(value = "P控制图 规格线") + private SpecificationLimit specificationLimit; + @ApiModelProperty(value = "P控制图 参数名") + private String argName; + + public PGraphData(List list, SpecificationLimit specificationLimit, String argName) { + this.list = list; + this.specificationLimit = specificationLimit; + this.argName = argName; + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/UGraphData.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/UGraphData.java new file mode 100644 index 0000000..0e0c528 --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/dto/UGraphData.java @@ -0,0 +1,32 @@ +package com.cnbm.processInspection.dto; + +import com.cnbm.qualityPlanning.entity.CPoint; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import com.cnbm.qualityPlanning.entity.UPoint; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/7/22 14:18 + */ +@Data +@ApiModel(value = "U控制图 结果类") +public class UGraphData { + @ApiModelProperty(value = "U控制图list数据") + private List list; + @ApiModelProperty(value = "U控制图 规格线") + private SpecificationLimit specificationLimit; + @ApiModelProperty(value = "U控制图 参数名") + private String argName; + + public UGraphData(List list, SpecificationLimit specificationLimit, String argName) { + this.list = list; + this.specificationLimit = specificationLimit; + this.argName = argName; + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/c/CGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/c/CGraph.java new file mode 100644 index 0000000..a18d5d3 --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/c/CGraph.java @@ -0,0 +1,153 @@ +package com.cnbm.processInspection.graphAnalyzed.forCount.c; + +import com.cnbm.basic.entity.ProductFeatures; +import com.cnbm.common.spc.util.DataUtils; +import com.cnbm.influx.config.InfluxClient; +import com.cnbm.influx.constant.Constant; +import com.cnbm.influx.param.QueryDataGroupByTimeParam; +import com.cnbm.influx.param.Tag; +import com.cnbm.qualityPlanning.entity.CPoint; +import com.cnbm.qualityPlanning.entity.ControlLimit; +import com.cnbm.qualityPlanning.entity.PPoint; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import com.influxdb.query.FluxRecord; +import com.influxdb.query.FluxTable; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Desc: "均值标准差 控制图 , 计算类" + * @Author: caixiang + * @DATE: 2022/7/20 14:26 + * 使用方式:① 先new MeanStandardDeviationGraph 对象 ;② 再initialData 初始化数据;③ 再get 控制限 + * + * 步骤: + * ① 先读mysql表,查询 product_features 表,先读到 sample_size(样本量) + * ② 再依据 influx.argName == mysql.product_feature.name && 时间段 查询所有的 参数数据 + * ③ 拿到参数数据后,分组 整合成List, + * 计算控制限 + * 计算 母体 的 \sigma 、 bar{x} 。。。 + * 计算CPK 、CPU 、CPL这些 + * ④ 如果配置了判读方案,还要 调用 StatisticalControlledTest Function 检验。 + * ⑤ + */ +@Data +public class CGraph { + + + //计数型,不能用判读方案校验,,因为 当每个样本n不同,控制限 都不一定相同。 +// private List interpretationScheme; + private String argName; + + private List list; + + private Double cbar; + + private SpecificationLimit specificationLimit; + + public CGraph(ProductFeatures productFeatures) throws Exception { + this.argName = productFeatures.getName(); + list = new ArrayList<>(); + this.specificationLimit = new SpecificationLimit( + productFeatures.getUsl()==null?null:productFeatures.getUsl(), + productFeatures.getSl()==null?null:productFeatures.getSl(), + productFeatures.getLsl()==null?null:productFeatures.getLsl() + ); + } + + private Double[] toDoubleArray(Object[] o){ + Double[] res= new Double[o.length]; + for(int i=0;i query){ + Double totalFailNum = (double)0; + + for (FluxTable fluxTable : query) { + List records = fluxTable.getRecords(); + Integer failNum = 0; + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + totalFailNum =totalFailNum + (double)failNum; + } + return totalFailNum/query.size(); + } + + public static void main(String[] args) { + //2022-08-04 T06:59:55.628Z + String name = "2022-08-04 T06:59:55.628Z"; + String[] s = name.split(" "); + String[] split = s[0].split("-"); + System.out.println(name); + } + + + + /** + * name : 初始化数据函数 + * desc : 从influxdb 里面读取数据,然后 加工处理成 我需要的 + * 步骤: + * ① + * */ + public void initialDate(QueryDataGroupByTimeParam queryDataParam){ + queryDataParam.setBucket(Constant.bucket); + List dropNames = new ArrayList<>(); + dropNames.add("transationId"); + dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); + queryDataParam.setDropedTagNames(dropNames); + queryDataParam.setTag(new Tag("argName",argName)); + + List query = InfluxClient.Client.queryGroupByTime(queryDataParam); + //1. 先从fluxdb 里面提取原始数据 + //计算p bar + this.cbar = computeCbar(query); + //2.计算各项式 + for(int i=0 ;i records = query.get(i).getRecords(); + Integer failNum = 0; + String name = DataUtils.splitToNeed(records.get(0).getTime().toString(),queryDataParam.getTimeType()); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + list.add(new CPoint( + getCL(), + i, + (double)failNum, + name + )); + } + } + + + + + /** + * desc: get Xbar控制图 的控制限 + * 注意:此函数 要在 initialDate()函数执行之后 + * */ + public ControlLimit getCL(){ + + Double mul = 3 * Math.sqrt( this.cbar ); + Double lcl = (this.cbar-mul)<0?0:(this.cbar-mul); + return new ControlLimit( + this.cbar + mul, + this.cbar, + lcl + ); + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/np/NPGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/np/NPGraph.java new file mode 100644 index 0000000..e70a802 --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/np/NPGraph.java @@ -0,0 +1,156 @@ +package com.cnbm.processInspection.graphAnalyzed.forCount.np; + +import com.cnbm.basic.entity.ProductFeatures; +import com.cnbm.common.spc.math.StandardDiviation; +import com.cnbm.common.spc.util.DataUtils; +import com.cnbm.influx.config.InfluxClient; +import com.cnbm.influx.constant.Constant; +import com.cnbm.influx.param.QueryDataGroupByTimeParam; +import com.cnbm.influx.param.QueryDataParam; +import com.cnbm.influx.param.Tag; +import com.cnbm.processInspection.controlCoefficientConstant.XBarRCoefficients; +import com.cnbm.processInspection.dto.InterpretationListArg; +import com.cnbm.processInspection.dto.InterpretationListArgForCount; +import com.cnbm.qualityPlanning.common.StatisticalControlledTest; +import com.cnbm.qualityPlanning.entity.*; +import com.influxdb.query.FluxRecord; +import com.influxdb.query.FluxTable; +import lombok.Data; +import org.omg.CORBA.PRIVATE_MEMBER; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Desc: "均值标准差 控制图 , 计算类" + * @Author: caixiang + * @DATE: 2022/7/20 14:26 + * 使用方式:① 先new MeanStandardDeviationGraph 对象 ;② 再initialData 初始化数据;③ 再get 控制限 + * + * 步骤: + * ① 先读mysql表,查询 product_features 表,先读到 sample_size(样本量) + * ② 再依据 influx.argName == mysql.product_feature.name && 时间段 查询所有的 参数数据 + * ③ 拿到参数数据后,分组 整合成List, + * 计算控制限 + * 计算 母体 的 \sigma 、 bar{x} 。。。 + * 计算CPK 、CPU 、CPL这些 + * ④ 如果配置了判读方案,还要 调用 StatisticalControlledTest Function 检验。 + * ⑤ + */ +@Data +public class NPGraph { + + + //计数型,不能用判读方案校验,,因为 当每个样本n不同,控制限 都不一定相同。 +// private List interpretationScheme; + private String argName; + + private List list; + + private Double pbar; + + private SpecificationLimit specificationLimit; + + public NPGraph(ProductFeatures productFeatures) throws Exception { + this.argName = productFeatures.getName(); + list = new ArrayList<>(); + this.specificationLimit = new SpecificationLimit( + productFeatures.getUsl()==null?null:productFeatures.getUsl(), + productFeatures.getSl()==null?null:productFeatures.getSl(), + productFeatures.getLsl()==null?null:productFeatures.getLsl() + ); + } + + private Double[] toDoubleArray(Object[] o){ + Double[] res= new Double[o.length]; + for(int i=0;i query){ + Double totalFailNum = (double)0; + Double totalN = (double)0; + + for (FluxTable fluxTable : query) { + List records = fluxTable.getRecords(); + + Integer failNum = 0; + Integer n = records.size(); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + totalFailNum =totalFailNum + (double)failNum; + totalN = totalN + (double)n; + } + + return totalFailNum/totalN; + } + + /** + * name : 初始化数据函数 + * desc : 从influxdb 里面读取数据,然后 加工处理成 我需要的 + * 步骤: + * ① + * */ + public void initialDate(QueryDataGroupByTimeParam queryDataParam){ + queryDataParam.setBucket(Constant.bucket); + List dropNames = new ArrayList<>(); + dropNames.add("transationId"); + dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); + queryDataParam.setDropedTagNames(dropNames); + queryDataParam.setTag(new Tag("argName",argName)); + + List query = InfluxClient.Client.queryGroupByTime(queryDataParam); + //1. 先从fluxdb 里面提取原始数据 + List originData = new ArrayList<>(); + //计算p bar + this.pbar = computePbar(query); + + //2.计算各项式 + for(int i=0 ;i records = query.get(i).getRecords(); + Integer failNum = 0; + Integer n = records.size(); + String name = DataUtils.splitToNeed(records.get(0).getTime().toString(),queryDataParam.getTimeType()); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + + list.add(new NPPoint( + getCL((double)n), + i, + failNum, + name + )); + } + } + + + + + /** + * desc: get Xbar控制图 的控制限 + * 注意:此函数 要在 initialDate()函数执行之后 + * */ + public ControlLimit getCL(Double n){ + Double npbar = n * this.pbar; + Double mul = 3 * Math.sqrt(npbar*(1-this.pbar)); + Double lcl = (npbar-mul)<0?0:(npbar-mul); + return new ControlLimit( + npbar + mul, + npbar, + lcl + ); + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/p/PGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/p/PGraph.java new file mode 100644 index 0000000..978572e --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/p/PGraph.java @@ -0,0 +1,163 @@ +package com.cnbm.processInspection.graphAnalyzed.forCount.p; + +import com.cnbm.basic.entity.ProductFeatures; +import com.cnbm.common.spc.util.DataUtils; +import com.cnbm.influx.config.InfluxClient; +import com.cnbm.influx.constant.Constant; +import com.cnbm.influx.param.QueryDataGroupByTimeParam; +import com.cnbm.influx.param.Tag; +import com.cnbm.qualityPlanning.entity.ControlLimit; +import com.cnbm.qualityPlanning.entity.NPPoint; +import com.cnbm.qualityPlanning.entity.PPoint; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import com.influxdb.query.FluxRecord; +import com.influxdb.query.FluxTable; +import lombok.Data; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @Desc: "均值标准差 控制图 , 计算类" + * @Author: caixiang + * @DATE: 2022/7/20 14:26 + * 使用方式:① 先new MeanStandardDeviationGraph 对象 ;② 再initialData 初始化数据;③ 再get 控制限 + * + * 步骤: + * ① 先读mysql表,查询 product_features 表,先读到 sample_size(样本量) + * ② 再依据 influx.argName == mysql.product_feature.name && 时间段 查询所有的 参数数据 + * ③ 拿到参数数据后,分组 整合成List, + * 计算控制限 + * 计算 母体 的 \sigma 、 bar{x} 。。。 + * 计算CPK 、CPU 、CPL这些 + * ④ 如果配置了判读方案,还要 调用 StatisticalControlledTest Function 检验。 + * ⑤ + */ +@Data +public class PGraph { + + + //计数型,不能用判读方案校验,,因为 当每个样本n不同,控制限 都不一定相同。 +// private List interpretationScheme; + private String argName; + + private List list; + + private Double pbar; + + private SpecificationLimit specificationLimit; + + public PGraph(ProductFeatures productFeatures) throws Exception { + this.argName = productFeatures.getName(); + list = new ArrayList<>(); + this.specificationLimit = new SpecificationLimit( + productFeatures.getUsl()==null?null:productFeatures.getUsl(), + productFeatures.getSl()==null?null:productFeatures.getSl(), + productFeatures.getLsl()==null?null:productFeatures.getLsl() + ); + } + + private Double[] toDoubleArray(Object[] o){ + Double[] res= new Double[o.length]; + for(int i=0;i query){ + Double totalFailNum = (double)0; + Double totalN = (double)0; + + for (FluxTable fluxTable : query) { + List records = fluxTable.getRecords(); + + Integer failNum = 0; + Integer n = records.size(); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + totalFailNum =totalFailNum + (double)failNum; + totalN = totalN + (double)n; + } + + return totalFailNum/totalN; + } + + public static void main(String[] args) { + //2022-08-04 T06:59:55.628Z + String name = "2022-08-04 T06:59:55.628Z"; + String[] s = name.split(" "); + String[] split = s[0].split("-"); + System.out.println(name); + } + + + + /** + * name : 初始化数据函数 + * desc : 从influxdb 里面读取数据,然后 加工处理成 我需要的 + * 步骤: + * ① + * */ + public void initialDate(QueryDataGroupByTimeParam queryDataParam){ + queryDataParam.setBucket(Constant.bucket); + List dropNames = new ArrayList<>(); + dropNames.add("transationId"); + dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); + queryDataParam.setDropedTagNames(dropNames); + queryDataParam.setTag(new Tag("argName",argName)); + + List query = InfluxClient.Client.queryGroupByTime(queryDataParam); + //1. 先从fluxdb 里面提取原始数据 + //计算p bar + this.pbar = computePbar(query); + + //2.计算各项式 + for(int i=0 ;i records = query.get(i).getRecords(); + Integer failNum = 0; + Integer n = records.size(); + String name = DataUtils.splitToNeed(records.get(0).getTime().toString(),queryDataParam.getTimeType()); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + Double pi = (double)failNum / (double)n; + + list.add(new PPoint( + getCL((double)n), + i, + pi, + name + )); + } + } + + + + + /** + * desc: get Xbar控制图 的控制限 + * 注意:此函数 要在 initialDate()函数执行之后 + * */ + public ControlLimit getCL(Double n){ + + Double mul = 3 * Math.sqrt( ( this.pbar * (1-this.pbar) ) / n ); + Double lcl = (this.pbar-mul)<0?0:(this.pbar-mul); + return new ControlLimit( + this.pbar + mul, + this.pbar, + lcl + ); + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/u/UGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/u/UGraph.java new file mode 100644 index 0000000..70ede0c --- /dev/null +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forCount/u/UGraph.java @@ -0,0 +1,161 @@ +package com.cnbm.processInspection.graphAnalyzed.forCount.u; + +import com.cnbm.basic.entity.ProductFeatures; +import com.cnbm.common.spc.util.DataUtils; +import com.cnbm.influx.config.InfluxClient; +import com.cnbm.influx.constant.Constant; +import com.cnbm.influx.param.QueryDataGroupByTimeParam; +import com.cnbm.influx.param.Tag; +import com.cnbm.qualityPlanning.entity.ControlLimit; +import com.cnbm.qualityPlanning.entity.PPoint; +import com.cnbm.qualityPlanning.entity.SpecificationLimit; +import com.cnbm.qualityPlanning.entity.UPoint; +import com.influxdb.query.FluxRecord; +import com.influxdb.query.FluxTable; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Desc: "均值标准差 控制图 , 计算类" + * @Author: caixiang + * @DATE: 2022/7/20 14:26 + * 使用方式:① 先new MeanStandardDeviationGraph 对象 ;② 再initialData 初始化数据;③ 再get 控制限 + * + * 步骤: + * ① 先读mysql表,查询 product_features 表,先读到 sample_size(样本量) + * ② 再依据 influx.argName == mysql.product_feature.name && 时间段 查询所有的 参数数据 + * ③ 拿到参数数据后,分组 整合成List, + * 计算控制限 + * 计算 母体 的 \sigma 、 bar{x} 。。。 + * 计算CPK 、CPU 、CPL这些 + * ④ 如果配置了判读方案,还要 调用 StatisticalControlledTest Function 检验。 + * ⑤ + */ +@Data +public class UGraph { + + + //计数型,不能用判读方案校验,,因为 当每个样本n不同,控制限 都不一定相同。 +// private List interpretationScheme; + private String argName; + + private List list; + + private Double ubar; + + private SpecificationLimit specificationLimit; + + public UGraph(ProductFeatures productFeatures) throws Exception { + this.argName = productFeatures.getName(); + list = new ArrayList<>(); + this.specificationLimit = new SpecificationLimit( + productFeatures.getUsl()==null?null:productFeatures.getUsl(), + productFeatures.getSl()==null?null:productFeatures.getSl(), + productFeatures.getLsl()==null?null:productFeatures.getLsl() + ); + } + + private Double[] toDoubleArray(Object[] o){ + Double[] res= new Double[o.length]; + for(int i=0;i query){ + Double totalFailNum = (double)0; + Double totalN = (double)0; + + for (FluxTable fluxTable : query) { + List records = fluxTable.getRecords(); + + Integer failNum = 0; + Integer n = records.size(); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + totalFailNum =totalFailNum + (double)failNum; + totalN = totalN + (double)n; + } + return totalFailNum/totalN; + } + + public static void main(String[] args) { + //2022-08-04 T06:59:55.628Z + String name = "2022-08-04 T06:59:55.628Z"; + String[] s = name.split(" "); + String[] split = s[0].split("-"); + System.out.println(name); + } + + + + /** + * name : 初始化数据函数 + * desc : 从influxdb 里面读取数据,然后 加工处理成 我需要的 + * 步骤: + * ① + * */ + public void initialDate(QueryDataGroupByTimeParam queryDataParam){ + queryDataParam.setBucket(Constant.bucket); + List dropNames = new ArrayList<>(); + dropNames.add("transationId"); + dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); + queryDataParam.setDropedTagNames(dropNames); + queryDataParam.setTag(new Tag("argName",argName)); + + List query = InfluxClient.Client.queryGroupByTime(queryDataParam); + //1. 先从fluxdb 里面提取原始数据 + //计算p bar + this.ubar = computeUbar(query); + + //2.计算各项式 + for(int i=0 ;i records = query.get(i).getRecords(); + Integer failNum = 0; + Integer n = records.size(); + String name = DataUtils.splitToNeed(records.get(0).getTime().toString(),queryDataParam.getTimeType()); + for (FluxRecord fluxRecord : records) { + //因为 传进去的就是Double 类型,所以取出来,自然而然就是Double + Double value = Double.parseDouble(fluxRecord.getValueByKey("_value").toString()); + if(value.equals((double) 0)){ + failNum+=1; + } + } + Double ui = (double)failNum / (double)n; + + list.add(new UPoint( + getCL((double)n), + i, + ui, + name + )); + } + } + + + + + /** + * desc: get Xbar控制图 的控制限 + * 注意:此函数 要在 initialDate()函数执行之后 + * */ + public ControlLimit getCL(Double n){ + + Double mul = 3 * Math.sqrt( this.ubar / n ); + Double lcl = (this.ubar-mul)<0?0:(this.ubar-mul); + return new ControlLimit( + this.ubar + mul, + this.ubar, + lcl + ); + } +} diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/mr/MeanRGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/mr/MeanRGraph.java index 075a50a..744c6bd 100644 --- a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/mr/MeanRGraph.java +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/mr/MeanRGraph.java @@ -75,7 +75,7 @@ public class MeanRGraph { this.specificationLimit = new SpecificationLimit( productFeatures.getUsl()==null?null:productFeatures.getUsl(), productFeatures.getSl()==null?null:productFeatures.getSl(), - productFeatures.getUsl()==null?null:productFeatures.getUsl() + productFeatures.getLsl()==null?null:productFeatures.getLsl() ); } @@ -102,6 +102,7 @@ public class MeanRGraph { List dropNames = new ArrayList<>(); dropNames.add("transationId"); dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); queryDataParam.setDropedTagNames(dropNames); queryDataParam.setTag(new Tag("argName",argName)); diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/ms/MeanStandardDeviationGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/ms/MeanStandardDeviationGraph.java index 4a68763..232fc73 100644 --- a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/ms/MeanStandardDeviationGraph.java +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/ms/MeanStandardDeviationGraph.java @@ -72,7 +72,7 @@ public class MeanStandardDeviationGraph { this.specificationLimit = new SpecificationLimit( productFeatures.getUsl()==null?null:productFeatures.getUsl(), productFeatures.getSl()==null?null:productFeatures.getSl(), - productFeatures.getUsl()==null?null:productFeatures.getUsl() + productFeatures.getLsl()==null?null:productFeatures.getLsl() ); } @@ -99,6 +99,7 @@ public class MeanStandardDeviationGraph { List dropNames = new ArrayList<>(); dropNames.add("transationId"); dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); queryDataParam.setDropedTagNames(dropNames); queryDataParam.setTag(new Tag("argName",argName)); diff --git a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/xmr/XMRGraph.java b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/xmr/XMRGraph.java index 2522586..d55cf3e 100644 --- a/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/xmr/XMRGraph.java +++ b/ym-process-inspection/src/main/java/com/cnbm/processInspection/graphAnalyzed/forMeterage/xmr/XMRGraph.java @@ -69,7 +69,7 @@ public class XMRGraph { this.specificationLimit = new SpecificationLimit( productFeatures.getUsl()==null?null:productFeatures.getUsl(), productFeatures.getSl()==null?null:productFeatures.getSl(), - productFeatures.getUsl()==null?null:productFeatures.getUsl() + productFeatures.getLsl()==null?null:productFeatures.getLsl() ); } @@ -96,6 +96,7 @@ public class XMRGraph { List dropNames = new ArrayList<>(); dropNames.add("transationId"); dropNames.add("inspectionSheetId"); + dropNames.add("batchNum"); queryDataParam.setDropedTagNames(dropNames); queryDataParam.setTag(new Tag("argName",argName)); diff --git a/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/CPoint.java b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/CPoint.java new file mode 100644 index 0000000..e0ca095 --- /dev/null +++ b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/CPoint.java @@ -0,0 +1,28 @@ +package com.cnbm.qualityPlanning.entity; + +import lombok.Data; + +/** + * @Desc: "整合,处理好 后的一行数据 (sampleSize 后的数据) " + * @Author: caixiang + * @DATE: 2022/7/21 9:43 + */ +@Data +public class CPoint { + + private ControlLimit controlLimit; + + private Integer position; + + //不合格品数 + private Double value; + + private String name; + + public CPoint(ControlLimit controlLimit, Integer position, Double value, String name) { + this.controlLimit = controlLimit; + this.position = position; + this.value = value; + this.name = name; + } +} diff --git a/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/NPPoint.java b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/NPPoint.java new file mode 100644 index 0000000..170d9ae --- /dev/null +++ b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/NPPoint.java @@ -0,0 +1,32 @@ +package com.cnbm.qualityPlanning.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @Desc: "整合,处理好 后的一行数据 (sampleSize 后的数据) " + * @Author: caixiang + * @DATE: 2022/7/21 9:43 + */ +@Data +public class NPPoint{ + + private ControlLimit controlLimit; + + private Integer position; + + //不合格品数 + private Integer value; + private String name; + + public NPPoint(ControlLimit controlLimit, Integer position, Integer value,String name) { + this.controlLimit = controlLimit; + this.position = position; + this.value = value; + this.name = name; + } +} diff --git a/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/PPoint.java b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/PPoint.java new file mode 100644 index 0000000..ac28c5d --- /dev/null +++ b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/PPoint.java @@ -0,0 +1,28 @@ +package com.cnbm.qualityPlanning.entity; + +import lombok.Data; + +/** + * @Desc: "整合,处理好 后的一行数据 (sampleSize 后的数据) " + * @Author: caixiang + * @DATE: 2022/7/21 9:43 + */ +@Data +public class PPoint { + + private ControlLimit controlLimit; + + private Integer position; + + //不合格品数 + private Double value; + + private String name; + + public PPoint(ControlLimit controlLimit, Integer position, Double value,String name) { + this.controlLimit = controlLimit; + this.position = position; + this.value = value; + this.name = name; + } +} diff --git a/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/UPoint.java b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/UPoint.java new file mode 100644 index 0000000..0f61ab1 --- /dev/null +++ b/ym-quality-planning/src/main/java/com/cnbm/qualityPlanning/entity/UPoint.java @@ -0,0 +1,28 @@ +package com.cnbm.qualityPlanning.entity; + +import lombok.Data; + +/** + * @Desc: "整合,处理好 后的一行数据 (sampleSize 后的数据) " + * @Author: caixiang + * @DATE: 2022/7/21 9:43 + */ +@Data +public class UPoint { + + private ControlLimit controlLimit; + + private Integer position; + + //不合格品数 + private Double value; + + private String name; + + public UPoint(ControlLimit controlLimit, Integer position, Double value, String name) { + this.controlLimit = controlLimit; + this.position = position; + this.value = value; + this.name = name; + } +}