项目初始化

This commit is contained in:
黎润豪 2024-10-22 10:46:33 +08:00
commit 49fd89cc28
126 changed files with 17802 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/target/
/youfool-devops.iml
/.idea/
*-backup-*.chnr.json
.back_devops

3
README.md Normal file
View File

@ -0,0 +1,3 @@
**运维管理系统CW**
**相关文档**

6665
db/devops.pdma.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
ALTER TABLE "DEVOPS"."REPAIR_TODO"
MODIFY ("SOURCE" VARCHAR2(10 BYTE));
COMMENT ON COLUMN "DEVOPS"."REPAIR_TODO"."SOURCE" IS '报障单来源1内网、2特设系统外网';
UPDATE "DEVOPS"."REPAIR_TODO" SET "SOURCE" = '1';

156
pom.xml Normal file
View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chinaweal.youfool</groupId>
<artifactId>youfool-devops</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>youfool-devops</name>
<url>https://www.chinaweal.com.cn</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
<log4j.version>2.17.1</log4j.version>
<logback.version>1.2.9</logback.version>
<shiro.version>1.12.0</shiro.version>
</properties>
<dependencies>
<!--基础框架youfool-framework-boot-->
<dependency>
<groupId>com.chinaweal.youfool</groupId>
<artifactId>youfool-framework-springboot</artifactId>
<version>1.1.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot-starter</artifactId>
<version>1.5.16</version>
</dependency>
<!--Java工具类库-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
<!--oracle-->
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
<!--解决oracle不支持的字符集-->
<dependency>
<groupId>cn.easyproject</groupId>
<artifactId>orai18n</artifactId>
<version>12.1.0.2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<!--图片压缩-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.14</version>
</dependency>
<!--把excel导出图片-->
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls</artifactId>
<version>3.9.1</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,45 @@
package com.chinaweal.youfool.devops;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication(scanBasePackages = {"com.chinaweal"})
@Slf4j
@EnableScheduling
public class DevOpsApplication extends SpringBootServletInitializer implements ApplicationListener<ContextRefreshedEvent> {
@Value("${applicationName}")
private String applicationName;
@Value("${version}")
private String version;
@Value("${description}")
private String description;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(DevOpsApplication.class);
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (event.getApplicationContext().getParent() == null) {
log.info("========================== 程序启动成功! ==========================");
log.info("====== 程 序:{} ", applicationName);
log.info("====== 版本号:{} ", version);
log.info("====== 描 述:{} ", description);
log.info("====== 接口文档路径:/doc.html账号admin、密码123456。注如果乱码请指定VM -Dfile.encoding=UTF-8");
log.info("====== Druid Monitor路径/druid账号admin、密码123456");
log.info("====================================================================");
}
}
public static void main(String[] args) {
SpringApplication.run(DevOpsApplication.class, args);
}
}

View File

@ -0,0 +1,72 @@
package com.chinaweal.youfool.devops.base.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.base.entity.Dict;
import com.chinaweal.youfool.devops.base.service.IDictService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* <p>
* 字典 前端控制器
* </p>
*
* @author chinaweal
* @since 2020-07-07
*/
@Api(tags = "1.字典")
@ApiSort(1)
@RestController("devopsDictController")
@RequestMapping("/dict")
public class DictController {
@Resource
private IDictService iDictService;
@GetMapping
@ApiImplicitParam(name = "type", value = "类型", required = true)
@ApiOperation(value = "1.根据类型查询字典列表", position = 1)
public RestResult<List<Dict>> listByType(@RequestParam String type) {
List<Dict> list = iDictService.listByType(type);
return RestResult.ok(list);
}
@ApiOperation(value = "2.字典分类列表", position = 2)
@PostMapping("/list")
public RestResult<IPage<Dict>> list(@RequestBody BaseQuery<Dict> query) {
IPage<Dict> data = iDictService.list(query);
return RestResult.ok(data);
}
@ApiOperation(value = "3.修改字典", position = 3)
@PostMapping("/update")
public RestResult<String> updateDict(@RequestBody Dict dict) {
iDictService.updateById(dict);
return RestResult.ok();
}
@ApiOperation(value = "4.删除字典", position = 4)
@DeleteMapping
public RestResult<String> deleteDict(@RequestParam @ApiParam("字典ID") String dictId) {
iDictService.removeById(dictId);
return RestResult.ok();
}
@ApiOperation(value = "5.新增字典", position = 5)
@PostMapping
public RestResult<String> saveDict(@RequestBody Dict dict) {
iDictService.save(dict);
return RestResult.ok();
}
}

View File

@ -0,0 +1,60 @@
package com.chinaweal.youfool.devops.base.controller;
import com.chinaweal.youfool.devops.base.service.ITaskFileService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
/**
* <p>
* 任务附件 控制器
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Api(tags = "任务附件")
@ApiSort(1)
@RestController
@RequestMapping("/base/taskFile")
public class TaskFileController {
@Resource
private ITaskFileService iTaskFileService;
@ApiOperation(value = "1.上传附件", position = 1)
@PostMapping("/uploadFile")
public RestResult<Map<String, String>> uploadFile(MultipartFile file, @RequestParam String taskId,
@RequestParam(required = false) String handleId, @RequestParam String type) throws IOException {
Map<String, String> body = iTaskFileService.updateFile(file, taskId, type, handleId);
return RestResult.ok(body);
}
@ApiOperation(value = "2.删除文件", position = 2)
@GetMapping("/deleteFile")
public RestResult<String> deleteFile(@RequestParam String id) {
iTaskFileService.deleteFile(id);
return RestResult.ok();
}
@ApiOperation(value = "3.文件下载", position = 3)
@GetMapping(value = "/downloadFile", produces = "application/octet-stream")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "文件ID", required = true),
@ApiImplicitParam(name = "online", value = "是否在线预览true在线、false直接下载")
})
public void downloadFile(@RequestParam String id, @RequestParam(defaultValue = "true") boolean online, HttpServletResponse response) throws IOException {
iTaskFileService.downloadFile(id, online, response);
}
}

View File

@ -0,0 +1,31 @@
package com.chinaweal.youfool.devops.base.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.devops.base.service.ITaskHandleService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.Serializable;
/**
* <p>
* 任务处理流程记录 控制器
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Api(tags = "任务处理流程记录")
@ApiSort(1)
@RestController
@RequestMapping("/base/taskHandle")
public class TaskHandleController {
}

View File

@ -0,0 +1,33 @@
package com.chinaweal.youfool.devops.base.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.chinaweal.youfool.devops.base.service.ITaskListService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* <p>
* 待办表 控制器
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Api(tags = "待办表")
@ApiSort(1)
@RestController
@RequestMapping("/base/taskList")
public class TaskListController {
}

View File

@ -0,0 +1,33 @@
package com.chinaweal.youfool.devops.base.controller.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* 分页查询参数父类
*/
@ApiModel("列表参数父类")
@Data
public class BaseListQuery {
@ApiModelProperty(value = "创建开始时间", dataType = "localDateTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createStart;
@ApiModelProperty(value = "创建结束时间", dataType = "localDateTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createEnd;
@ApiModelProperty(value = "排序字段")
private String orderField;
@ApiModelProperty(value = "排序规则asc升序desc降序")
private String orderSort = "asc";
@ApiModelProperty(value = "当前页", dataType = "int")
private int current = 1;
@ApiModelProperty(value = "每页显示条数", dataType = "int")
private int size = 10;
}

View File

@ -0,0 +1,68 @@
package com.chinaweal.youfool.devops.base.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 字典
* </p>
*
* @author chinaweal
* @since 2020-07-07
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("DICT")
@ApiModel(value = "Dict对象", description = "字典")
public class Dict extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 字典ID
*/
@ApiModelProperty(value = "字典ID")
@TableId(value = "DICT_ID", type = IdType.ASSIGN_UUID)
private String dictId;
/**
* 类型
*/
@ApiModelProperty(value = "类型")
@TableField("TYPE")
private String type;
/**
* 代码
*/
@ApiModelProperty(value = "代码")
@TableField("CODE")
private String code;
/**
* 名称
*/
@ApiModelProperty(value = "名称")
@TableField("NAME")
private String name;
/**
* 排序
*/
@ApiModelProperty(value = "排序")
@TableField("SORT")
private String sort;
}

View File

@ -0,0 +1,101 @@
package com.chinaweal.youfool.devops.base.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* <p>
* 任务附件
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("TASK_FILE")
@ApiModel(value = "TaskFile对象", description = "任务附件")
public class TaskFile extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 文件ID
*/
@ApiModelProperty(value = "文件ID")
@TableId(value = "ID", type = IdType.ASSIGN_UUID)
private String id;
/**
* 文件名
*/
@ApiModelProperty(value = "文件名")
@TableField("FILE_NAME")
private String fileName;
/**
* 文件类型
*/
@ApiModelProperty(value = "文件类型")
@TableField("FILE_TYPE")
private String fileType;
/**
* 类型
*/
@ApiModelProperty(value = "类型")
@TableField("TYPE")
private String type;
/**
* 文件路径
*/
@ApiModelProperty(value = "文件路径")
@TableField("FILE_PATH")
private String filePath;
/**
* 文件大小;单位字节
*/
@ApiModelProperty(value = "文件大小;单位字节")
@TableField("FILE_SIZE")
private Long fileSize;
/**
* 待办id
*/
@ApiModelProperty(value = "待办id")
@TableField("TASK_ID")
private String taskId;
/**
* 处理ID;对处理流程记录
*/
@ApiModelProperty(value = "处理ID;对处理流程记录")
@TableField("HANDLE_ID")
private String handleId;
/**
* 上传时间
*/
@ApiModelProperty(value = "上传时间")
@TableField("UPLOAD_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime uploadTime;
}

View File

@ -0,0 +1,139 @@
package com.chinaweal.youfool.devops.base.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 任务处理流程记录
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("TASK_HANDLE")
@ApiModel(value = "TaskHandle对象", description = "任务处理流程记录")
public class TaskHandle extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 处理ID
*/
@ApiModelProperty(value = "处理ID")
@TableId(value = "HANDLE_ID", type = IdType.ASSIGN_UUID)
private String handleId;
/**
* 待办id
*/
@ApiModelProperty(value = "待办id")
@TableField("TASK_ID")
private String taskId;
/**
* 类型
*/
@ApiModelProperty(value = "类型")
@TableField("BUS_TYPE")
private String busType;
/**
* 处理人
*/
@ApiModelProperty(value = "处理人")
@TableField("HANDLE_NICKNAME")
private String handleNickname;
/**
* 处理人ID
*/
@ApiModelProperty(value = "处理人ID")
@TableField("HANDLE_USER_ID")
private String handleUserId;
/**
* 处理人账号
*/
@ApiModelProperty(value = "处理人账号")
@TableField("HANDLE_USERNAME")
private String handleUsername;
/**
* 环节步骤;start开始assign分派handle处理中feedback已反馈unresolved未解决end结束
*/
@ApiModelProperty(value = "环节步骤;start开始assign分派handle处理中feedback已反馈unresolved未解决end结束")
@TableField("STEP")
private String step;
@ApiModelProperty(value = "步骤次数")
@TableField("ORDER_INDEX")
private Integer orderIndex;
/**
* 生成时间
*/
@ApiModelProperty(value = "生成时间")
@TableField("HAPPEN_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime happenTime;
/**
* 处理结果
*/
@ApiModelProperty(value = "处理结果")
@TableField("RESULT")
private String result;
/**
* 环节状态;0过期1有效
*/
@ApiModelProperty(value = "环节状态;0过期1有效")
@TableField("STATUS")
private String status;
@TableField(exist = false)
private List<TaskFile> files = new ArrayList<>();
/**
* 下一个节点表单
*/
@TableField(exist = false)
private String nextStep;
/**
* 下一个步处理人用户
*/
@TableField(exist = false)
private String nextHandleUsername;
/**
* 下一个步处理人用户id
*/
@TableField(exist = false)
private String nextHandleUserId;
/**
* 下一个步处理人名
*/
@TableField(exist = false)
private String nextHandleNickname;
}

View File

@ -0,0 +1,198 @@
package com.chinaweal.youfool.devops.base.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.chinaweal.youfool.framework.springboot.util.ConstantsUtil;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* <p>
* 待办表
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("TASK_LIST")
@ApiModel(value = "TaskList对象", description = "待办表")
public class TaskList extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 待办ID
*/
@ApiModelProperty(value = "待办ID")
@TableId(value = "task_id", type = IdType.ASSIGN_UUID)
private String taskId;
/**
* 业务表ID,对应业务的表的ID
*/
@ApiModelProperty(value = "业务表ID,对应业务的表的ID")
@TableField("BIZ_ID")
private String bizId;
/**
* 标题
*/
@ApiModelProperty(value = "标题")
@TableField("TITLE")
private String title;
/**
* 申报账号ID
*/
@ApiModelProperty(value = "申报账号ID")
@TableField("SEND_ID")
private String sendId;
/**
* 申报用户昵称
*/
@ApiModelProperty(value = "申报用户昵称")
@TableField("SEND_NAME")
private String sendName;
/**
* 申报用户账号
*/
@ApiModelProperty(value = "申报用户账号")
@TableField("SEND_USERNAME")
private String sendUsername;
/**
* 签收人ID个人或机构
*/
@ApiModelProperty(value = "签收人ID个人或机构")
@TableField("SIGN_ID")
private String signId;
/**
* 签收人账号个人或机构
*/
@ApiModelProperty(value = "签收人账号,个人或机构")
@TableField("SIGN_USERNAME")
private String signUsername;
/**
* 签收人名称
*/
@ApiModelProperty(value = "签收人名称")
@TableField("SIGN_NAME")
private String signName;
/**
* 所属机构Id
*/
@ApiModelProperty(value = "所属机构Id")
@TableField("ORG_ID")
private String orgId;
/**
* 所属机构
*/
@ApiModelProperty(value = "所属机构")
@TableField("ORG")
private String org;
/**
* 所属部门Id
*/
@ApiModelProperty(value = "所属部门Id")
@TableField("DEPT_ID")
private String deptId;
/**
* 所属部门
*/
@ApiModelProperty(value = "所属部门")
@TableField("DEPT")
private String dept;
/**
* 业务类型;assign:领导交办
*/
@ApiModelProperty(value = "业务类型;assign:领导交办")
@TableField("BUS_TYPE")
private String busType;
/**
* 优先级别;1紧急234
*/
@ApiModelProperty(value = "优先级别;1紧急234低")
@TableField("PRIORITY")
private Integer priority;
/**
* 紧急程度;1紧急234
*/
@ApiModelProperty(value = "紧急程度;1紧急234低")
@TableField("URGENCY")
private Integer urgency;
/**
* 环节步骤;
*/
@ApiModelProperty(value = "环节步骤;")
@TableField("STEP")
private String step;
/**
* 催单次数
*/
@ApiModelProperty(value = "催单次数")
@TableField("REMINDER")
private Integer reminder;
/**
* 是否删除;0有效1删除
*/
@ApiModelProperty(value = "是否删除;0有效1删除")
@TableField("DELETED")
@TableLogic(value = ConstantsUtil.NOT_DELETED, delval = ConstantsUtil.DELETED)
private String deleted;
/**
* 报送时间
*/
@ApiModelProperty(value = "报送时间")
@TableField("LAUNCH_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime launchTime;
/**
* 到期时间
*/
@ApiModelProperty(value = "到期时间")
@TableField("SOLVE_LIMIT_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime solveLimitTime;
/**
* 处理更新时间
*/
@ApiModelProperty(value = "处理更新时间")
@TableField("HANDLE_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime handleTime;
/**
* 任务状态 0在办1办结
*/
@ApiModelProperty(value = "任务状态 0在办1办结")
@TableField("status")
private String status;
}

View File

@ -0,0 +1,18 @@
package com.chinaweal.youfool.devops.base.mapper;
import com.chinaweal.youfool.devops.base.entity.Dict;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
/**
* <p>
* 字典 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-07-07
*/
@Repository("devopsDictMapper")
public interface DictMapper extends BaseMapper<Dict> {
}

View File

@ -0,0 +1,16 @@
package com.chinaweal.youfool.devops.base.mapper;
import com.chinaweal.youfool.devops.base.entity.TaskFile;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 任务附件 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface TaskFileMapper extends BaseMapper<TaskFile> {
}

View File

@ -0,0 +1,21 @@
package com.chinaweal.youfool.devops.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 任务处理流程记录 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface TaskHandleMapper extends BaseMapper<TaskHandle> {
/**
* 根据bizId查询最大的orderIndex值
*/
Long maxOrderIndex(@Param("taskId") String taskId);
}

View File

@ -0,0 +1,16 @@
package com.chinaweal.youfool.devops.base.mapper;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 待办表 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface TaskListMapper extends BaseMapper<TaskList> {
}

View File

@ -0,0 +1,35 @@
package com.chinaweal.youfool.devops.base.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.devops.base.entity.Dict;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import java.util.List;
/**
* <p>
* 字典 服务类
* </p>
*
* @author chinaweal
* @since 2020-07-07
*/
public interface IDictService extends IService<Dict> {
String LABEL = "label";
String QUESTION = "question";
String ASSIGN_EVENT_TYPE = "assignEventType";
List<Dict> listByType(String type);
Dict getByTypeAndCode(String type, String code);
void saveNameByTypeCode(String type, String code, String name);
IPage<Dict> list(BaseQuery<Dict> query);
void addDict(String type,String name);
}

View File

@ -0,0 +1,14 @@
package com.chinaweal.youfool.devops.base.service;
/**
* 自定义运维监控例如密码过期监控
*/
public interface IMonitorService {
/**
* 查询数据库密码过期情况
*/
void countDbPwdExpireAndSendWx() throws Exception;
}

View File

@ -0,0 +1,43 @@
package com.chinaweal.youfool.devops.base.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.devops.base.entity.TaskFile;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* <p>
* 任务附件 服务类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface ITaskFileService extends IService<TaskFile> {
/**
* 分页查询任务附件
*/
IPage<TaskFile> listTaskFile(BaseQuery<TaskFile> query);
Map<String, String> updateFile(MultipartFile file, String bizId, String type, String handleId) throws IOException;
/**
* 获取上传保存相对目录格式类型 + 当天的日期
*/
String filePath(String type);
void deleteFile(String id);
List<TaskFile> listByTaskIdAndType(String taskId, String type);
List<TaskFile> listByHandleId(String handleId);
void downloadFile(String id, boolean online, HttpServletResponse response) throws IOException;
}

View File

@ -0,0 +1,44 @@
package com.chinaweal.youfool.devops.base.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import java.util.List;
/**
* <p>
* 任务处理流程记录 服务类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface ITaskHandleService extends IService<TaskHandle> {
/**
* 通用的节点标识
*/
String STRART = "start"; //开始
String END = "end"; //结束
String ASSIGN = "assign";//分派
String FEEDBACK = "feedback";//处理反馈
String UNRESOLVED = "unresolved";//未解决
String RESOLVED = "resolved";//已解决
/**
* 分页查询任务处理流程记录
*/
IPage<TaskHandle> listTaskHandle(BaseQuery<TaskHandle> query);
/**
* 流程下一步更新
*/
void next(TaskHandle taskHandle);
/**
* 通过任务id获取流程跟踪记录
*/
List<TaskHandle> listByTaskId(String taskId);
}

View File

@ -0,0 +1,33 @@
package com.chinaweal.youfool.devops.base.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
/**
* <p>
* 待办表 服务类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface ITaskListService extends IService<TaskList> {
/**
* 业务类型
*/
String BUS_TYPE_ASSIGN = "assign";//领导交办
/**
* 分页查询待办表
*/
IPage<TaskList> listTaskList(BaseQuery<TaskList> query);
/**
* 新建任务
*/
TaskHandle createTask(TaskList task, String result);
}

View File

@ -0,0 +1,90 @@
package com.chinaweal.youfool.devops.base.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.base.entity.Dict;
import com.chinaweal.youfool.devops.base.mapper.DictMapper;
import com.chinaweal.youfool.devops.base.service.IDictService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 字典 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-07-07
*/
@Service("devopsDictServiceImpl")
@Transactional("devopsTransactionManager")
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements IDictService {
@Override
public List<Dict> listByType(String type) {
LambdaQueryWrapper<Dict> qw = new LambdaQueryWrapper<>();
qw.eq(Dict::getType, type)
.orderByAsc(Dict::getSort);
List<Dict> list = list(qw);
return list;
}
@Override
public Dict getByTypeAndCode(String type, String code) {
LambdaQueryWrapper<Dict> qw = new LambdaQueryWrapper<>();
qw.eq(Dict::getType, type).eq(Dict::getCode, code);
Dict dict = getOne(qw);
return dict;
}
@Override
public void saveNameByTypeCode(String type, String code, String name) {
Dict dict = getByTypeAndCode(type, code);
if (dict == null) {
dict = new Dict();
dict.setType(type);
dict.setCode(code);
dict.setName(name);
save(dict);
}
}
@Override
public IPage<Dict> list(BaseQuery<Dict> query) {
Dict entity = query.getEntity(Dict.class);
Page<Dict> page = query.getPage();
LambdaQueryWrapper<Dict> lqw = Wrappers.lambdaQuery();
lqw.eq(Dict::getType, entity.getType());
lqw.like(StringUtils.isNotBlank(entity.getName()), Dict::getName, entity.getName());
if (page.getOrders().isEmpty()) {
page.addOrder(OrderItem.desc("update_time"));
}
return page(page, lqw);
}
@Override
public void addDict(String type, String name) {
LambdaQueryWrapper<Dict> lqw = Wrappers.lambdaQuery();
lqw.eq(Dict::getType, type).eq(Dict::getName, name);
Dict dict = getOne(lqw);
if (dict == null) {
//不存在,则新增
dict = new Dict();
dict.setType(type);
dict.setCode(name);
dict.setName(name);
save(dict);
}
}
}

View File

@ -0,0 +1,115 @@
package com.chinaweal.youfool.devops.base.service.impl;
import com.chinaweal.youfool.devops.base.service.IMonitorService;
import com.chinaweal.youfool.devops.repair.api.RobotApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.*;
@Service
@Slf4j
public class MonitorServiceImpl implements IMonitorService {
@Value("${dbUsernames}")
private String[] dbUsernames;
@Value("${dbWebhookKeys}")
private String[] dbWebhookKeys;
@Resource
private RobotApi robotApi;
@Override
public void countDbPwdExpireAndSendWx() throws Exception {
List<String> list = new ArrayList<>();
//145数据库
list = findExpireUserInfo("jdbc:oracle:thin:@19.130.241.145:1521:FSAMRDATA", "system", "Chinaweal", "19.130.241.145");
//147数据库
list.addAll(findExpireUserInfo("jdbc:oracle:thin:@19.130.241.147:1521:FSAMRDATA", "system", "Chinaweal_2022", "19.130.241.147"));
//152数据库
list.addAll(findExpireUserInfo("jdbc:oracle:thin:@19.130.241.152:1521:FSAMRDATA", "system", "Chinaweal", "19.130.241.152"));
//顺德133数据库
list.addAll(findExpireUserInfo("jdbc:oracle:thin:@19.202.179.133:1521:SDAMRDATA", "system", "ChinaWeal_2020", "19.202.179.133"));
if (list.size() == 0) {
//没有账号过期,则不需要提醒
return;
}
String tip = "数据库账号密码过期提醒,有" + list.size() + "个账号即将过期!\n" +
"主机 -> 账号 -> 过期时间\n";
for (String s : list) {
//拼接账号
tip += s;
}
Map<String, Object> content = new HashMap<>();
content.put("content", tip);
content.put("mentioned_mobile_list", new String[]{"13827173481"});
Map<String, Object> query = new HashMap<>();
query.put("msgtype", "text");
query.put("text", content);
for (String dbWebhookKey : dbWebhookKeys) {
robotApi.webhookSend(query, dbWebhookKey);
}
}
/**
* 获取过期账号列表信息文本
*/
private List<String> findExpireUserInfo(String jdbc, String user, String pwd, String ip) {
//动态加载,减少依赖性
List<String> list = new ArrayList<>();
try {
Class<?> aClass = Class.forName("oracle.jdbc.driver.OracleDriver");
Driver driver = (Driver) aClass.getDeclaredConstructor().newInstance();
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", pwd);
//properties.setProperty("internal_logon", "sysdba");
Connection connect = driver.connect(jdbc, properties);
String sql = "select username,account_status,EXPIRY_DATE from dba_users " +
"where EXPIRY_DATE - 7 < sysdate and USERNAME in";
String join = StringUtils.join(dbUsernames, "','");
sql = sql + "('" + join + "')";
PreparedStatement pre = connect.prepareStatement(sql);
ResultSet resultSet = pre.executeQuery();
list = new ArrayList<>();
while (resultSet.next()) {
String username = resultSet.getString("USERNAME");
//String accountStatus = resultSet.getString("ACCOUNT_STATUS");
Date expiryDate = resultSet.getDate("EXPIRY_DATE");
String text = ip + " -> " + username + " -> " + (expiryDate != null ? DateFormatUtils.format(expiryDate, "yyyy-MM-dd HH:mm:ss") : "") + "\n";
list.add(text);
}
} catch (Exception e) {
log.error("连接{}数据库出错!", jdbc, e);
String tip = ip + "数据库,用户:" + user + ",连接出错,请检查!";
tip += "\n错误信息" + e;
Map<String, Object> content = new HashMap<>();
content.put("content", tip);
content.put("mentioned_mobile_list", new String[]{"13827173481"});
Map<String, Object> query = new HashMap<>();
query.put("msgtype", "text");
query.put("text", content);
for (String dbWebhookKey : dbWebhookKeys) {
robotApi.webhookSend(query, dbWebhookKey);
}
}
return list;
}
}

View File

@ -0,0 +1,171 @@
package com.chinaweal.youfool.devops.base.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.base.entity.TaskFile;
import com.chinaweal.youfool.devops.base.mapper.TaskFileMapper;
import com.chinaweal.youfool.devops.base.service.ITaskFileService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.util.DateTimeUtils;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* <p>
* 任务附件 服务实现类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Service
@Slf4j
@Transactional("devopsTransactionManager")
public class TaskFileServiceImpl extends ServiceImpl<TaskFileMapper, TaskFile> implements ITaskFileService {
@Value("${file.devopsDir}")
private String devopsDir;
@Override
public IPage<TaskFile> listTaskFile(BaseQuery<TaskFile> query) {
TaskFile entity = query.getEntity(TaskFile.class);
Page<TaskFile> page = query.getPage();
LambdaQueryWrapper<TaskFile> lambdaQueryWrapper = Wrappers.lambdaQuery();
return page(page, lambdaQueryWrapper);
}
@Override
public Map<String, String> updateFile(MultipartFile multipartFile, String taskId, String type, String handleId) throws IOException {
TaskFile taskFile = new TaskFile();
taskFile.setTaskId(taskId);
taskFile.setFileName(multipartFile.getOriginalFilename());
taskFile.setFileType(multipartFile.getContentType());
taskFile.setType(type);
taskFile.setHandleId(handleId);
taskFile.setUploadTime(LocalDateTime.now());
int i = multipartFile.getOriginalFilename().lastIndexOf(".");
String filePathName = UUID.randomUUID().toString();
if (i > 0) {
filePathName += multipartFile.getOriginalFilename().substring(i);
}
filePathName = filePath(taskFile.getType()) + File.separator + filePathName;
taskFile.setFilePath(filePathName);
File file = new File(devopsDir + File.separator + filePathName);
file.mkdirs();
try (InputStream is = multipartFile.getInputStream();) {
if (StringUtils.containsIgnoreCase(multipartFile.getContentType(), "image")
&& multipartFile.getSize() >= 2 * 1024 * 1024) { // 大于2M进行压缩
//压缩图片
TimeInterval timer = DateUtil.timer();
Thumbnails.of(is).scale(1f).outputQuality(0.5f).toFile(file);
log.debug("图片压缩耗时: {} ms", timer.interval());
} else {
multipartFile.transferTo(file);
}
} catch (IOException e) {
log.error("上传出错", e);
throw new RuntimeException(e.getMessage());
}
taskFile.setFileSize(file.length());
save(taskFile);
Map<String, String> body = new LinkedHashMap<>();
body.put("id", taskFile.getId());
body.put("taskId", taskFile.getTaskId());
return body;
}
@Override
public String filePath(String type) {
return type + File.separator + LocalDate.now().format(DateTimeUtils.SHORT_DATE_FORMATTER);
}
@Override
public void deleteFile(String id) {
TaskFile taskFile = getById(id);
if (taskFile == null) {
return;
}
File file = new File(devopsDir + taskFile.getFilePath());
if (file.exists()) {
file.delete();
}
removeById(id);
}
@Override
public List<TaskFile> listByTaskIdAndType(String taskId, String type) {
LambdaQueryWrapper<TaskFile> lqw = Wrappers.lambdaQuery();
lqw.eq(TaskFile::getTaskId, taskId)
.eq(TaskFile::getType, type)
.orderByAsc(TaskFile::getUploadTime);
return list(lqw);
}
@Override
public List<TaskFile> listByHandleId(String handleId) {
LambdaQueryWrapper<TaskFile> lqw = Wrappers.lambdaQuery();
lqw.eq(TaskFile::getHandleId, handleId)
.orderByAsc(TaskFile::getUploadTime);
return list(lqw);
}
@Override
public void downloadFile(String id, boolean online, HttpServletResponse response) throws IOException {
TaskFile taskFile = getById(id);
if (taskFile == null) {
return;
}
//拼接绝对路径,获取流
InputStream is;
try {
is = new FileInputStream(devopsDir + "/" + taskFile.getFilePath());
} catch (FileNotFoundException e) {
log.warn(e.getMessage());
return;
}
OutputStream os = response.getOutputStream();
String fileName = new String(taskFile.getFileName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
if (online) {
//直接展示
response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
} else {
//设置:当浏览器收到这份资源的时候,以下载的方式提醒用户,而不是直接显示
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
}
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.close();
is.close();
}
}

View File

@ -0,0 +1,82 @@
package com.chinaweal.youfool.devops.base.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.chinaweal.youfool.devops.base.mapper.TaskHandleMapper;
import com.chinaweal.youfool.devops.base.service.ITaskHandleService;
import com.chinaweal.youfool.devops.base.service.ITaskListService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 任务处理流程记录 服务实现类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Service
@Transactional("devopsTransactionManager")
public class TaskHandleServiceImpl extends ServiceImpl<TaskHandleMapper, TaskHandle> implements ITaskHandleService {
@Resource
private ITaskListService iTaskListService;
@Override
public IPage<TaskHandle> listTaskHandle(BaseQuery<TaskHandle> query) {
TaskHandle entity = query.getEntity(TaskHandle.class);
Page<TaskHandle> page = query.getPage();
LambdaQueryWrapper<TaskHandle> lambdaQueryWrapper = Wrappers.lambdaQuery();
return page(page, lambdaQueryWrapper);
}
@Override
public void next(TaskHandle taskHandle) {
//失效之前的有效状态
LambdaUpdateWrapper<TaskHandle> ulq = Wrappers.lambdaUpdate();
ulq.eq(TaskHandle::getTaskId, taskHandle.getTaskId())
.set(TaskHandle::getStatus, "0");
update(ulq);
//获取最后的order_index值
Long index = baseMapper.maxOrderIndex(taskHandle.getTaskId());
if (index == null) {
index = 0L;
}
taskHandle.setHappenTime(LocalDateTime.now());
taskHandle.setStatus("1");
taskHandle.setOrderIndex((int) (index + 1));
save(taskHandle);
//更新taskList的step字段和处理时间字段
LambdaUpdateWrapper<TaskList> uqw = Wrappers.lambdaUpdate();
uqw.eq(TaskList::getTaskId, taskHandle.getTaskId())
.set(TaskList::getStep, taskHandle.getStep())
.set(TaskList::getHandleTime, LocalDateTime.now());
iTaskListService.update(uqw);
}
@Override
public List<TaskHandle> listByTaskId(String taskId) {
LambdaQueryWrapper<TaskHandle> lqw = Wrappers.lambdaQuery();
lqw.eq(TaskHandle::getTaskId, taskId);
lqw.orderByAsc(TaskHandle::getOrderIndex);
List<TaskHandle> list = list(lqw);
return list;
}
}

View File

@ -0,0 +1,65 @@
package com.chinaweal.youfool.devops.base.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.chinaweal.youfool.devops.base.mapper.TaskListMapper;
import com.chinaweal.youfool.devops.base.service.ITaskHandleService;
import com.chinaweal.youfool.devops.base.service.ITaskListService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.util.ConstantsUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* <p>
* 待办表 服务实现类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Service
@Transactional("devopsTransactionManager")
public class TaskListServiceImpl extends ServiceImpl<TaskListMapper, TaskList> implements ITaskListService {
@Resource
private ITaskHandleService iTaskHandleService;
@Override
public IPage<TaskList> listTaskList(BaseQuery<TaskList> query) {
TaskList entity = query.getEntity(TaskList.class);
Page<TaskList> page = query.getPage();
LambdaQueryWrapper<TaskList> lambdaQueryWrapper = Wrappers.lambdaQuery();
return page(page, lambdaQueryWrapper);
}
@Override
public TaskHandle createTask(TaskList task, String result) {
task.setStep(ITaskHandleService.STRART);
task.setDeleted(ConstantsUtil.NOT_DELETED);
save(task);
//插入流程表,启动流程
TaskHandle taskHandle = new TaskHandle();
taskHandle.setTaskId(task.getTaskId());
taskHandle.setStep(task.getStep());
taskHandle.setHandleUserId(task.getSendId());
taskHandle.setHandleNickname(task.getSendName());
taskHandle.setHandleUsername(task.getSendUsername());
taskHandle.setBusType(task.getBusType());
taskHandle.setResult(result);
iTaskHandleService.next(taskHandle);
return taskHandle;
}
}

View File

@ -0,0 +1,25 @@
package com.chinaweal.youfool.devops.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/statistic/**").
allowedOrigins("*"). //允许跨域的域名,可以用*表示允许任何域名使用
allowedMethods("*"). //允许任何方法post、get等
allowedHeaders("*"). //允许任何请求头
allowCredentials(true). //带上cookie信息
exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内不需要再发送预检验请求可以缓存该结果
}
};
}
}

View File

@ -0,0 +1,70 @@
package com.chinaweal.youfool.devops.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.CommonMetaObjectHandler;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* 运维模块的数据源
*
* @author itluck
*/
@Configuration
@MapperScan(basePackages = {"com.chinaweal.youfool.devops.repair.**.mapper", "com.chinaweal.youfool.devops.base.**.mapper", "com.chinaweal.youfool.devops.leaderassign.**.mapper", "com.chinaweal.youfool.devops.org.mapper"}, sqlSessionTemplateRef = "devopsSqlSessionTemplate")
public class DevopsDataSource {
@Bean(name = "devopsDS", initMethod = "init", destroyMethod = "close")
@ConfigurationProperties(prefix = "spring.datasource.devops")
@Primary
public DruidDataSource dataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "devopsSqlSessionFactory")
public MybatisSqlSessionFactoryBean sqlSessionFactory(@Qualifier("devopsDS") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(new CommonMetaObjectHandler());
bean.setGlobalConfig(globalConfig);
bean.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml"));
bean.setPlugins(paginationInterceptor());// 分页插件
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/**/*.xml"));
return bean;
}
@Bean(name = "devopsTransactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("devopsDS") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "devopsSqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("devopsSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置最大单页限制数量,默认 500 条,-1 不受限制
paginationInterceptor.setLimit(-1);
return paginationInterceptor;
}
}

View File

@ -0,0 +1,39 @@
package com.chinaweal.youfool.devops.config;
import com.chinaweal.youfool.framework.springboot.filter.RepeatlyReadFilter;
import com.chinaweal.youfool.framework.springboot.log.filter.RestLogFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author itluck
*/
@Configuration
public class FilterConfig {
/**
* 日志记录过滤器
*/
@Bean
public FilterRegistrationBean<RestLogFilter> restLogFilter() {
FilterRegistrationBean<RestLogFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new RestLogFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setName("restLogFilter");
registrationBean.setOrder(-99);
return registrationBean;
}
/**
* 开启重复读取request流用于日志
*/
@Bean
public FilterRegistrationBean<RepeatlyReadFilter> repeatlyReadFilter() {
FilterRegistrationBean<RepeatlyReadFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new RepeatlyReadFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setName("repeatlyReadFilter");
registrationBean.setOrder(-100);
return registrationBean;
}
}

View File

@ -0,0 +1,50 @@
package com.chinaweal.youfool.devops.config;
import com.chinaweal.youfool.devops.org.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(loginInterceptor);
registration.addPathPatterns("/**");
//添加不拦截路径
List<String> excludes = new ArrayList<>();
excludes.add("/**/*.html");
excludes.add("/**/*.js");
excludes.add("/**/*.css");
excludes.add("/**/*.woff");
excludes.add("/**/*.ttf");
excludes.add("/**/*.png");
// excludes.add("/swagger-resources/**");
excludes.add("/user/loginBusiness");
excludes.add("/user/loginOuter");
excludes.add("/user/loginEngineer");
excludes.add("/user/vcode");
excludes.add("/user/clearFreq");
excludes.add("/repair/downloadFile");
excludes.add("/repair/uploadFile");
excludes.add("/repair/notification/**");
excludes.add("/repair/exportTodo");
excludes.add("/statistic/exportSumSummary");
excludes.add("/statistic/exportListByItemId");
excludes.add("/statistic/exportGroupOrg");
excludes.add("/statistic/countRepairStepByUserId");
excludes.add("/base/taskFile/uploadFile");
excludes.add("/base/taskFile/downloadFile");
registration.excludePathPatterns(excludes);
}
}

View File

@ -0,0 +1,20 @@
package com.chinaweal.youfool.devops.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.stereotype.Component;
/**
* 引入properties常用值
*/
@Component
@Configuration
@PropertySource(value = {"classpath:properties/youfool-devops.properties"}, encoding = "UTF-8")
public class PropertySourceConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}

View File

@ -0,0 +1,14 @@
package com.chinaweal.youfool.devops.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* 引用定时任务的xml
*/
@Configuration
@ImportResource(locations = {"classpath:spring-timer.xml"})
public class SchedulingXmlConfig {
}

View File

@ -0,0 +1,123 @@
package com.chinaweal.youfool.devops.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* @author itluck
*/
@Configuration
@EnableSwagger2
@EnableKnife4j
@ConditionalOnProperty(value = "swagger.enable", havingValue = "true")
public class SwaggerKnife4j {
@Value("${applicationName}")
private String applicationName;
@Value("${version}")
private String version;
@Value("${description}")
private String description;
@Value("${license}")
private String license;
@Bean("orgApi")
public Docket orgApi() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> headers = new ArrayList<>();
tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
headers.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())
.groupName("组织架构")
.select()
.apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.org"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(headers);
}
@Bean("devopsApi")
public Docket devopsApi() {
//添加head参数start
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> headers = new ArrayList<>();
tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
headers.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())
.groupName("运维报障")
.select()
.apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.repair"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(headers);
}
@Bean("basisApi")
public Docket basisApi() {
//添加head参数start
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> headers = new ArrayList<>();
tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
headers.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())
.groupName("基础环境")
.select()
.apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.base"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(headers);
}
@Bean("websocketApi")
public Docket websocketApi() {
//添加head参数start
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> headers = new ArrayList<>();
tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
headers.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())
.groupName("WebSocket测试环境")
.select()
.apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.websocket"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(headers);
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(applicationName)
.description(description)
.termsOfServiceUrl("https://www.chinaweal.com.cn")
.version(version)
.contact(new Contact("chinaweal", "https://www.chinaweal.com.cn", ""))
.license(license)
.licenseUrl("https://www.chinaweal.com.cn")
.build();
}
}

View File

@ -0,0 +1,59 @@
package com.chinaweal.youfool.devops.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.CommonMetaObjectHandler;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* youfool基础的数据源
*
* @author itluck
*/
@Configuration
@MapperScan(basePackages = "com.chinaweal.youfool.framework.springboot.**.mapper", sqlSessionTemplateRef = "youfoolSqlSessionTemplate")
public class YoufoolDataSource {
@Bean(name = "youfoolDS", initMethod = "init", destroyMethod = "close")
@ConfigurationProperties(prefix = "spring.datasource.youfool")
public DruidDataSource dataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "youfoolSqlSessionFactory")
public MybatisSqlSessionFactoryBean sqlSessionFactory(@Qualifier("youfoolDS") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(new CommonMetaObjectHandler());
bean.setGlobalConfig(globalConfig);
bean.setConfigLocation(new ClassPathResource("youfool/mybatis/mybatis-config.xml"));
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:youfool/mybatis/mapper/**/*.xml"));
return bean;
}
@Bean(name = "youfoolTransactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("youfoolDS") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "youfoolSqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("youfoolSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

View File

@ -0,0 +1,14 @@
package com.chinaweal.youfool.devops.dev;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.CodeGenerator;
/**
* 代码生成器
*/
public class MybatisPlusCodeGenerator {
public static void main(String[] args) {
CodeGenerator codeGenerator = new CodeGenerator("properties/codeCenerator");
codeGenerator.generateCode();
}
}

View File

@ -0,0 +1,89 @@
package com.chinaweal.youfool.devops.leaderassign.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.AssignHandleQuery;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.TaskAssignVo;
import com.chinaweal.youfool.devops.leaderassign.entity.Assign;
import com.chinaweal.youfool.devops.leaderassign.service.IAssignService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Map;
/**
* <p>
* 领导交办详情 控制器
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Api(tags = "领导交办详情")
@ApiSort(1)
@RestController
@RequestMapping("/assign")
public class AssignController {
@Resource
private IAssignService iAssignService;
@ApiOperation(value = "1.新增领导交办详情", position = 1)
@PostMapping("/save")
public RestResult<Assign> saveAssign(@RequestBody @Valid Assign assign, BindingResult bindingResult) {
AssertUtils.isBndingValidit(bindingResult);
assign = iAssignService.saveAssign(assign);
return RestResult.ok(assign);
}
@ApiOperation(value = "2.分页查询领导交办列表", position = 2)
@PostMapping("/listTask")
public RestResult<IPage<TaskAssignVo>> listTask(@RequestBody Map map) {
IPage<TaskAssignVo> data = iAssignService.listTask(map);
return RestResult.ok(data);
}
@ApiOperation(value = "3.查看领导交办详情", position = 3)
@GetMapping("/getAssign")
public RestResult<Assign> getAssign(@RequestParam @ApiParam("bizId") String bizId) {
Assign assign = iAssignService.getAssign(bizId);
return RestResult.ok(assign);
}
@ApiOperation(value = "4.删除领导交办", position = 4)
@PostMapping("/deleteAssign")
public RestResult<String> deleteAssign(@RequestParam @ApiParam("bizId") String bizId) {
iAssignService.deleteAssign(bizId);
return RestResult.ok();
}
@ApiOperation(value = "5.流程节点扭转", position = 5)
@PostMapping("/next")
public RestResult<String> next(@RequestBody AssignHandleQuery data) {
iAssignService.next(data);
return RestResult.ok();
}
@ApiOperation(value = "6.更新处理信息", position = 6)
@PostMapping("/updateHandle")
public RestResult<String> updateHandle(@RequestBody Assign assign) {
iAssignService.updateHandle(assign);
return RestResult.ok();
}
@ApiOperation(value = "7.更新表单信息", position = 7)
@PostMapping("/updateAssign")
public RestResult<String> updateAssign(@RequestBody Assign assign) {
iAssignService.updateAssign(assign);
return RestResult.ok();
}
}

View File

@ -0,0 +1,48 @@
package com.chinaweal.youfool.devops.leaderassign.controller.dto;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 领导交办流程操作实体
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class AssignHandleQuery extends TaskHandle {
private static final long serialVersionUID = 1L;
/**
* 交办单号ID
*/
@ApiModelProperty(value = "交办单号ID")
private String bizId;
/**
* 优先级别;1紧急234
*/
@ApiModelProperty(value = "优先级别;1紧急234低")
private Integer priority;
/**
* 计划完成时间
*/
@ApiModelProperty(value = "计划完成时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime plannedTime;
/**
* 实际完成时间
*/
@ApiModelProperty(value = "实际完成时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime realityTime;
}

View File

@ -0,0 +1,172 @@
package com.chinaweal.youfool.devops.leaderassign.controller.dto;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 领导交办待办列表的vo
*/
@Data
public class TaskAssignVo implements Serializable {
/**
* 待办ID
*/
@ApiModelProperty(value = "待办ID")
private String id;
/**
* 业务表ID,对应业务的表的ID
*/
@ApiModelProperty(value = "业务表ID,对应业务的表的ID")
private String bizId;
/**
* 标题
*/
@ApiModelProperty(value = "标题")
private String title;
/**
* 申报账号ID
*/
@ApiModelProperty(value = "申报账号ID")
private String sendId;
/**
* 申报用户昵称
*/
@ApiModelProperty(value = "申报用户昵称")
private String sendName;
/**
* 申报用户账号
*/
@ApiModelProperty(value = "申报用户账号")
private String sendUsername;
/**
* 签收人ID个人或机构
*/
@ApiModelProperty(value = "签收人ID个人或机构")
private String signId;
/**
* 签收人名称
*/
@ApiModelProperty(value = "签收人名称")
private String signName;
/**
* 所属机构Id
*/
@ApiModelProperty(value = "所属机构Id")
private String orgId;
/**
* 所属机构
*/
@ApiModelProperty(value = "所属机构")
private String org;
/**
* 所属部门Id
*/
@ApiModelProperty(value = "所属部门Id")
private String deptId;
/**
* 所属部门
*/
@ApiModelProperty(value = "所属部门")
private String dept;
/**
* 业务类型;assign:领导交办
*/
@ApiModelProperty(value = "业务类型;assign:领导交办")
private String busType;
/**
* 优先级别;1紧急234
*/
@ApiModelProperty(value = "优先级别;1紧急234低")
private Integer priority;
/**
* 紧急程度;1紧急234
*/
@ApiModelProperty(value = "紧急程度;1紧急234低")
private Integer urgency;
/**
* 环节步骤;
*/
@ApiModelProperty(value = "环节步骤;")
private String step;
/**
* 催单次数
*/
@ApiModelProperty(value = "催单次数")
private Integer reminder;
/**
* 是否删除;0有效1删除
*/
@ApiModelProperty(value = "是否删除;0有效1删除")
private String deleted;
/**
* 报送时间
*/
@ApiModelProperty(value = "报送时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime launchTime;
/**
* 到期时间
*/
@ApiModelProperty(value = "到期时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime solveLimitTime;
/**
* 处理更新时间
*/
@ApiModelProperty(value = "处理更新时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime handleTime;
/**
* 任务状态 0在办1办结
*/
@ApiModelProperty(value = "任务状态 0在办1办结")
private String status;
/**
* 事件描述
*/
@ApiModelProperty(value = "事件描述")
private String content;
/**
* 交办时间
*/
@ApiModelProperty(value = "交办时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime assignTime;
/**
* 计划完成时间
*/
@ApiModelProperty(value = "计划完成时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime plannedTime;
}

View File

@ -0,0 +1,245 @@
package com.chinaweal.youfool.devops.leaderassign.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.devops.base.entity.TaskFile;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.chinaweal.youfool.framework.springboot.util.ConstantsUtil;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 领导交办详情
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("ASSIGN")
@ApiModel(value = "Assign对象", description = "领导交办详情")
public class Assign extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 交办单号ID
*/
@ApiModelProperty(value = "交办单号ID")
@TableId(value = "BIZ_ID")
private String bizId;
/**
* 待办id
*/
@ApiModelProperty(value = "待办id")
@TableField("TASK_ID")
private String taskId;
/**
* 标题
*/
@ApiModelProperty(value = "标题")
@TableField("TITLE")
@NotBlank(message = "标题不能为空")
private String title;
/**
* 领导名称
*/
@ApiModelProperty(value = "领导名称")
@TableField("leader_name")
@NotBlank(message = "领导名称不能为空")
private String leaderName;
/**
* 申报账号ID
*/
@ApiModelProperty(value = "申报账号ID")
@TableField("SEND_ID")
private String sendId;
/**
* 申报用户昵称
*/
@ApiModelProperty(value = "申报用户昵称")
@TableField("SEND_NAME")
private String sendName;
/**
* 申报用户账号
*/
@ApiModelProperty(value = "申报用户账号")
@TableField("SEND_USERNAME")
@NotBlank(message = "申报用户账号不能为空")
private String sendUsername;
/**
* 处理人id
*/
@ApiModelProperty(value = "处理人id")
@TableField("HANDLE_USERID")
private String handleUserid;
/**
* 处理人账号
*/
@ApiModelProperty(value = "处理人账号")
@TableField("HANDLE_USER")
private String handleUser;
/**
* 处理人
*/
@ApiModelProperty(value = "处理人")
@TableField("HANDLE_NAME")
private String handleName;
/**
* 所属机构Id
*/
@ApiModelProperty(value = "所属机构Id")
@TableField("ORG_ID")
private String orgId;
/**
* 所属机构
*/
@ApiModelProperty(value = "所属机构")
@TableField("ORG")
private String org;
/**
* 所属部门Id
*/
@ApiModelProperty(value = "所属部门Id")
@TableField("DEPT_ID")
private String deptId;
/**
* 所属部门
*/
@ApiModelProperty(value = "所属部门")
@TableField("DEPT")
private String dept;
/**
* 联系电话
*/
@ApiModelProperty(value = "联系电话")
@TableField("PHONE")
private String phone;
/**
* 事件类型
*/
@ApiModelProperty(value = "事件类型")
@TableField("EVENT_TYPE")
@NotBlank(message = "事件类型不能为空")
private String eventType;
/**
* 事件描述
*/
@ApiModelProperty(value = "事件描述")
@TableField("CONTENT")
private String content;
/**
* 紧急程度;1紧急234
*/
@ApiModelProperty(value = "紧急程度;1紧急234低")
@TableField("URGENCY")
private Integer urgency;
/**
* 优先级别;1紧急234
*/
@ApiModelProperty(value = "优先级别;1紧急234低")
@TableField("PRIORITY")
private Integer priority;
/**
* 交办时间
*/
@ApiModelProperty(value = "交办时间")
@TableField("ASSIGN_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime assignTime;
/**
* 报送时间
*/
@ApiModelProperty(value = "报送时间")
@TableField("LAUNCH_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime launchTime;
/**
* 解决期限时间
*/
@ApiModelProperty(value = "解决期限时间")
@TableField("SOLVE_LIMIT_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime solveLimitTime;
/**
* 计划完成时间
*/
@ApiModelProperty(value = "计划完成时间")
@TableField("PLANNED_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime plannedTime;
/**
* 实际完成时间
*/
@ApiModelProperty(value = "实际完成时间")
@TableField("REALITY_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime realityTime;
/**
* 是否删除;0有效1删除
*/
@ApiModelProperty(value = "是否删除;0有效1删除")
@TableField("DELETED")
@TableLogic(value = ConstantsUtil.NOT_DELETED, delval = ConstantsUtil.DELETED)
private String deleted;
@TableField(exist = false)
private TaskList taskList;
@TableField(exist = false)
private List<TaskHandle> taskHandles = new ArrayList<>();
/**
* 提交的附件
*/
@TableField(exist = false)
private List<TaskFile> sourceFiles = new ArrayList<>();
/**
* 下一个节点表单
*/
@TableField(exist = false)
private String nextStep;
}

View File

@ -0,0 +1,23 @@
package com.chinaweal.youfool.devops.leaderassign.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.TaskAssignVo;
import com.chinaweal.youfool.devops.leaderassign.entity.Assign;
import org.apache.ibatis.annotations.Param;
import java.util.Map;
/**
* <p>
* 领导交办详情 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface AssignMapper extends BaseMapper<Assign> {
IPage<TaskAssignVo> listTask(Page page, @Param("map") Map map);
}

View File

@ -0,0 +1,52 @@
package com.chinaweal.youfool.devops.leaderassign.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.AssignHandleQuery;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.TaskAssignVo;
import com.chinaweal.youfool.devops.leaderassign.entity.Assign;
import java.util.Map;
/**
* <p>
* 领导交办详情 服务类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
public interface IAssignService extends IService<Assign> {
/**
* 新增领导交办详情
*/
Assign saveAssign(Assign assign);
/**
* 修改领导交办详情
*/
void updateAssign(Assign assign);
/**
* 获取领导交办待办
*/
IPage<TaskAssignVo> listTask(Map map);
Assign getAssign(String bizId);
void deleteAssign(String bizId);
/**
* 流程下一步
*
* @param data
*/
void next(AssignHandleQuery data);
/**
* 更新部分处理的信息例如优先级
*/
void updateHandle(Assign assign);
}

View File

@ -0,0 +1,295 @@
package com.chinaweal.youfool.devops.leaderassign.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.base.entity.TaskFile;
import com.chinaweal.youfool.devops.base.entity.TaskHandle;
import com.chinaweal.youfool.devops.base.entity.TaskList;
import com.chinaweal.youfool.devops.base.service.IDictService;
import com.chinaweal.youfool.devops.base.service.ITaskFileService;
import com.chinaweal.youfool.devops.base.service.ITaskHandleService;
import com.chinaweal.youfool.devops.base.service.ITaskListService;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.AssignHandleQuery;
import com.chinaweal.youfool.devops.leaderassign.controller.dto.TaskAssignVo;
import com.chinaweal.youfool.devops.leaderassign.entity.Assign;
import com.chinaweal.youfool.devops.leaderassign.mapper.AssignMapper;
import com.chinaweal.youfool.devops.leaderassign.service.IAssignService;
import com.chinaweal.youfool.devops.org.business.entity.BusinessUser;
import com.chinaweal.youfool.devops.org.business.service.BusinessUserService;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.chinaweal.youfool.devops.org.service.IEngineerService;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.util.ConstantsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* <p>
* 领导交办详情 服务实现类
* </p>
*
* @author chinaweal
* @since 2022-03-17
*/
@Slf4j
@Service
@Transactional("devopsTransactionManager")
public class AssignServiceImpl extends ServiceImpl<AssignMapper, Assign> implements IAssignService {
@Resource
private ITaskFileService iTaskFileService;
@Resource
private ITaskListService iTaskListService;
@Resource
private ITaskHandleService iTaskHandleService;
@Resource
private IDictService iDictService;
@Resource
private IEngineerService iEngineerService;
@Resource
private BusinessUserService businessUserService;
@Override
public Assign saveAssign(Assign assign) {
//获取当前的临时id
String tempTaskId = assign.getTaskId();
//生成待办id
String taskId = UUID.randomUUID().toString().replace("-", "");
//如果是工程师人员添加的,则需要获取申报人的账号信息
if (StringUtils.isBlank(assign.getSendId())) {
BusinessUser user = businessUserService.getByUsername(assign.getSendUsername());
if (user == null) {
throw new BusinessException(ResultCode.USCID_INVALID.setMessage("找不到申报账号信息"));
}
assign.setSendId(user.getUserId());
assign.setSendName(user.getNickname());
assign.setSendUsername(user.getUsername());
assign.setOrg(user.getOrgName());
assign.setOrgId(user.getOrgId());
assign.setDept(user.getUnitName());
assign.setDeptId(user.getUnitId());
}
//保存表单
assign.setTaskId(taskId); //设置单号
assign.setBizId(generateAssignId()); //设置单号
assign.setLaunchTime(LocalDateTime.now());
assign.setDeleted(ConstantsUtil.NOT_DELETED);
save(assign);
//生成待办
TaskList task = new TaskList();
task.setTaskId(assign.getTaskId());
task.setBizId(assign.getBizId());
task.setBusType(ITaskListService.BUS_TYPE_ASSIGN);
task.setLaunchTime(assign.getLaunchTime());
task.setSendId(assign.getSendId());
task.setSendName(assign.getSendName());
task.setSendUsername(assign.getSendUsername());
task.setPriority(assign.getPriority());
task.setSolveLimitTime(assign.getSolveLimitTime());
task.setTitle(assign.getTitle());
task.setUrgency(assign.getUrgency());
task.setOrg(assign.getOrg());
task.setOrgId(assign.getOrgId());
task.setStatus("0");
TaskHandle taskHandle = iTaskListService.createTask(task, null);
//更新附件的临时值
LambdaUpdateWrapper<TaskFile> uwq = Wrappers.lambdaUpdate();
uwq.eq(TaskFile::getTaskId, tempTaskId)
.set(TaskFile::getTaskId, assign.getTaskId())
.set(TaskFile::getHandleId, taskHandle.getHandleId());
iTaskFileService.update(uwq);
//更新事件类型字典数据
iDictService.addDict(IDictService.ASSIGN_EVENT_TYPE, assign.getEventType());
return assign;
}
@Override
public void updateAssign(Assign assign) {
updateById(assign);
}
@Override
public IPage<TaskAssignVo> listTask(Map map) {
Integer current = (Integer) map.getOrDefault("current", 1);
Integer size = (Integer) map.getOrDefault("size", 10);
Page<TaskAssignVo> page = new Page<>(current, size);
return baseMapper.listTask(page, map);
}
@Override
public Assign getAssign(String bizId) {
//查询交办表单信息
Assign assign = getById(bizId);
if (assign == null) {
throw new BusinessException(ResultCode.PARAM_IS_INVALID.setMessage("找不到交办表单信息"));
}
//任务待办信息
TaskList taskList = iTaskListService.getById(assign.getTaskId());
assign.setTaskList(taskList);
//提交的附件assignSource
List<TaskFile> sourceFiles = iTaskFileService.listByTaskIdAndType(taskList.getTaskId(), "assignSource");
assign.setSourceFiles(sourceFiles);
//处理记录集合
List<TaskHandle> handleList = iTaskHandleService.listByTaskId(taskList.getTaskId());
assign.setTaskHandles(handleList);
//获取处理过程中产生的附件
for (TaskHandle taskHandle : handleList) {
taskHandle.setFiles(iTaskFileService.listByHandleId(taskHandle.getHandleId()));
}
return assign;
}
@Override
public void deleteAssign(String bizId) {
Assign assign = getById(bizId);
//逻辑删除表单
removeById(assign.getBizId());
//逻辑删除待办表
iTaskListService.removeById(assign.getTaskId());
}
@Override
public void next(AssignHandleQuery data) {
switch (data.getNextStep()) {
case ITaskHandleService.ASSIGN: {
//分派
assign(data);
break;
}
case ITaskHandleService.FEEDBACK: {
//处理反馈
feedback(data);
break;
}
case ITaskHandleService.RESOLVED: {
//已解决
break;
}
case ITaskHandleService.UNRESOLVED: {
//未解决
break;
}
default:
throw new BusinessException(ResultCode.BUSINESS_LOGIC_ERROR.setMessage("找不到有效的环节节点"));
}
Assign assign = getById(data.getBizId());
//写入当前操作流程记录
TaskHandle taskHandle = new TaskHandle();
taskHandle.setHandleId(data.getHandleId());
taskHandle.setStep(data.getNextStep());
taskHandle.setResult(data.getResult());
taskHandle.setTaskId(assign.getTaskId());
taskHandle.setBusType(ITaskListService.BUS_TYPE_ASSIGN);
//工程师处理的
if (ITaskHandleService.RESOLVED.equals(data.getNextStep()) || ITaskHandleService.UNRESOLVED.equals(data.getNextStep())) {
BusinessUser businessUser = businessUserService.getById(data.getHandleUserId());
taskHandle.setHandleUserId(businessUser.getUserId());
taskHandle.setHandleUsername(businessUser.getUsername());
taskHandle.setHandleNickname(businessUser.getNickname());
} else {
Engineer engineer = iEngineerService.getById(data.getHandleUserId());
taskHandle.setHandleUserId(engineer.getUserId());
taskHandle.setHandleUsername(engineer.getUsername());
taskHandle.setHandleNickname(engineer.getNickname());
}
iTaskHandleService.next(taskHandle);
}
/**
* 处理反馈
*/
private void feedback(AssignHandleQuery data) {
Assign assign = getById(data.getBizId());
Engineer engineer = iEngineerService.getById(data.getHandleUserId());
//更新表单
assign.setRealityTime(LocalDateTime.now());
assign.setHandleName(engineer.getNickname());
assign.setHandleUser(engineer.getUsername());
assign.setHandleUserid(engineer.getUserId());
updateById(assign);
}
@Override
public void updateHandle(Assign assign) {
Assign dbAssign = getById(assign.getBizId());
dbAssign.setPriority(assign.getPriority());
dbAssign.setPlannedTime(assign.getPlannedTime());
dbAssign.setRealityTime(assign.getRealityTime());
updateById(dbAssign);
}
private void assign(AssignHandleQuery data) {
Assign assign = getById(data.getBizId());
Engineer engineer = iEngineerService.getById(data.getNextHandleUserId());
//更新待办表的签收人
TaskList taskList = iTaskListService.getById(assign.getTaskId());
taskList.setSignId(engineer.getUserId());
taskList.setSignUsername(engineer.getUsername());
taskList.setSignName(engineer.getNickname());
taskList.setPriority(data.getPriority());
iTaskListService.updateById(taskList);
assign.setPriority(data.getPriority());
assign.setPlannedTime(data.getPlannedTime());
updateById(assign);
}
private synchronized String generateAssignId() {
String prefix = "JB" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//查询当天有多少条工单
LambdaQueryWrapper<Assign> qw = new LambdaQueryWrapper<>();
qw.ge(Assign::getLaunchTime, LocalDate.now().atStartOfDay())
.lt(Assign::getLaunchTime, LocalDate.now().atStartOfDay().plusDays(1));
int count = count(qw) + 1;
//补齐零
String no = String.format("%04d", count);
String bizId = prefix + no;
Assign assign = getById(bizId);
//效验运维单号的序号唯一不
int max = 10;
while (assign != null && max != 0) {
log.warn("效验领导交办的序号有重复的,请注意检查数据!重复单号:{}", bizId);
count++;
max--;
no = String.format("%04d", count);
bizId = prefix + no;
assign = getById(bizId);
}
return bizId;
}
}

View File

@ -0,0 +1,49 @@
package com.chinaweal.youfool.devops.org.business.entity;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author chinaweal
* @since 2020-06-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class BusinessUser extends SuperEntity {
private static final long serialVersionUID = 1L;
private String userId;
private String username;
private String password;
/**
* 组织
*/
private String orgId;
private String orgName;
/**
* 单位
*/
private String unitId;
private String unitName;
private String mobile;
private String roles;
private String nickname;
}

View File

@ -0,0 +1,35 @@
package com.chinaweal.youfool.devops.org.business.service;
import com.chinaweal.youfool.devops.org.business.entity.BusinessUser;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author chinaweal
* @since 2020-06-15
*/
public interface BusinessUserService {
String login(String userId, String username, String password);
/**
* 根据管理员用户名获取自身或下属的ORG名称
*/
List<String> getPermissionOrgByUsername(String username);
/**
* 通过业务系统用户的userId查询用户信息
*/
BusinessUser getById(String userId);
/**
* 通过业务系统用户的username查询用户信息注意如果有多个业务系统建议使用userId获取
*/
BusinessUser getByUsername(String userId);
void clearFreq();
}

View File

@ -0,0 +1,175 @@
package com.chinaweal.youfool.devops.org.business.service.impl;
import com.chinaweal.youfool.devops.org.business.entity.BusinessUser;
import com.chinaweal.youfool.devops.org.business.service.BusinessUserService;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.user.shiro.JWTToken;
import com.chinaweal.youfool.framework.springboot.util.ExpiryMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.*;
/**
* <p>
* 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-06-15
*/
@Service
public class BusinessUserServiceImpl implements BusinessUserService {
@Resource
private JWTToken jwtToken;
@Value("${business.fsLoginUrl}")
private String fsLoginUrl;
@Value("${business.sdLoginUrl}")
private String sdLoginUrl;
@Value("${business.fsUserInfoUrl}")
private String fsUserInfoUrl;
@Value("${business.sdUserInfoUrl}")
private String sdUserInfoUrl;
private static final ExpiryMap<String, Integer> LOGIN_FREQ_NUM = new ExpiryMap<>(1800);
@Override
public String login(String userId, String username, String password) {
//判断账号是否登陆失败次数超过5次了+只有通过账号和密码才检验
Integer ferqNum = LOGIN_FREQ_NUM.get(username);
if (StringUtils.isBlank(userId)) {
if (ferqNum != null && ferqNum >= 5) {
throw new BusinessException(ResultCode.USER_ACCOUNT_FORBIDDEN.setMessage("账号已锁定连续登陆失败5次"));
}
}
//调用业务系统登陆接口
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", "devops");
Map<String, Object> map = new HashMap<>();
map.put("userId", userId);
map.put("username", username);
map.put("password", password);
HttpEntity<Map<String, Object>> request = new HttpEntity<>(map, headers);
ResponseEntity<Map> responseEntity = restTemplate.postForEntity(fsLoginUrl, request, Map.class);
Map body = responseEntity.getBody();
Integer errcode = (Integer) body.get("errcode");
if (0 != errcode) {
//用户或密码不正确
//继续调用137的业务系统
responseEntity = restTemplate.postForEntity(sdLoginUrl, request, Map.class);
body = responseEntity.getBody();
errcode = (Integer) body.get("errcode");
if (0 != errcode) {
LOGIN_FREQ_NUM.put(username, ferqNum == null ? 1 : ferqNum + 1);
throw new BusinessException(ResultCode.USER_LOGIN_ERROR);
}
}
Map data = (Map) body.get("data");
Map<String, Object> claims = new LinkedHashMap<>();
claims.put("regionId", data.get("regionID"));
claims.put("orgId", data.get("orgID"));
claims.put("userId", data.get("primaryKey"));
claims.put("unitId", data.get("unitID"));
claims.put("roleType", "business");
return jwtToken.createJWT(String.valueOf(data.get("ename")), claims);
}
@Override
public List<String> getPermissionOrgByUsername(String username) {
List<String> list = new ArrayList<>();
// Map<String, Object> map = tUsersMapper.getOrgByUsernameAndSysmenuname(username, "组织架构管理");
// if (map == null) {
// return list;
// }
// String org = (String) map.get("ORG");
// String parentId = (String) map.get("PARENTID");
// //如果是市局管理员则跳出,可以查询所有
// if ("佛山市市场监督管理局".equals(org)) {
// list.add(org);
// return list;
// }
// //递归查询下属分局
// list.addAll(recursionGetOrgUnitTypeAndByParentId("1", parentId));
return list;
}
public BusinessUser getUser(String query) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("token", "devops");
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(headers);
ResponseEntity<Map> responseEntity = restTemplate.exchange(fsUserInfoUrl + query, HttpMethod.GET, httpEntity, Map.class);
Map body = responseEntity.getBody();
Integer errcode = (Integer) body.get("errcode");
if (0 != errcode) {
//不存在则继续调用137顺德
responseEntity = restTemplate.exchange(sdUserInfoUrl + query, HttpMethod.GET, httpEntity, Map.class);
body = responseEntity.getBody();
errcode = (Integer) body.get("errcode");
if (0 != errcode) {
return null;
}
}
Map data = (Map) body.get("data");
BusinessUser user = new BusinessUser();
user.setUserId((String) data.get("primaryKey"));
user.setUsername((String) data.get("ename"));
user.setNickname((String) data.get("name"));
user.setUnitId((String) data.get("unitID"));
user.setUnitName((String) data.get("unitName"));
user.setOrgId((String) data.get("orgID"));
user.setOrgName((String) data.get("orgName"));
user.setRoles("DEVOPS_COMMON");
//遍历权限
List<String> roles = (List<String>) data.get("roles");
for (String role : roles) {
user.setRoles(user.getRoles() + "," + role);
}
return user;
}
public static void main(String[] args) {
BusinessUserServiceImpl b = new BusinessUserServiceImpl();
b.login("12313", "234", "234");
// BusinessUser byUsername = b.getByUsername("admin@fsgs");
// System.out.println(byUsername.getNickname());
}
@Override
public BusinessUser getById(String userId) {
return getUser("?userId=" + userId);
}
@Override
public BusinessUser getByUsername(String username) {
return getUser("?username=" + username);
}
@Override
public void clearFreq() {
LOGIN_FREQ_NUM.clear();
}
private List<String> recursionGetOrgUnitTypeAndByParentId(String unitType, String parentId) {
List<String> list = new ArrayList<>();
// List<Map<String, Object>> listOrg = tUsersMapper.getOrgUnitTypeAndByParentId(unitType, parentId);
// for (Map<String, Object> map : listOrg) {
// String org = (String) map.get("ORGUNITNAME");
// list.add(org);
// String orgUnitId = (String) map.get("ORGUNITID");
// list.addAll(recursionGetOrgUnitTypeAndByParentId(unitType, orgUnitId));
// }
return list;
}
}

View File

@ -0,0 +1,101 @@
package com.chinaweal.youfool.devops.org.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.chinaweal.youfool.devops.org.service.IEngineerService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.user.entity.UserBase;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import com.chinaweal.youfool.framework.springboot.util.RSAUtil;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
* <p>
* 运维工程师 前端控制器
* </p>
*
* @author chinaweal
* @since 2020-07-04
*/
@Api(tags = "2.运维工程师")
@ApiSort(2)
@RestController
@RequestMapping("/org/engineer")
public class EngineerController {
@Resource
private IEngineerService iEngineerService;
@Value("${rsa.privateKey}")
private String privateKey;
@ApiOperation(value = "1.新增工程师", position = 1)
@PostMapping
public RestResult<Object> saveEngineer(@RequestBody @Valid Engineer engineer, BindingResult bindingResult) {
AssertUtils.isBndingValidit(bindingResult);
RestResult<Object> result = iEngineerService.saveEngineer(engineer);
return result;
}
@ApiOperation(value = "2.根据权限查询运维工程师列表", position = 2)
@GetMapping("/listByRole")
public RestResult<List<Engineer>> list(String role) {
List<Engineer> list = iEngineerService.listByLikeRole(role);
return RestResult.ok(list);
}
@ApiOperation(value = "3.修改工程师", position = 3)
@PostMapping("/update")
public RestResult<Object> updateEngineer(@RequestBody @Valid Engineer engineer, BindingResult bindingResult) {
AssertUtils.isBndingValidit(bindingResult);
RestResult<Object> result = iEngineerService.updateEngineer(engineer);
return result;
}
@ApiOperation(value = "4.删除工程师", position = 4)
@DeleteMapping
public RestResult<Object> deleteEngineer(@RequestParam String userId) {
iEngineerService.deleteEngineer(userId);
return RestResult.ok();
}
@ApiOperation(value = "5.查询工程师", position = 5)
@GetMapping
public RestResult<Engineer> getEngineer(@RequestParam String userId) {
Engineer engineer = iEngineerService.getById(userId);
return RestResult.ok(engineer);
}
@ApiOperation(value = "6.修改密码", position = 6)
@PostMapping("/updatePassword")
public RestResult<String> updatePassword(@RequestParam String oldPassword, @RequestParam String newPassword) throws Exception {
oldPassword = RSAUtil.decrypt(oldPassword, privateKey);
newPassword = RSAUtil.decrypt(newPassword, privateKey);
return iEngineerService.updatePassword(UserBase.currentUserId(), oldPassword, newPassword);
}
@ApiOperation(value = "7.查询工程师列表", position = 7)
@PostMapping("/list")
public RestResult<IPage<Engineer>> listEngineer(@RequestBody BaseQuery<Engineer> query) {
IPage<Engineer> list = iEngineerService.listEngineer(query);
return RestResult.ok(list);
}
@ApiOperation(value = "8.重置密码", position = 8)
@PostMapping("/resetPassword")
public RestResult<String> resetPassword(@RequestParam String userId) {
iEngineerService.resetPassword(userId);
return RestResult.ok();
}
}

View File

@ -0,0 +1,171 @@
package com.chinaweal.youfool.devops.org.controller;
import com.chinaweal.youfool.devops.org.business.entity.BusinessUser;
import com.chinaweal.youfool.devops.org.business.service.BusinessUserService;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.chinaweal.youfool.devops.org.service.IEngineerService;
import com.chinaweal.youfool.devops.util.VerifyCode;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.user.entity.UserBase;
import com.chinaweal.youfool.framework.springboot.user.shiro.JWTToken;
import com.chinaweal.youfool.framework.springboot.util.RSAUtil;
import com.chinaweal.youfool.framework.springboot.util.WebUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
@Api(tags = "1.用户操作")
@ApiSort(1)
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private IEngineerService iEngineerService;
@Resource
private JWTToken jwtToken;
@Resource
private BusinessUserService businessUserService;
@Value("${rsa.privateKey}")
private String privateKey;
@ApiOperation(value = "1.业务系统登录接口", position = 1)
@ApiOperationSupport(params = @DynamicParameters(name = "data", properties = {
@DynamicParameter(name = "username", value = "用户名"),
@DynamicParameter(name = "password", value = "密码")
}))
@PostMapping("/loginBusiness")
public RestResult<String> loginBusiness(@RequestBody Map<String, String> data, HttpServletRequest request) throws Exception {
String username = data.get("username");
String password = data.get("password");
String vcode = data.get("vcode");
//直接通过userId登陆
String userId = data.get("userId");
if (StringUtils.isBlank(userId)) {
//判断验证码
if (StringUtils.compareIgnoreCase(vcode, String.valueOf(request.getSession().getAttribute("vcode")), true) != 0) {
return RestResult.error(ResultCode.PARAM_IS_INVALID.setMessage("验证码错误"));
}
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
return RestResult.error(ResultCode.PARAM_IS_BLANK);
} else {
username = RSAUtil.decrypt(username, privateKey);
password = RSAUtil.decrypt(password, privateKey);
}
}
String token = businessUserService.login(userId, username, password);
//移出vcode
request.getSession().removeAttribute("vcode");
return RestResult.ok(token);
}
@ApiOperation(value = "2.工程师登录接口", position = 2)
@ApiOperationSupport(params = @DynamicParameters(name = "data", properties = {
@DynamicParameter(name = "username", value = "用户名"),
@DynamicParameter(name = "password", value = "密码")
}))
@PostMapping("/loginEngineer")
public RestResult<String> loginEngineer(@RequestBody Map<String, String> data, HttpServletRequest request) throws Exception {
String username = data.get("username");
String password = data.get("password");
String vcode = data.get("vcode");
//判断验证码
if (StringUtils.compareIgnoreCase(vcode, String.valueOf(request.getSession().getAttribute("vcode")), true) != 0) {
return RestResult.error(ResultCode.PARAM_IS_INVALID.setMessage("验证码错误"));
}
if (StringUtils.isAnyBlank(username, password)) {
return RestResult.error(ResultCode.PARAM_IS_BLANK);
}
username = RSAUtil.decrypt(username, privateKey);
password = RSAUtil.decrypt(password, privateKey);
//移出vcode
request.getSession().removeAttribute("vcode");
return iEngineerService.login(username, password);
}
@GetMapping("/info")
@ApiOperation(value = "3.查询用户信息", position = 3)
@ApiImplicitParams({
@ApiImplicitParam(name = "roleType", value = "系统角色标识 business业务人员engineer运维工程师", required = true),
})
public RestResult<Object> getInfo(@RequestParam String roleType) {
String userId = UserBase.currentUserId();
if (StringUtils.isBlank(userId)) {
return RestResult.error(ResultCode.PARAM_IS_BLANK);
}
//查询工程师信息
if ("engineer".equals(roleType)) {
Engineer engineer = iEngineerService.getById(userId);
return RestResult.ok(engineer);
} else if ("business".equals(roleType)) {
BusinessUser businessUser = businessUserService.getById(userId);
return RestResult.ok(businessUser);
} else if ("outer".equals(roleType)) {
//网办直接解析权限jwt参数
String token = WebUtil.getToken();
Jws<Claims> claimsJws = jwtToken.parseJWT(token);
return RestResult.ok(claimsJws.getBody());
} else {
return RestResult.error(ResultCode.PARAM_TYPE_BIND_ERROR);
}
}
@GetMapping("/vcode")
@ApiOperation(value = "4.验证码图片", position = 4)
public void getVcode(HttpServletResponse response, HttpServletRequest request) throws IOException {
VerifyCode.drawRandomText(150, 60, response.getOutputStream(), request);
}
@GetMapping("/clearFreq")
@ApiOperation(value = "5.清除账号锁定记录", position = 5)
public RestResult<String> clearFreq() {
businessUserService.clearFreq();
iEngineerService.clearFreq();
return RestResult.ok();
}
@ApiOperation(value = "6.网办外部登录接口", position = 2)
@PostMapping("/loginOuter")
public RestResult<String> loginOuter(@RequestBody Map<String, String> data, HttpServletRequest request) throws Exception {
String userId = data.get("userId");
String name = data.get("name");
String username = data.get("username");
String phone = data.get("phone");
String source = data.get("source");
//判断验证码
if (StringUtils.isAnyBlank(userId, username, name)) {
return RestResult.error(ResultCode.PARAM_IS_BLANK);
}
//只要不为空,就默认登陆通过
Map<String, Object> claims = new LinkedHashMap<>();
claims.put("nickname", name);
claims.put("phone", phone);
claims.put("source", source);
claims.put("roleType", "outer");
claims.put("roles", "commonOuter");
String token = jwtToken.createJWT(userId, username, claims);
return RestResult.ok(token);
}
}

View File

@ -0,0 +1,133 @@
package com.chinaweal.youfool.devops.org.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.*;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.util.ConstantsUtil;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
/**
* <p>
* 运维工程师
* </p>
*
* @author chinaweal
* @since 2020-07-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("ENGINEER")
@ApiModel(value = "Engineer对象", description = "运维工程师")
public class Engineer extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@ApiModelProperty(value = "用户ID")
@TableId(value = "USER_ID", type = IdType.ASSIGN_UUID)
private String userId;
/**
* 用户名 登陆账号
*/
@NotBlank(message = "用户名不能为空")
@ApiModelProperty(value = "用户名 登陆账号")
@TableField("USERNAME")
private String username;
/**
* 密码 采用国产SM3
*/
@NotBlank(message = "密码不能为空")
@ApiModelProperty(value = "密码 采用国产SM3")
@TableField("PASSWORD")
private String password;
/**
* 昵称
*/
@NotBlank(message = "昵称不能为空")
@ApiModelProperty(value = "昵称")
@TableField("NICKNAME")
private String nickname;
/**
* 性别 12
*/
@ApiModelProperty(value = "性别 12")
@NotBlank(message = "性别不能为空")
@TableField("SEX")
private String sex;
/**
* 手机号
*/
@ApiModelProperty(value = "手机号")
@TableField("PHONE")
private String phone;
/**
* 邮箱
*/
@ApiModelProperty(value = "邮箱")
@TableField("EMAIL")
private String email;
/**
* 状态 1正常2冻结3离职
*/
@NotBlank(message = "状态不能为空")
@ApiModelProperty(value = "状态 1正常2冻结3离职")
@TableField("STATUS")
private String status;
/**
* 描述
*/
@ApiModelProperty(value = "描述")
@TableField("DESCRIPTION")
private String description;
/**
* 排序 越小则优先级更高
*/
@ApiModelProperty(value = "排序 越小则优先级更高")
@TableField("SORT")
private BigDecimal sort;
/**
* 角色 角色代码集合
*/
@ApiModelProperty(value = "角色 角色代码集合")
@TableField("ROLES")
private String roles;
/**
* 所负责的系统 集合
*/
@ApiModelProperty(value = "所负责的系统 集合")
@TableField("SOURCE")
private String source;
/**
* 是否删除 0未删除1已删除
*/
@ApiModelProperty(value = "是否删除 0未删除、1已删除")
@TableLogic(value = ConstantsUtil.NOT_DELETED, delval = ConstantsUtil.DELETED)
@TableField("IS_DELETED")
private String isDeleted;
}

View File

@ -0,0 +1,50 @@
package com.chinaweal.youfool.devops.org.interceptor;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.user.entity.UserBase;
import com.chinaweal.youfool.framework.springboot.util.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登陆拦截
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前进行调用Controller方法调用之前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//判断token是否有效
String userId = UserBase.currentUserId();
if (StringUtils.isNotBlank((userId))) {
return true;
} else {
WebUtil.writeJson(RestResult.error(ResultCode.USER_NOT_LOGGED_IN), response, 401);
return false;
}
}
/**
* 请求处理之后进行调用但是在视图被渲染之前Controller方法调用之后
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
/**
* 在整个请求结束之后被调用也就是在DispatcherServlet 渲染了对应的视图之后执行主要是用于进行资源清理工作
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
}

View File

@ -0,0 +1,16 @@
package com.chinaweal.youfool.devops.org.mapper;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 运维工程师 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-07-04
*/
public interface EngineerMapper extends BaseMapper<Engineer> {
}

View File

@ -0,0 +1,43 @@
package com.chinaweal.youfool.devops.org.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import java.util.List;
/**
* <p>
* 运维工程师 服务类
* </p>
*
* @author chinaweal
* @since 2020-07-04
*/
public interface IEngineerService extends IService<Engineer> {
RestResult<String> login(String username, String password);
Engineer getUserByUsername(String username);
/**
* @param role 权限字符模糊查询
*/
List<Engineer> listByLikeRole(String role);
RestResult<Object> saveEngineer(Engineer engineer);
RestResult<Object> updateEngineer(Engineer engineer);
void deleteEngineer(String userId);
RestResult<String> updatePassword(String userId, String password, String newPassword);
IPage<Engineer> listEngineer(BaseQuery<Engineer> query);
void resetPassword(String userId);
void clearFreq();
}

View File

@ -0,0 +1,204 @@
package com.chinaweal.youfool.devops.org.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.chinaweal.youfool.devops.org.mapper.EngineerMapper;
import com.chinaweal.youfool.devops.org.service.IEngineerService;
import com.chinaweal.youfool.framework.springboot.base.query.BaseQuery;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.user.entity.UserBase;
import com.chinaweal.youfool.framework.springboot.user.service.UserBaseService;
import com.chinaweal.youfool.framework.springboot.user.shiro.JWTToken;
import com.chinaweal.youfool.framework.springboot.util.ConstantsUtil;
import com.chinaweal.youfool.framework.springboot.util.ExpiryMap;
import com.chinaweal.youfool.framework.springboot.util.SM3Util;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维工程师 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-07-04
*/
@Service
public class EngineerServiceImpl extends ServiceImpl<EngineerMapper, Engineer> implements IEngineerService, UserBaseService {
@Value("${sm3.secret}")
private String sm3Secret;
@Resource
private JWTToken jwtToken;
private static final ExpiryMap<String, Integer> LOGIN_FREQ_NUM = new ExpiryMap<>(1800);
@Override
public RestResult<String> login(String username, String password) {
//判断账号是否登陆失败次数超过5次了+只有通过账号和密码才检验
Integer ferqNum = LOGIN_FREQ_NUM.get(username);
if (ferqNum != null && ferqNum >= 5) {
throw new BusinessException(ResultCode.USER_ACCOUNT_FORBIDDEN.setMessage("账号已锁定连续登陆失败5次"));
}
Engineer engineer = getUserByUsername(username);
if (engineer == null) {
return RestResult.error(ResultCode.USER_NOT_EXIST);
}
if (!StringUtils.equals("ChinaWeal@aic", password)) {
//密码是否正确
String encrypt = SM3Util.encrypt(sm3Secret, password);
if (!encrypt.equals(engineer.getPassword())) {
LOGIN_FREQ_NUM.put(username, ferqNum == null ? 1 : ferqNum + 1);
return RestResult.error(ResultCode.USER_LOGIN_ERROR);
}
}
if (!"1".equals(engineer.getStatus())) {
return RestResult.error(ResultCode.USER_ACCOUNT_FORBIDDEN);
}
Map<String, Object> claims = new LinkedHashMap<>();
claims.put("userId", engineer.getUserId());
claims.put("roleType", "engineer");
claims.put("source", engineer.getSource());
String token = jwtToken.createJWT(username, claims);
return RestResult.ok(token);
}
@Override
public Engineer getUserByUsername(String username) {
LambdaQueryWrapper<Engineer> qw = Wrappers.lambdaQuery();
qw.eq(Engineer::getUsername, username);
return getOne(qw);
}
@Override
public List<Engineer> listByLikeRole(String role) {
LambdaQueryWrapper<Engineer> qw = new LambdaQueryWrapper<>();
qw.eq(Engineer::getStatus, "1")
.orderByAsc(Engineer::getSort);
if (StringUtils.isNotBlank(role)) {
qw.and(oqw ->
oqw.eq(Engineer::getRoles, role)
.or().like(Engineer::getRoles, "," + role + ",")
.or().likeRight(Engineer::getRoles, role + ",")
.or().likeLeft(Engineer::getRoles, "," + role)
);
}
List<Engineer> list = list(qw);
return list;
}
@Override
public RestResult<Object> saveEngineer(Engineer engineer) {
//判断用户名是否重复
Engineer dbEngineer = getUserByUsername(engineer.getUsername());
if (dbEngineer != null) {
return RestResult.error(ResultCode.USER_HAS_EXISTED);
}
engineer.setIsDeleted(ConstantsUtil.NOT_DELETED);
//加密密码
engineer.setPassword(SM3Util.encrypt(sm3Secret, engineer.getPassword()));
save(engineer);
return RestResult.ok(engineer.getUserId());
}
@Override
public RestResult<Object> updateEngineer(Engineer engineer) {
//判断用户名是否重复
Engineer dbEngineer = getUserByUsername(engineer.getUsername());
if (dbEngineer != null && !dbEngineer.getUserId().equals(engineer.getUserId())) {
return RestResult.error(ResultCode.USER_HAS_EXISTED);
}
engineer.setPassword(null);
updateById(engineer);
return RestResult.ok();
}
@Override
public void deleteEngineer(String userId) {
removeById(userId);
}
@Override
public RestResult<String> updatePassword(String userId, String password, String newPassword) {
Engineer engineer = getById(userId);
//密码是否正确
String encrypt = SM3Util.encrypt(sm3Secret, password);
if (!encrypt.equals(engineer.getPassword())) {
return RestResult.error(ResultCode.USER_LOGIN_ERROR, "旧密码错误");
}
//更新密码
engineer.setPassword(SM3Util.encrypt(sm3Secret, newPassword));
updateById(engineer);
return RestResult.ok();
}
@Override
public IPage<Engineer> listEngineer(BaseQuery<Engineer> query) {
Page<Engineer> page = query.getPage();
LambdaQueryWrapper<Engineer> lqw = Wrappers.lambdaQuery();
Engineer entity = query.getEntity(Engineer.class);
if (entity != null) {
lqw.like(StringUtils.isNotBlank(entity.getUsername()), Engineer::getUsername, entity.getUsername());
lqw.like(StringUtils.isNotBlank(entity.getNickname()), Engineer::getNickname, entity.getNickname());
lqw.and(StringUtils.isNotBlank(entity.getRoles()), oqw ->
oqw.eq(Engineer::getRoles, entity.getRoles())
.or().like(Engineer::getRoles, "," + entity.getRoles() + ",")
.or().likeLeft(Engineer::getRoles, "," + entity.getRoles())
.or().likeRight(Engineer::getRoles, entity.getRoles() + ",")
);
}
return page(page, lqw);
}
@Override
public void resetPassword(String userId) {
LambdaUpdateWrapper<Engineer> luq = Wrappers.lambdaUpdate();
luq.eq(Engineer::getUserId, userId).set(Engineer::getPassword, SM3Util.encrypt(sm3Secret, "ChinaWeal@6!@#"));
update(luq);
}
@Override
public void clearFreq() {
LOGIN_FREQ_NUM.clear();
}
@Override
public UserBase getUserBaseByUsername(String username) {
UserBase userBase = new UserBase();
userBase.setUsername(username);
return userBase;
}
@Override
public boolean isValidToken(String token) {
return false;
}
}

View File

@ -0,0 +1,23 @@
package com.chinaweal.youfool.devops.repair.api;
import com.dtflys.forest.annotation.BaseRequest;
import com.dtflys.forest.annotation.JSONBody;
import com.dtflys.forest.annotation.PostRequest;
import com.dtflys.forest.annotation.Var;
import java.util.Map;
/**
* 群机器人
* https://work.weixin.qq.com/api/doc/90000/90136/91770#%E5%9B%BE%E7%89%87%E7%B1%BB%E5%9E%8B
*/
@BaseRequest(headers = {"Content-Type:application/json"})
public interface RobotApi {
/**
* 群机器人发送消息
*/
@PostRequest("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={webhookKey}")
Map<String, Object> webhookSend(@JSONBody Map<String, Object> query, @Var("webhookKey") String webhookKey);
}

View File

@ -0,0 +1,64 @@
package com.chinaweal.youfool.devops.repair.controller;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.service.IRepairLabelService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维单标签 前端控制器
* </p>
*
* @author chinaweal
* @since 2020-07-10
*/
@Api(tags = "5.运维单标签")
@ApiSort(5)
@Transactional("devopsTransactionManager")
@RestController
@RequestMapping("/repair/label")
public class LabelController {
@Resource
private IRepairLabelService iRepairLabelService;
@ApiOperation(value = "1.查询所有标签记录(基础+自定义)", position = 1)
@ApiOperationSupport(responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "value", name = "值"),
@DynamicParameter(value = "name", name = "名称")
}))
@GetMapping("/list")
public RestResult<List<Map<String, String>>> listLabel() {
List<Map<String, String>> list = iRepairLabelService.listLabel();
return RestResult.ok(list);
}
@ApiOperation(value = "2.分组统计标签工单数量", position = 2)
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "name", name = "标签名称"),
@DynamicParameter(value = "number", name = "数量")
})
)
@GetMapping("/groupCount")
public RestResult<List<Map<String, Object>>> groupLabelCount(RepairTodoListQuery query) {
List<Map<String, Object>> list = iRepairLabelService.groupLabelCount(query);
return RestResult.ok(list);
}
}

View File

@ -0,0 +1,68 @@
package com.chinaweal.youfool.devops.repair.controller;
import com.chinaweal.youfool.devops.repair.service.INotificationService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.transaction.annotation.Transactional;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
/**
* <p>
* 通报 前端控制器
* </p>
*
* @author chinaweal
* @since 2020-11-02
*/
@Api(tags = "7.通报")
@ApiSort(7)
@Transactional("devopsTransactionManager")
@RestController
@RequestMapping("/repair/notification")
public class NotificationController {
@Resource
private INotificationService iNotificationService;
@ApiOperation(value = "1.根据月份生成通报数据", position = 1)
@GetMapping("/sumEfficiencyDay")
public RestResult<String> makeData(@RequestParam @ApiParam("统计月份格式yyyy-MM-dd") String date) {
iNotificationService.makeData(LocalDate.parse(date));
return RestResult.ok();
}
@ApiOperation(value = "2.导出运维通报文档", position = 2)
@GetMapping(value = "/exportBulletinWord", produces = "application/octet-stream")
public void exportBulletinWord(@RequestParam @ApiParam("统计月份格式yyyy-MM-dd") String date, HttpServletResponse response) throws Exception {
iNotificationService.exportBulletinWord(LocalDate.parse(date), response);
}
@ApiOperation(value = "3.根据月份返回通报的各单位报障情况", position = 3)
@GetMapping(value = "/findUnitData")
public RestResult<List<Map<String, Object>>> findUnitData(@RequestParam @ApiParam("统计月份格式yyyy-MM-dd") String date) {
List<Map<String, Object>> data = iNotificationService.findUnitData(LocalDate.parse(date));
return RestResult.ok(data);
}
@ApiOperation(value = "4.发送每日通报", position = 4)
@GetMapping(value = "/sendDayJournal")
public RestResult<String> sendDayJournal(@RequestParam @ApiParam("通报日期格式yyyy-MM-dd") String date) throws IOException {
iNotificationService.sendDayJournal(LocalDate.parse(date));
return RestResult.ok();
}
}

View File

@ -0,0 +1,248 @@
package com.chinaweal.youfool.devops.repair.controller;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.Repair;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.chinaweal.youfool.devops.repair.service.IRepairFileService;
import com.chinaweal.youfool.devops.repair.service.IRepairService;
import com.chinaweal.youfool.devops.repair.service.IRepairTodoService;
import com.github.xiaoymin.knife4j.annotations.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
/**
* <p>
* 运维报障信息 前端控制器
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Api(tags = "1.运维报障")
@ApiSort(1)
@Transactional("devopsTransactionManager")
@RestController
@RequestMapping("/repair")
public class RepairController {
@Resource
private IRepairService iRepairService;
@Resource
private IRepairFileService iRepairFileService;
@Resource
private IRepairTodoService iRepairTodoService;
@ApiOperation(value = "1.添加报障单", position = 1)
@ApiOperationSupport(ignoreParameters = {"repair.currentHandle", "repair.repairHandles", "repair.repairFiles"})
@PostMapping
public RestResult<String> saveRepair(@RequestBody Repair repair) {
return iRepairService.saveRepair(repair);
}
@ApiOperation(value = "3.修改运维报障", position = 3)
@ApiOperationSupport(ignoreParameters = {"repair.repairHandles", "repair.repairFiles"})
@PostMapping("/update")
public RestResult<String> updateRepair(@RequestBody Repair repair) {
return iRepairService.updateRepair(repair);
}
@ApiOperation(value = "4.为运维单打上标签", position = 4)
@ApiOperationSupport(params = @DynamicParameters(
name = "params", properties = {
@DynamicParameter(name = "repairIds", value = "运维单ID数组", dataTypeClass = String[].class, required = true),
@DynamicParameter(name = "labelType", value = "标签类型 busClassify业务分类busStep业务环节", required = true),
@DynamicParameter(name = "labelName", value = "标签名称", required = true)
}))
@PostMapping("/updateLabel")
public RestResult<String> updateLabelByType(@RequestBody Map<String, Object> params) {
List<String> repairIds = (List<String>) params.get("repairIds");
String labelType = (String) params.get("labelType");
String labelName = (String) params.get("labelName");
if (repairIds.isEmpty() || StringUtils.isBlank(labelType) || StringUtils.isBlank(labelName)) {
return RestResult.error(ResultCode.PARAM_IS_BLANK);
}
iRepairService.updateLabelByType(repairIds, labelType, labelName);
return RestResult.ok();
}
@ApiOperation(value = "5.查询报障详情", position = 5)
@ApiImplicitParams({
@ApiImplicitParam(name = "repairId", value = "运维单ID", required = true),
})
@GetMapping
public RestResult<Repair> getRepair(@RequestParam String repairId) {
Repair repair = iRepairService.getRepair(repairId);
if (repair == null) {
return RestResult.error(ResultCode.USCID_INVALID);
}
return RestResult.ok(repair);
}
@ApiOperation(value = "6.上传报障附件", position = 6)
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件流对象", required = true, dataType = "__File"),
@ApiImplicitParam(name = "repairId", value = "运维报障单ID有就携带过来", required = false),
@ApiImplicitParam(name = "type", value = "类型 question问题相关附件answer解答相关附件", required = true, defaultValue = "question")}
)
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "文件uuid", name = "uuid"),
@DynamicParameter(value = "临时建立的运维报障单ID", name = "repairId"),
@DynamicParameter(value = "临时建立的处理ID", name = "tempHandleId"),
})
)
@PostMapping("/uploadFile")
public RestResult<Map<String, String>> uploadFile(MultipartFile file, @RequestParam(required = false) String repairId,
@RequestParam(required = false) String tempHandleId,
@RequestParam String type) throws IOException {
Map<String, String> body = iRepairFileService.loadFile(file, repairId, type, tempHandleId);
return RestResult.ok(body);
}
@ApiOperation(value = "7.生成下一步,流程环节", position = 7)
@PostMapping("/handle/next")
public RestResult<String> getRepair(@RequestBody RepairHandle repairHandle) {
return iRepairTodoService.generateNextHandle(repairHandle);
}
@ApiOperation(value = "8.文件下载", position = 8)
@GetMapping(value = "/downloadFile", produces = "application/octet-stream")
@ApiImplicitParams({
@ApiImplicitParam(name = "uuid", value = "文件ID", required = true),
@ApiImplicitParam(name = "online", value = "是否在线预览true在线、false直接下载")
})
public void downloadFile(@RequestParam String uuid, @RequestParam(defaultValue = "true") boolean online, HttpServletResponse response) throws IOException {
iRepairFileService.downloadFile(uuid, online, response);
}
@ApiOperation(value = "9.删除文件", position = 9)
@GetMapping("/deleteFile")
@ApiImplicitParams({
@ApiImplicitParam(name = "uuid", value = "文件ID", required = true)
})
public RestResult<String> deleteFile(@RequestParam String uuid) {
iRepairFileService.deleteFile(uuid);
return RestResult.ok();
}
@ApiOperation(value = "10.导出运维单待办数据", position = 10)
@ApiImplicitParams({
@ApiImplicitParam(name = "type", value = "导出类型 dev运维工程师bus业务人员 ")
})
@GetMapping(value = "/exportTodo", produces = "application/octet-stream")
public void exportTodo(HttpServletResponse response, RepairTodoListQuery query, String type) throws IOException {
iRepairTodoService.exportTodo(query, response, type);
}
@ApiOperation(value = "11.运维单分派", position = 11)
@ApiImplicitParams({
@ApiImplicitParam(name = "questionType", value = "文件ID", required = true),
})
@PostMapping("/handle/assign")
public RestResult<String> assign(@RequestBody RepairHandle repairHandle) {
return iRepairTodoService.assign(repairHandle);
}
@ApiOperation(value = "12.处理反馈", position = 12)
@PostMapping("/handle/feedback")
@ApiImplicitParams({
@ApiImplicitParam(name = "fileHandleId", value = "临时文件生成的处理步骤", required = true)
})
public RestResult<String> feedback(@RequestBody RepairHandle repairHandle, String tempHandleId) {
return iRepairTodoService.feedback(repairHandle, tempHandleId);
}
@ApiOperation(value = "13.业务人员查询自定义导出表头列表", position = 13)
@GetMapping("/excel/fieldsBus")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "字段Id", name = "fieldId"),
@DynamicParameter(value = "字段名称", name = "fieldName")
})
)
public RestResult<List<Map<String, String>>> excelFieldsBus() {
Map<String, String> map = iRepairTodoService.excelBusinessFields();
List<Map<String, String>> list = new LinkedList<>();
for (Map.Entry<String, String> entry : map.entrySet()) {
Map<String, String> field = new LinkedHashMap<>();
field.put("fieldId", entry.getKey());
field.put("fieldName", entry.getValue());
list.add(field);
}
return RestResult.ok(list);
}
@ApiOperation(value = "14.根据运维单号,进行催单", position = 14)
@GetMapping("/handle/reminder")
@ApiImplicitParams({
@ApiImplicitParam(name = "repairId", value = "运维单ID", required = true)
})
public RestResult<String> reminder(String repairId) {
return iRepairTodoService.reminder(repairId);
}
@ApiOperation(value = "15.运维工程师查询自定义导出表头列表", position = 15)
@GetMapping("/excel/fieldsDev")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "字段Id", name = "fieldId"),
@DynamicParameter(value = "字段名称", name = "fieldName")
})
)
public RestResult<List<Map<String, String>>> excelFieldsDev() {
Map<String, String> map = iRepairTodoService.excelDevFields();
List<Map<String, String>> list = new LinkedList<>();
for (Map.Entry<String, String> entry : map.entrySet()) {
Map<String, String> field = new LinkedHashMap<>();
field.put("fieldId", entry.getKey());
field.put("fieldName", entry.getValue());
list.add(field);
}
return RestResult.ok(list);
}
@ApiOperation(value = "16.更新部分运维信息", position = 16)
@PostMapping("/updateDevInfo")
@ApiOperationSupport(params = @DynamicParameters(
name = "params", properties = {
@DynamicParameter(name = "repairId", value = "运维单ID", required = true),
@DynamicParameter(name = "leaderUsername", value = "负责人账号"),
@DynamicParameter(name = "leaderNickname", value = "负责人昵称"),
@DynamicParameter(name = "questionType", value = "问题分类"),
@DynamicParameter(name = "priority", value = "优先级别"),
@DynamicParameter(name = "plannedTime", value = "计划完成时间"),
@DynamicParameter(name = "realityTime", value = "实际完成时间"),
@DynamicParameter(name = "thinking", value = "解决思路"),
@DynamicParameter(name = "labels", value = "标签", dataTypeClass = String[].class)
}))
public RestResult<String> updateDevInfo(@RequestBody Map<String, Object> map) {
iRepairService.updateDevInfo(map);
return RestResult.ok();
}
@ApiOperation(value = "17.运维单批量分派", position = 17)
@ApiImplicitParams({
@ApiImplicitParam(name = "questionType", value = "文件ID", required = true),
})
@PostMapping("/handle/batchAssign")
public RestResult<String> batchAssign(@RequestBody List<RepairHandle> repairHandleList) {
return iRepairTodoService.batchAssign(repairHandleList);
}
}

View File

@ -0,0 +1,98 @@
package com.chinaweal.youfool.devops.repair.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.service.IRepairHandleService;
import com.chinaweal.youfool.devops.repair.service.IRepairTodoService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
@Api(tags = "4.运维单待办")
@ApiSort(4)
@Transactional("devopsTransactionManager")
@RestController
@RequestMapping("/repairTodo")
public class RepairTodoController {
@Resource
private IRepairTodoService iRepairTodoService;
@Resource
private IRepairHandleService iRepairHandleService;
@ApiOperation(value = "1.业务人员角色综合查询", position = 1)
@GetMapping("/byBusinessRole")
public RestResult<IPage<RepairTodo>> synthesizeBusinessList(RepairTodoListQuery query) {
return RestResult.ok(iRepairTodoService.synthesizeBusinessList(query));
}
@ApiOperation(value = "2.获取工程师待办列表", position = 2)
@GetMapping("/engineerList")
public RestResult<IPage<RepairTodo>> findTodoByEngineer(RepairTodoListQuery query) {
return RestResult.ok(iRepairTodoService.findTodoByEngineer(query));
}
@ApiOperation(value = "3.获取业务人员待办列表", position = 3)
@GetMapping("/businessList")
public RestResult<IPage<RepairTodo>> findTodoByBusiness(RepairTodoListQuery query) {
return RestResult.ok(iRepairTodoService.findTodoByBusiness(query));
}
@ApiOperation(value = "4.删除运维报障待办", position = 4)
@ApiImplicitParams({
@ApiImplicitParam(name = "repairId", value = "运维单ID", required = true),
})
@GetMapping("/deleteRepairTodo")
public RestResult<String> deleteRepairTodo(@RequestParam String repairId) {
LambdaQueryWrapper<RepairTodo> uw = new LambdaQueryWrapper<>();
uw.eq(RepairTodo::getRepairId, repairId);
iRepairTodoService.remove(uw);
return RestResult.ok();
}
@ApiOperation(value = "5.更新处理中并是有效状态,描述内容", position = 5)
@ApiImplicitParams({
@ApiImplicitParam(name = "handleId", value = "处理ID", required = true),
@ApiImplicitParam(name = "text", value = "内容", required = true),
})
@PostMapping("/updateHandleText")
public RestResult<String> updateHandleText(@RequestParam String handleId, @RequestParam String text) {
LambdaUpdateWrapper<RepairHandle> uw = new LambdaUpdateWrapper<>();
uw.eq(RepairHandle::getHandleId, handleId).eq(RepairHandle::getStatus, "1")
.set(RepairHandle::getResult, text)
.set(RepairHandle::getHappenTime, LocalDateTime.now());
iRepairHandleService.update(uw);
return RestResult.ok();
}
@ApiOperation(value = "6.业务人员未解决", position = 6)
@ApiImplicitParams({
@ApiImplicitParam(name = "handleId", value = "处理ID", required = true),
@ApiImplicitParam(name = "text", value = "内容", required = true),
})
@PostMapping("/unresolvedHandle")
public RestResult<String> unresolvedHandle(@RequestBody RepairHandle repairHandle, @RequestParam String tempHandleId) {
iRepairHandleService.unresolvedHandle(repairHandle, tempHandleId);
return RestResult.ok();
}
@ApiOperation(value = "7.运维工程师角色综合查询列表", position = 7)
@GetMapping("/byEngineer")
public RestResult<IPage<RepairTodo>> synthesizeEngineerList(RepairTodoListQuery query) {
return RestResult.ok(iRepairTodoService.synthesizeEngineerList(query));
}
@ApiOperation(value = "8.查询工程师自己所负责的待办", position = 8)
@GetMapping("/leaderTodo")
public RestResult<IPage<RepairTodo>> leaderTodo(RepairTodoListQuery query) {
return RestResult.ok(iRepairTodoService.leaderTodo(query));
}
}

View File

@ -0,0 +1,205 @@
package com.chinaweal.youfool.devops.repair.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.service.IRepairService;
import com.chinaweal.youfool.devops.repair.service.IRepairTodoService;
import com.chinaweal.youfool.devops.repair.service.impl.StatisticServiceImpl;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 统计
*/
@Api(tags = "3.运维报障统计")
@ApiSort(3)
@Transactional("devopsTransactionManager")
@RestController
@RequestMapping("/statistic")
public class StatisticController {
@Resource
private IRepairService iRepairService;
@Resource
private IRepairTodoService iRepairTodoService;
@Resource
private StatisticServiceImpl statisticService;
@ApiOperation(value = "1.根据申报账号UserId查询每个环节的数", position = 1)
@ApiImplicitParam(name = "username", value = "用户username", required = true)
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "declare", name = "已报障"),
@DynamicParameter(value = "assign", name = "分派"),
@DynamicParameter(value = "handle", name = "处理中"),
@DynamicParameter(value = "feedback", name = "已处理"),
@DynamicParameter(value = "unresolved", name = "未解决"),
@DynamicParameter(value = "resolved", name = "已解决"),
})
)
@GetMapping("/countRepairStepByUserId")
public RestResult<Map<String, Integer>> countRepairStepByUserId(String userId) {
Map<String, Integer> body = iRepairTodoService.countRepairStepByUserId(userId);
return RestResult.ok(body);
}
@ApiOperation(value = "2.运维单报障各项统计汇总", position = 2)
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "id", name = "数据项ID"),
@DynamicParameter(value = "name", name = "数据项名称"),
@DynamicParameter(value = "value", name = "值"),
@DynamicParameter(value = "isHide", name = "是否隐藏字段 truefalse"),
})
)
@GetMapping("/countSummary")
public RestResult<Map<String, Object>> sumSummary(RepairTodoListQuery query) {
Map<String, Object> body = new LinkedHashMap<>();
//概况总要
List<Map<String, Object>> summary = iRepairService.sumSummary(query);
body.put("summary", summary);
//业务分类标签
List<Map<String, Object>> busClassify = iRepairService.sumBusLabelByType(query, "labelBusClassify");
body.put("busClassify", busClassify);
//业务分类标签
List<Map<String, Object>> busStep = iRepairService.sumBusLabelByType(query, "labelBusStep");
body.put("busStep", busStep);
return RestResult.ok(body);
}
@ApiOperation(value = "3.根据统计内容项ID查询列表", position = 3)
@ApiImplicitParams({
@ApiImplicitParam(name = "itemId", value = "统计项Id", required = true),
})
@GetMapping("/listByItemId")
public RestResult<IPage<RepairTodo>> listByItemId(RepairTodoListQuery query, @RequestParam String itemId) {
IPage<RepairTodo> page = iRepairTodoService.listByItemId(query, itemId);
return RestResult.ok(page);
}
@ApiOperation(value = "4.导出统计汇总信息", position = 4)
@GetMapping("/exportSumSummary")
public void exportSumSummary(HttpServletResponse response, RepairTodoListQuery query) throws IOException {
iRepairService.exportSumSummary(query, response);
}
@ApiOperation(value = "5.根据统计内容项ID导出列表", position = 5)
@ApiImplicitParams({
@ApiImplicitParam(name = "itemId", value = "统计项Id", required = true),
})
@GetMapping("/exportListByItemId")
public void exportListByItemId(HttpServletResponse response, RepairTodoListQuery query, @RequestParam String itemId, @RequestParam String type) throws IOException {
iRepairTodoService.exportListByItemId(response, query, itemId, type);
}
@ApiOperation(value = "6.统计市局和各区的报障情况", position = 6)
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "name", name = "单位名称"),
@DynamicParameter(value = "total", name = "报障总数"),
@DynamicParameter(value = "resolved", name = "已解决"),
@DynamicParameter(value = "resolvedRate", name = "已解决占比"),
@DynamicParameter(value = "feedback", name = "已处理"),
@DynamicParameter(value = "feedbackRate", name = "已处理占比"),
@DynamicParameter(value = "unresolved", name = "未解决"),
@DynamicParameter(value = "unresolvedRate", name = "未解决占比"),
@DynamicParameter(value = "handleAndDeclare", name = "处理中"),
@DynamicParameter(value = "handleAndDeclareRate", name = "处理中占比"),
})
)
@GetMapping("/groupOrg")
public RestResult<List<Map<String, Object>>> groupOrgCount(RepairTodoListQuery query) {
List<Map<String, Object>> list = statisticService.groupOrgCount(query);
return RestResult.ok(list);
}
@ApiOperation(value = "7.导出统计市局和各区的报障情况", position = 7)
@GetMapping("/exportGroupOrg")
public void exportGroupOrg(HttpServletResponse response, RepairTodoListQuery query) throws IOException {
statisticService.exportGroupOrg(query, response);
}
@ApiOperation(value = "8.统计工单报障总数、待处理、待确认、已归档", position = 8)
@GetMapping("/sumTotalType")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "total", name = "报障总数"),
@DynamicParameter(value = "untreated", name = "待处理"),
@DynamicParameter(value = "confirmed", name = "待确认"),
@DynamicParameter(value = "resolved", name = "已归档"),
})
)
public RestResult<Map<String, Object>> sumTotalType(RepairTodoListQuery query) {
Map<String, Object> map = statisticService.sumTotalType(query);
return RestResult.ok(map);
}
@ApiOperation(value = "9.统计问题分类", position = 9)
@GetMapping("/sumQuestionType")
public RestResult<List<Map<String, Object>>> sumQuestionType(RepairTodoListQuery query) {
List<Map<String, Object>> map = statisticService.sumQuestionType(query);
return RestResult.ok(map);
}
@ApiOperation(value = "10.统计处理1到3次以上的成功次数", position = 10)
@GetMapping("/sumSuccess")
public RestResult<List<Map<String, Object>>> sumSuccess(RepairTodoListQuery query) {
List<Map<String, Object>> map = statisticService.sumSuccess(query);
return RestResult.ok(map);
}
@ApiOperation(value = "11.统计每天报障数、响应速度、业务总数、故障率", position = 11)
@GetMapping("/sumEfficiencyDay")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "date", name = "天 yyyy-MM-dd"),
@DynamicParameter(value = "reportTotal", name = "报障数"),
@DynamicParameter(value = "busTotal", name = "业务总数"),
@DynamicParameter(value = "faultRate", name = "故障率"),
@DynamicParameter(value = "resSpeed", name = "响应速度 小时单位时间是工作时间8小时"),
})
)
public RestResult<Map<String, Object>> sumEfficiency(RepairTodoListQuery query) {
Map<String, Object> list = statisticService.sumEfficiency(query);
return RestResult.ok(list);
}
@ApiOperation(value = "12.统计前5个问题的分类", position = 12)
@GetMapping("/sumQuestionTopDay")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(value = "date", name = "天 yyyy-MM-dd"),
@DynamicParameter(value = "reportTotal", name = "报障数"),
})
)
public RestResult<Map<String, Object>> sumQuestionTopDay(RepairTodoListQuery query) {
Map<String, Object> list = statisticService.sumQuestionTopDay(query);
return RestResult.ok(list);
}
}

View File

@ -0,0 +1,80 @@
package com.chinaweal.youfool.devops.repair.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.service.IRepairSummaryService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
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 javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* <p>
* 运维报障统计汇总 前端控制器
* </p>
*
* @author chinaweal
* @since 2020-08-13
*/
@Api(tags = "6.运维报障统计汇总主动调用")
@ApiSort(6)
@Transactional("devopsTransactionManager")
@RestController
@RequestMapping("/repair/summary")
public class SummaryController {
@Resource
private IRepairSummaryService iRepairSummaryService;
@ApiOperation(value = "1.根据时间范围按天并区分机构汇总,相关报障数据信息", position = 1)
@GetMapping("/sumOrgDay")
@Transactional(value = "devopsTransactionManager", propagation = Propagation.NOT_SUPPORTED)
public RestResult<String> sumAllOrgByDay(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startTime,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endTime) {
if (startTime.isAfter(endTime)) {
return RestResult.error(ResultCode.PARAM_IS_INVALID, "时间范围有误");
}
while (startTime.isBefore(endTime)) {
iRepairSummaryService.sumAllOrgByDay(startTime);
startTime = startTime.plusDays(1);
}
return RestResult.ok();
}
@ApiOperation(value = "2.根据时间范围按天并区分机构和问题分类汇总,相关报障数据信息", position = 2)
@GetMapping("/sumOrgQDay")
@Transactional(value = "devopsTransactionManager", propagation = Propagation.NOT_SUPPORTED)
public RestResult<String> sumAllOrgAndGroupQuestionByDay(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startTime,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endTime) {
if (startTime.isAfter(endTime)) {
return RestResult.error(ResultCode.PARAM_IS_INVALID, "时间范围有误");
}
while (startTime.isBefore(endTime)) {
iRepairSummaryService.sumAllOrgAndGroupQuestionByDay(startTime);
startTime = startTime.plusDays(1);
}
return RestResult.ok();
}
}

View File

@ -0,0 +1,111 @@
package com.chinaweal.youfool.devops.repair.controller.query;
import com.chinaweal.youfool.devops.base.controller.query.BaseListQuery;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@ApiModel("运维报障列表参数")
@Data
public class RepairTodoListQuery extends BaseListQuery {
@ApiModelProperty(value = "运维单ID 对应repair表repair_id")
private String repairId;
@ApiModelProperty(value = "标题")
private String title;
@ApiModelProperty(value = "申报用户昵称")
private String nickname;
@ApiModelProperty(value = "申报用户userId")
private String userId;
@ApiModelProperty(value = "申报用户账号")
private String username;
@ApiModelProperty(value = "所属机构")
private String org;
@ApiModelProperty(value = "所属部门")
private String dept;
@ApiModelProperty(value = "所属业务处室id")
private String deptId;
@ApiModelProperty(value = "问题类型")
private String questionType;
@ApiModelProperty(value = "业务模块")
private String business;
@ApiModelProperty(value = "优先级别 1紧急234低")
private Integer priority;
@ApiModelProperty(value = "报送时间开始")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime launchTimeStart;
@ApiModelProperty(value = "报送时间结束")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime launchTimeEnd;
@ApiModelProperty(value = "解决期限时间开始")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime solveLimitTimeStart;
@ApiModelProperty(value = "解决期限时间结束")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime solveLimitTimeEnd;
@ApiModelProperty(value = "环节步骤 多个可以用\",\"分割declaredeclare已报障assign分派handle处理中feedback已处理unresolved未解决resolved已解决end结束")
private String[] step;
@ApiModelProperty(value = "忽略的环节步骤 多个可以用\",\"分割declaredeclare已报障assign分派handle处理中feedback已处理unresolved未解决resolved已解决end结束")
private String[] notStep;
@ApiModelProperty(value = "运维工程师")
private String engineer;
@ApiModelProperty(value = "运维工程师username")
private String engineerUsername;
@ApiModelProperty(value = "处理更新时间开始")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime handleTimeStart;
@ApiModelProperty(value = "处理更新时间结束")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime handleTimeEnd;
@ApiModelProperty(value = "紧急程度 1紧急234低")
private Integer urgency;
@ApiModelProperty(value = "自定义导出表头列表")
private String[] fields;
@ApiModelProperty(value = "根据待办ID导出")
private String[] todoIds;
@ApiModelProperty(value = "催单,不为空则只查询催单记录")
private Integer reminder;
@ApiModelProperty(value = "根据催单排序优先")
private Boolean isReminderSort;
@ApiModelProperty(value = "业务受理号")
private String busAcceptNo;
@ApiModelProperty(value = "业务要求办理时效")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime busHandleTime;
@ApiModelProperty(value = "业务办理分类")
private String busClassify;
@ApiModelProperty(value = "业务办理业务环节")
private String busStep;
@ApiModelProperty(value = "多个所属部门精准搜索")
private List<String> orgList;
@ApiModelProperty(value = "多个所属部门模糊")
private List<String> orgListLike;
@ApiModelProperty(value = "多个部门id")
private List<String> orgIdList;
@ApiModelProperty(value = "负责人账号")
private String leaderUsername;
@ApiModelProperty(value = "负责人昵称")
private String leaderNickname;
@ApiModelProperty(value = "故障内容")
private String faultDescription;
@ApiModelProperty(value = "最后处理反馈时间开始")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime feedbackTimeStart;
@ApiModelProperty(value = "最后处理反馈时间结束")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime feedbackTimeEnd;
@ApiModelProperty(value = "标签")
private List<String> labels;
@ApiModelProperty(value = "查询的页面tab标识")
private String tabId;
@ApiModelProperty(value = "分派人员名称")
private String assignPersonnel;
@ApiModelProperty(value = "工单来源")
private List<String> source;
}

View File

@ -0,0 +1,149 @@
package com.chinaweal.youfool.devops.repair.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* <p>
* 通报
* </p>
*
* @author chinaweal
* @since 2020-11-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("NOTIFICATION")
@ApiModel(value = "Notification对象", description = "通报")
public class Notification extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* id
*/
@ApiModelProperty(value = "id")
@TableId(value = "UUID", type = IdType.ASSIGN_UUID)
private String uuid;
/**
* 统计月份
*/
@ApiModelProperty(value = "统计月份")
@TableField("MONTH_DATE")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDate monthDate;
/**
* 统计单位
*/
@ApiModelProperty(value = "统计单位")
@TableField("ORG")
private String org;
/**
* 报障总数
*/
@ApiModelProperty(value = "报障总数")
@TableField("TOTAL")
private BigDecimal total;
/**
* 已解决
*/
@ApiModelProperty(value = "已解决")
@TableField("RESOLVED")
private BigDecimal resolved;
/**
* 待确认
*/
@ApiModelProperty(value = "待确认")
@TableField("CONFIRMED")
private BigDecimal confirmed;
/**
* 未处理
*/
@ApiModelProperty(value = "未处理")
@TableField("UNTREATED")
private BigDecimal untreated;
/**
* 历史报障总数
*/
@ApiModelProperty(value = "历史报障总数")
@TableField("HISTORY_TOTAL")
private BigDecimal historyTotal;
/**
* 历史已解决
*/
@ApiModelProperty(value = "历史已解决")
@TableField("HISTORY_RESOLVED")
private BigDecimal historyResolved;
/**
* 历史待确认
*/
@ApiModelProperty(value = "历史待确认")
@TableField("HISTORY_CONFIRMED")
private BigDecimal historyConfirmed;
/**
* 历史未处理
*/
@ApiModelProperty(value = "历史未处理")
@TableField("HISTORY_UNTREATED")
private BigDecimal historyUntreated;
/**
* 一次处理
*/
@ApiModelProperty(value = "一次处理")
@TableField("ONE")
private BigDecimal one;
/**
* 两次处理
*/
@ApiModelProperty(value = "两次处理")
@TableField("TWO")
private BigDecimal two;
/**
* 三次处理以上
*/
@ApiModelProperty(value = "三次处理以上")
@TableField("THREE")
private BigDecimal three;
/**
* 故障平均处理时长 单位秒
*/
@ApiModelProperty(value = "故障平均处理时长 单位秒")
@TableField("AVG_HANDLE")
private BigDecimal avgHandle;
/**
* 故障平均解决时长 单位秒
*/
@ApiModelProperty(value = "故障平均解决时长 单位秒")
@TableField("AVG_RESOLVED")
private BigDecimal avgResolved;
}

View File

@ -0,0 +1,286 @@
package com.chinaweal.youfool.devops.repair.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 运维报障信息
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("REPAIR")
@ApiModel(value = "Repair对象", description = "运维报障信息")
public class Repair extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 运维单ID
*/
@ApiModelProperty(value = "运维单ID")
@TableId("REPAIR_ID")
private String repairId;
/**
* 标题
*/
@ApiModelProperty(value = "标题")
@TableField("TITLE")
private String title;
/**
* 申报账号ID
*/
@ApiModelProperty(value = "申报账号ID")
@TableField("USER_ID")
private String userId;
/**
* 申报用户昵称
*/
@ApiModelProperty(value = "申报用户昵称")
@TableField("NICKNAME")
private String nickname;
/**
* 申报用户账号
*/
@ApiModelProperty(value = "申报用户账号")
@TableField("USERNAME")
private String username;
/**
* 所属机构
*/
@ApiModelProperty(value = "所属机构")
@TableField("ORG")
private String org;
/**
* 所属机构Id
*/
@ApiModelProperty(value = "所属机构Id")
@TableField("ORG_ID")
private String orgId;
/**
* 所属部门
*/
@ApiModelProperty(value = "所属部门")
@TableField("DEPT")
private String dept;
/**
* 所属部门Id
*/
@ApiModelProperty(value = "所属部门Id")
@TableField("DEPT_ID")
private String deptId;
/**
* 联系电话
*/
@ApiModelProperty(value = "联系电话")
@TableField("PHONE")
private String phone;
/**
* 问题类型
*/
@ApiModelProperty(value = "问题类型")
@TableField("QUESTION_TYPE")
private String questionType;
/**
* 业务模块
*/
@ApiModelProperty(value = "业务模块")
@TableField("BUSINESS")
private String business;
/**
* 优先级别 1紧急234
*/
@ApiModelProperty(value = "优先级别 1紧急234低")
@TableField("PRIORITY")
private Integer priority;
/**
* 紧急程度 1紧急234
*/
@ApiModelProperty(value = "紧急程度 1紧急234低")
@TableField("URGENCY")
private Integer urgency;
/**
* 故障描述
*/
@ApiModelProperty(value = "故障描述")
@TableField("FAULT_DESCRIPTION")
private String faultDescription;
/**
* 报送时间
*/
@ApiModelProperty(value = "报送时间")
@TableField("LAUNCH_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime launchTime;
/**
* 解决期限时间
*/
@ApiModelProperty(value = "解决期限时间")
@TableField("SOLVE_LIMIT_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime solveLimitTime;
/**
* 当前环节信息
*/
@ApiModelProperty(value = "当前环节处理信息")
@TableField(exist = false)
private RepairHandle currentHandle;
/**
* 运维报障处理流程记录
*/
@ApiModelProperty(value = "运维报障处理流程记录列表")
@TableField(exist = false)
private List<RepairHandle> repairHandles;
/**
* 问题相关文件列表
*/
@ApiModelProperty(value = "问题相关附件")
@TableField(exist = false)
private List<RepairFile> questionFiles;
/**
* 问题相关文件列表
*/
@ApiModelProperty(value = "解答相关附件")
@TableField(exist = false)
private List<RepairFile> answerFiles;
/**
* 业务受理号
*/
@ApiModelProperty(value = "业务受理号")
@TableField("BUS_ACCEPT_NO")
private String busAcceptNo;
/**
* 业务办理分类标签
*/
@ApiModelProperty(value = "业务办理分类")
@TableField("BUS_CLASSIFY")
private String busClassify;
/**
* 业务办理业务环节
*/
@ApiModelProperty(value = "业务办理业务环节")
@TableField("BUS_STEP")
private String busStep;
/**
* 业务要求办理时效
*/
@ApiModelProperty(value = "业务要求办理时效")
@TableField("BUS_HANDLE_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime busHandleTime;
/**
* 计划完成时间
*/
@ApiModelProperty(value = "计划完成时间")
@TableField("PLANNED_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime plannedTime;
/**
* 实际完成时间
*/
@ApiModelProperty(value = "实际完成时间")
@TableField("REALITY_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime realityTime;
/**
* 负责人昵称
*/
@ApiModelProperty(value = "负责人昵称")
@TableField("LEADER_NICKNAME")
private String leaderNickname;
/**
* 负责人账号
*/
@ApiModelProperty(value = "负责人账号")
@TableField("LEADER_USERNAME")
private String leaderUsername;
@ApiModelProperty(value = "待办信息")
@TableField(exist = false)
private RepairTodo repairTodo;
@ApiModelProperty(value = "标签")
@TableField(exist = false)
private List<String> labels;
/**
* 解决思路填录
*/
@ApiModelProperty(value = "解决思路填录")
@TableField("THINKING")
private String thinking;
/**
* 标签字符
*/
@ApiModelProperty(value = "标签字符")
@TableField("LABEL")
private String label;
/**
* 业务企业名称
*/
@ApiModelProperty(value = "业务企业名称")
@TableField("BUS_ENT_NAME")
private String busEntName;
/**
* 是否需要导出数据0否1是
*/
@ApiModelProperty("是否需要导出数据0否1是")
@TableField("NEED_DATA_EXPORT")
private String needDataExport;
/**
* 报障单来源
* 1内网2特设系统外网
*/
@ApiModelProperty("报障单来源")
@TableField(exist = false)
private String source;
}

View File

@ -0,0 +1,97 @@
package com.chinaweal.youfool.devops.repair.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* <p>
* 运维报障附件
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("REPAIR_FILE")
@ApiModel(value = "RepairFile对象", description = "运维报障附件")
public class RepairFile extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 文件ID
*/
@ApiModelProperty(value = "文件ID")
@TableId(value = "UUID", type = IdType.ASSIGN_UUID)
private String uuid;
/**
* 文件名
*/
@ApiModelProperty(value = "文件名")
@TableField("FILE_NAME")
private String fileName;
/**
* 文件类型
*/
@ApiModelProperty(value = "文件类型")
@TableField("FILE_TYPE")
private String fileType;
/**
* 类型 question问题相关附件answer解答相关附件
*/
@ApiModelProperty(value = "类型 question问题相关附件answer解答相关附件")
@TableField("TYPE")
private String type;
/**
* 文件路径
*/
@ApiModelProperty(value = "文件路径")
@TableField("FILE_PATH")
private String filePath;
/**
* 文件大小 单位字节
*/
@ApiModelProperty(value = "文件大小 单位字节")
@TableField("FILE_SIZE")
private Long fileSize;
/**
* 运维单ID 对应repair表的repair_id
*/
@ApiModelProperty(value = "运维单ID 对应repair表的repair_id")
@TableField("REPAIR_ID")
private String repairId;
/**
* 处理ID 对应运维报障处理流程记录
*/
@ApiModelProperty(value = "处理ID 对应运维报障处理流程记录")
@TableField("HANDLE_ID")
private String handleId;
/**
* 上传时间
*/
@ApiModelProperty(value = "上传时间")
@TableField(value = "UPLOAD_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime uploadTime;
}

View File

@ -0,0 +1,189 @@
package com.chinaweal.youfool.devops.repair.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 运维报障处理流程记录
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("REPAIR_HANDLE")
@ApiModel(value = "RepairHandle对象", description = "运维报障处理流程记录")
public class RepairHandle extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 处理ID
*/
@ApiModelProperty(value = "处理ID")
@TableId(value = "HANDLE_ID", type = IdType.ASSIGN_UUID)
private String handleId;
/**
* 报障待办ID 对应repair_todo表的todo_id
*/
@ApiModelProperty(value = "报障待办ID 对应repair_todo表的todo_id")
@TableField("TODO_ID")
private String todoId;
/**
* 运维单ID 对应repair表的repair_id
*/
@ApiModelProperty(value = "运维单ID 对应repair表的repair_id")
@TableField("REPAIR_ID")
private String repairId;
/**
* 处理人
*/
@ApiModelProperty(value = "处理人")
@TableField("HANDLE_NICKNAME")
private String handleNickname;
/**
* 处理人账号
*/
@ApiModelProperty(value = "处理人账号")
@TableField("HANDLE_USERNAME")
private String handleUsername;
/**
* 环节步骤 declaredeclare已报障assign分派handle处理中feedback已处理unresolved未解决resolved已解决end结束
*/
@ApiModelProperty(value = "环节步骤 declaredeclare已报障assign分派handle处理中feedback已处理unresolved未解决resolved已解决end结束")
@TableField("STEP")
private String step;
/**
* 生成时间
*/
@ApiModelProperty(value = "生成时间")
@TableField("HAPPEN_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime happenTime;
/**
* 处理结果
*/
@ApiModelProperty(value = "处理结果")
@TableField("RESULT")
private String result;
/**
* 优先级别 1紧急234
*/
@ApiModelProperty(value = "优先级别 1紧急234低")
@TableField(exist = false)
private Integer priority;
/**
* 问题分类
*/
@ApiModelProperty(value = "问题分类")
@TableField(exist = false)
private String questionType;
/**
* 问题分类
*/
@ApiModelProperty(value = "问题标签")
@TableField(exist = false)
private String[] labels;
/**
* 环节状态 0过期1有效
*/
@ApiModelProperty(value = "环节状态 0过期1有效")
@TableField("STATUS")
private String status;
/**
* 下一个处理人
*/
@ApiModelProperty(value = "下一个处理人")
@TableField(exist = false)
private String nextHandleNickname;
/**
* 下一个处理人username
*/
@ApiModelProperty(value = "下一个处理人username")
@TableField(exist = false)
private String nextHandleUsername;
@TableField(exist = false)
@ApiModelProperty(value = "附件列表")
private List<RepairFile> files;
@TableField(exist = false)
@ApiModelProperty(value = "计划完成时间")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime plannedTime;
/**
* 负责人昵称
*/
@ApiModelProperty(value = "负责人昵称")
@TableField(exist = false)
private String leaderNickname;
/**
* 解决思路填录
*/
@ApiModelProperty(value = "解决思路填录")
@TableField(exist = false)
private String thinking;
/**
* 负责人账号
*/
@ApiModelProperty(value = "负责人账号")
@TableField(exist = false)
private String leaderUsername;
public LocalDateTime getHappenTime() {
return happenTime;
}
public void setHappenTime(LocalDateTime happenTime) {
this.happenTime = happenTime;
}
public RepairHandle(String todoId, String repairId, String step) {
this.todoId = todoId;
this.repairId = repairId;
this.step = step;
}
public RepairHandle(String todoId, String repairId, String step, String handleUsername, String handleNickname, String result) {
this.todoId = todoId;
this.repairId = repairId;
this.step = step;
this.handleUsername = handleUsername;
this.handleNickname = handleNickname;
this.result = result;
}
}

View File

@ -0,0 +1,55 @@
package com.chinaweal.youfool.devops.repair.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 运维单标签
* </p>
*
* @author chinaweal
* @since 2020-07-10
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("REPAIR_LABEL")
@ApiModel(value = "Label对象", description = "运维单标签")
public class RepairLabel extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 标签ID
*/
@ApiModelProperty(value = "标签ID")
@TableId(value = "LABEL_ID", type = IdType.ASSIGN_UUID)
private String labelId;
/**
* 名称
*/
@ApiModelProperty(value = "名称")
@TableField("NAME")
private String name;
/**
* 运维单ID 对应repair表repair_id
*/
@ApiModelProperty(value = "运维单ID 对应repair表repair_id")
@TableField("REPAIR_ID")
private String repairId;
}

View File

@ -0,0 +1,95 @@
package com.chinaweal.youfool.devops.repair.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableField;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 运维报障统计汇总
* </p>
*
* @author chinaweal
* @since 2020-08-13
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("REPAIR_SUMMARY")
@ApiModel(value = "Summary对象", description = "运维报障统计汇总")
public class RepairSummary extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* id
*/
@ApiModelProperty(value = "id")
@TableId(value = "UUID", type = IdType.ASSIGN_UUID)
private String uuid;
/**
* 时间
*/
@ApiModelProperty(value = "时间")
@TableField("TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime time;
/**
* 统计类型 多种统计汇总结果类型然后所有表字段拉平存放
*/
@ApiModelProperty(value = "统计类型 多种统计汇总结果类型,然后所有表字段拉平存放")
@TableField("TYPE")
private String type;
/**
* 问题分类
*/
@ApiModelProperty(value = "问题分类")
@TableField("QUESTION_TYPE")
private String questionType;
/**
* 业务总数
*/
@ApiModelProperty(value = "业务总数")
@TableField("BUS_TOTAL")
private BigDecimal busTotal;
/**
* 报障数
*/
@ApiModelProperty(value = "报障数")
@TableField("REPORT_TOTAL")
private BigDecimal reportTotal;
/**
* 处理数
*/
@ApiModelProperty(value = "处理数")
@TableField("HANDLE_TOTAL")
private BigDecimal handleTotal;
/**
* 机构
*/
@ApiModelProperty(value = "机构")
@TableField("ORG")
private String org;
}

View File

@ -0,0 +1,337 @@
package com.chinaweal.youfool.devops.repair.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 运维报障待办
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(schema = "DEVOPS", value = "REPAIR_TODO")
@ApiModel(value = "RepairTodo对象", description = "运维报障待办")
@JsonIgnoreProperties(value = {"handler"})
public class RepairTodo extends SuperEntity {
private static final long serialVersionUID = 1L;
/**
* 报障待办ID
*/
@ApiModelProperty(value = "报障待办ID")
@TableId(value = "TODO_ID", type = IdType.ASSIGN_UUID)
private String todoId;
/**
* 运维单ID 对应repair表repair_id
*/
@ApiModelProperty(value = "运维单ID 对应repair表repair_id")
@TableField("REPAIR_ID")
private String repairId;
/**
* 标题
*/
@ApiModelProperty(value = "标题")
@TableField("TITLE")
private String title;
/**
* 申报账号ID
*/
@ApiModelProperty(value = "申报账号ID")
@TableField("USER_ID")
private String userId;
/**
* 申报用户昵称
*/
@ApiModelProperty(value = "申报用户昵称")
@TableField("NICKNAME")
private String nickname;
/**
* 申报用户账号
*/
@ApiModelProperty(value = "申报用户账号")
@TableField("USERNAME")
private String username;
/**
* 所属机构
*/
@ApiModelProperty(value = "所属机构")
@TableField("ORG")
private String org;
/**
* 所属机构Id
*/
@ApiModelProperty(value = "所属机构Id")
@TableField("ORG_ID")
private String orgId;
/**
* 所属部门
*/
@ApiModelProperty(value = "所属部门")
@TableField("DEPT")
private String dept;
/**
* 所属部门Id
*/
@ApiModelProperty(value = "所属部门Id")
@TableField("DEPT_ID")
private String deptId;
/**
* 问题分类
*/
@ApiModelProperty(value = "问题分类")
@TableField(exist = false)
private String questionType;
/**
* 标签
*/
@ApiModelProperty(value = "标签")
@TableField(exist = false)
private List<String> labels;
/**
* 业务模块
*/
@ApiModelProperty(value = "业务模块")
@TableField("BUSINESS")
private String business;
/**
* 优先级别 1紧急234
*/
@ApiModelProperty(value = "优先级别 1紧急234低")
@TableField("PRIORITY")
private Integer priority;
/**
* 紧急程度 1紧急234
*/
@ApiModelProperty(value = "紧急程度 1紧急234低")
@TableField("URGENCY")
private Integer urgency;
/**
* 报送时间
*/
@ApiModelProperty(value = "报送时间")
@TableField("LAUNCH_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime launchTime;
/**
* 解决期限时间
*/
@ApiModelProperty(value = "解决期限时间")
@TableField("SOLVE_LIMIT_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime solveLimitTime;
/**
* 环节步骤 declaredeclare已报障assign分派handle处理中feedback已处理unresolved未解决resolved已解决end结束
*/
@ApiModelProperty(value = "环节步骤 declaredeclare已报障assign分派handle处理中feedback已处理unresolved未解决resolved已解决end结束")
@TableField("STEP")
private String step;
/**
* 运维工程师
*/
@ApiModelProperty(value = "运维工程师")
@TableField("ENGINEER")
private String engineer;
/**
* 运维工程师username
*/
@ApiModelProperty(value = "运维工程师username")
@TableField("ENGINEER_USERNAME")
private String engineerUsername;
/**
* 催单次数
*/
@ApiModelProperty(value = "催单次数")
@TableField("REMINDER")
private Integer reminder;
/**
* 处理更新时间
*/
@ApiModelProperty(value = "处理更新时间")
@TableField("HANDLE_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime handleTime;
/**
* 是否删除 0有效1删除
*/
@ApiModelProperty(value = "是否删除 0有效1删除")
@TableLogic(value = "0", delval = "1")
@TableField("DELETED")
private String deleted;
/**
* 故障描述
*/
@ApiModelProperty(value = "故障描述")
@TableField(exist = false)
private String faultDescription;
/**
* 业务受理号
*/
@ApiModelProperty(value = "业务受理号")
@TableField(exist = false)
private String busAcceptNo;
/**
* 业务要求办理时效
*/
@ApiModelProperty(value = "业务要求办理时效")
@TableField(exist = false)
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime busHandleTime;
/**
* 业务办理分类标签
*/
@ApiModelProperty(value = "业务办理分类标签")
@TableField(exist = false)
private String busClassify;
/**
* 业务办理业务环节
*/
@ApiModelProperty(value = "业务办理业务环节")
@TableField(exist = false)
private String busStep;
/**
* 计划完成时间
*/
@ApiModelProperty(value = "计划完成时间")
@TableField(exist = false)
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime plannedTime;
/**
* 实际完成时间
*/
@ApiModelProperty(value = "实际完成时间")
@TableField(exist = false)
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime realityTime;
/**
* 负责人昵称
*/
@ApiModelProperty(value = "负责人昵称")
@TableField(exist = false)
private String leaderNickname;
/**
* 负责人账号
*/
@ApiModelProperty(value = "负责人账号")
@TableField(exist = false)
private String leaderUsername;
@ApiModelProperty(value = "解决时长,单位小时")
@TableField(exist = false)
private BigDecimal solveTime;
/**
* 最后处理反馈时间
*/
@ApiModelProperty(value = "最后处理反馈时间")
@TableField("FEEDBACK_TIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime feedbackTime;
@ApiModelProperty(value = "最后处理反馈时长")
@TableField(exist = false)
private BigDecimal feedbackTimeSize;
@ApiModelProperty(value = "解决思路填录")
@TableField(exist = false)
private String thinking;
/**
* 标签集合字符
*/
@ApiModelProperty(value = "标签集合字符','分割")
@TableField(exist = false)
private String label;
/**
* 是否需要导出数据0否1是
*/
@ApiModelProperty("是否需要导出数据0否1是")
@TableField(exist = false)
private String needDataExport;
/**
* 报障单来源
* 1内网2特设系统外网3佛山pc年报
*/
@ApiModelProperty("报障单来源")
@TableField("SOURCE")
private String source;
public LocalDateTime getLaunchTime() {
return launchTime;
}
public void setLaunchTime(LocalDateTime launchTime) {
this.launchTime = launchTime;
}
public LocalDateTime getSolveLimitTime() {
return solveLimitTime;
}
public void setSolveLimitTime(LocalDateTime solveLimitTime) {
this.solveLimitTime = solveLimitTime;
}
public LocalDateTime getHandleTime() {
return handleTime;
}
public void setHandleTime(LocalDateTime handleTime) {
this.handleTime = handleTime;
}
public LocalDateTime getBusHandleTime() {
return busHandleTime;
}
public void setBusHandleTime(LocalDateTime busHandleTime) {
this.busHandleTime = busHandleTime;
}
}

View File

@ -0,0 +1,142 @@
package com.chinaweal.youfool.devops.repair.excel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.List;
/**
* 自定义表格样式
*/
public class CustomRowCellWriteHandler implements CellWriteHandler, RowWriteHandler, SheetWriteHandler {
private Workbook workbook;
private CellStyle defaultCellStyle;
/**
* 设置居中和边框
*
* @return
*/
private CellStyle getBorderAndCenter(CellStyle style) {
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
return style;
}
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
Integer columnIndex = head.getColumnIndex();
if (!isHead) {
//内容
cell.setCellStyle(defaultCellStyle);
} else if (relativeRowIndex == 0 && columnIndex == 0) {
//大标题
CellStyle cellStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 14);
font.setBold(true);
cellStyle.setFont(font);
cell.setCellStyle(getBorderAndCenter(cellStyle));
} else if (relativeRowIndex == 1) {
//小表头
CellStyle cellStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12);
font.setBold(true);
cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellStyle.setFont(font);
cell.setCellStyle(getBorderAndCenter(cellStyle));
}
}
@Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
if (!isHead) {
//默认高度
row.setHeightInPoints(20);
} else if (relativeRowIndex == 0) {
List<List<String>> heads = writeSheetHolder.getHead();
Sheet sheet = writeSheetHolder.getSheet();
//大表头
int size = heads.size();
//合并标题内容
CellRangeAddress hTitleRegion = new CellRangeAddress(0, 0, 0, size - 1);
sheet.addMergedRegion(hTitleRegion);
row.setHeightInPoints(40);
} else if (relativeRowIndex == 1) {
List<List<String>> heads = writeSheetHolder.getHead();
Sheet sheet = writeSheetHolder.getSheet();
int size = heads.size();
row.setHeightInPoints(25);
//添加小表头筛选
CellRangeAddress cellRangeAddress = new CellRangeAddress(1, 1, 0, size - 1);
sheet.setAutoFilter(cellRangeAddress);
//判断列宽
sheet.setColumnWidth(0, 2000);
for (int i = 1; i < size; i++) {
sheet.setColumnWidth(i, 5000);
}
}
}
void init(WriteWorkbookHolder writeWorkbookHolder) {
this.workbook = writeWorkbookHolder.getWorkbook();
CellStyle cellStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12);
cellStyle.setFont(font);
this.defaultCellStyle = getBorderAndCenter(cellStyle);
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
init(writeWorkbookHolder);
}
}

View File

@ -0,0 +1,41 @@
package com.chinaweal.youfool.devops.repair.excel;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author itluc
*/
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
@Override
public Class supportJavaTypeKey() {
return LocalDateTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return LocalDateTime.parse(cellData.getStringValue());
} else {
return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern(contentProperty.getDateTimeFormatProperty().getFormat()));
}
}
@Override
public CellData convertToExcelData(LocalDateTime value, ExcelContentProperty
contentProperty, GlobalConfiguration globalConfiguration) {
return new CellData(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}

View File

@ -0,0 +1,147 @@
package com.chinaweal.youfool.devops.repair.excel;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import static com.chinaweal.youfool.devops.repair.service.IRepairHandleService.*;
@Data
public class RepairTodoExcel {
private Integer no;
private String repairId;
private String title;
private String nickname;
private String username;
private String org;
private String dept;
private String business;
private String priority;
private String urgency;
private LocalDateTime solveLimitTime;
private String step;
private String engineer;
private LocalDateTime handleTime;
private String faultDescription;
private LocalDateTime launchTime;
private String reminder;
private String busAcceptNo;
private LocalDateTime busHandleTime;
private LocalDateTime plannedTime;
private LocalDateTime realityTime;
private LocalDateTime feedbackTime;
private String questionType;
private String label;
private String leaderNickname;
private String solveTime;
private String feedbackTimeSize;
private String busStep;
private String busClassify;
public void setPriority(Integer priority) {
if (priority == null) return;
switch (priority) {
case 1: {
this.priority = "紧急";
break;
}
case 2: {
this.priority = "高";
break;
}
case 3: {
this.priority = "中";
break;
}
case 4: {
this.priority = "低";
break;
}
default:
break;
}
}
public void setUrgency(Integer urgency) {
if (urgency == null) return;
switch (urgency) {
case 1: {
this.urgency = "紧急";
break;
}
case 2: {
this.urgency = "高";
break;
}
case 3: {
this.urgency = "中";
break;
}
case 4: {
this.urgency = "低";
break;
}
default:
break;
}
}
public void setStep(String step) {
if (step == null) return;
switch (step) {
case DECLARE: {
this.step = "已报障";
break;
}
case ASSIGN: {
this.step = "分派";
break;
}
case HANDLE: {
this.step = "处理中";
break;
}
case FEEDBACK: {
this.step = "已处理";
break;
}
case UNRESOLVED: {
this.step = "未解决";
break;
}
case RESOLVED: {
this.step = "已解决";
break;
}
case END: {
this.step = "结束";
break;
}
default:
break;
}
}
public void setReminder(Integer reminder) {
if (reminder != null) {
this.reminder = "催单";
}
}
public void setSolveTime(BigDecimal solveTime) {
if (solveTime != null) {
this.solveTime = solveTime.setScale(3, BigDecimal.ROUND_HALF_UP) + " 小时";
}
}
public void setFeedbackTimeSize(BigDecimal feedbackTimeSize) {
if (feedbackTimeSize != null) {
this.feedbackTimeSize = feedbackTimeSize.setScale(3, BigDecimal.ROUND_HALF_UP) + " 小时";
}
}
}

View File

@ -0,0 +1,23 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaweal.youfool.devops.repair.entity.Notification;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
/**
* <p>
* 通报 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-11-02
*/
public interface NotificationMapper extends BaseMapper<Notification> {
List<Map<String, Object>> dailyHandledUserNum(@Param("start") LocalDate start, @Param("end") LocalDate end);
List<Map<String, Object>> unhandledUserNum();
}

View File

@ -0,0 +1,16 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaweal.youfool.devops.repair.entity.RepairFile;
/**
* <p>
* 运维报障附件 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface RepairFileMapper extends BaseMapper<RepairFile> {
}

View File

@ -0,0 +1,53 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障处理流程记录 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface RepairHandleMapper extends BaseMapper<RepairHandle> {
BigDecimal countStep(@Param("query") RepairTodoListQuery query, @Param("itemId") String itemId);
/**
* 处理故障N次成功数量
*/
BigDecimal countResultSecond(@Param("query") RepairTodoListQuery query, @Param("second") Integer second);
/**
* 处理故障N次成功列表
*/
IPage<RepairTodo> listResultSecond(Page<RepairTodo> page, @Param("query") RepairTodoListQuery query, @Param("second") Integer second);
/**
* 平均解决时长
*/
Map<String, Object> getAvgResolvedTime(@Param("query") RepairTodoListQuery query);
/**
* 平均处理时长
*/
Map<String, Object> getAvgFeedbackTime(@Param("query") RepairTodoListQuery query);
/**
* 根据时间范围机构环节统计流程数量去重
*/
Long countDistinctByTimeAndOrgAndStep(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime,
@Param("orgListLike") List<String> orgListLike, @Param("step") String step);
}

View File

@ -0,0 +1,31 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairLabel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维单标签 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-07-10
*/
public interface RepairLabelMapper extends BaseMapper<RepairLabel> {
List<Map<String, String>> listLabelOrder();
/**
* 统计分类名称出现的次数
*
* @param query
*/
List<Map<String, Object>> groupNameCount(@Param("query") RepairTodoListQuery query);
List<String> listNameByRepairId(@Param("repairId") String repairId);
}

View File

@ -0,0 +1,25 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.Repair;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障信息 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface RepairMapper extends BaseMapper<Repair> {
List<Map<String, Object>> groupByQuestionTypeCount(@Param("query") RepairTodoListQuery query);
BigDecimal countByQuestionType(@Param("query") RepairTodoListQuery query);
}

View File

@ -0,0 +1,29 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.chinaweal.youfool.devops.repair.entity.RepairSummary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障统计汇总 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-08-13
*/
public interface RepairSummaryMapper extends BaseMapper<RepairSummary> {
List<Map<String, Object>> sumTotalByOrgAndDay(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime,
@Param("orgs") List<String> orgs);
List<Map<String, Object>> getGroupQuestionTop(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime,
@Param("orgs") List<String> orgs);
List<Map<String, Object>> sumTotalByOrgAndQuestionDay(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime,
@Param("questionType") String questionType, @Param("orgs") List<String> orgs);
}

View File

@ -0,0 +1,52 @@
package com.chinaweal.youfool.devops.repair.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障待办 Mapper 接口
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface RepairTodoMapper extends BaseMapper<RepairTodo> {
IPage<RepairTodo> listTodo(Page<RepairTodo> page, RepairTodoListQuery query);
IPage<RepairTodo> listByTodoId(Page<RepairTodo> page, String[] todoIds);
/**
* 根据统计项ID 查询列表
*/
// IPage<RepairTodo> listByItemId(Page<RepairTodo> page, RepairTodoListQuery query, String itemId);
/**
* 查询业务统分类统计查询
*/
List<Map<String, Object>> groupByBusClassifyCount(@Param("query") RepairTodoListQuery query);
/**
* 查询业务统环节统计查询
*/
List<Map<String, Object>> groupByBusStepCount(@Param("query") RepairTodoListQuery query);
/**
* 根据搜索条件查询整体数据数据情况
*/
Map<String, Object> getWhole(@Param("query") RepairTodoListQuery query);
Long countByLaunchTimeAndLikeOrg(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime,
@Param("orgListLike") List<String> orgListLike);
List<String> listSonOrgId(@Param("orgId") String orgId);
}

View File

@ -0,0 +1,94 @@
package com.chinaweal.youfool.devops.repair.scheduled;
import com.chinaweal.youfool.devops.base.service.IMonitorService;
import com.chinaweal.youfool.devops.repair.service.INotificationService;
import com.chinaweal.youfool.devops.repair.service.IRepairSummaryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDate;
/**
* 汇总统计定时任务
*/
@Component
@Slf4j
public class SummaryScheduled {
@Resource
private IRepairSummaryService iRepairSummaryService;
@Resource
private INotificationService iNotificationService;
@Resource
private IMonitorService iMonitorService;
/**
* 按照天数格式和机构 汇总报障的记录参数
* 每天零点5分开始跑汇总昨天的一整天
*/
@Transactional("devopsTransactionManager")
public void sumAllOrgByDay() {
log.info("--------开始:执行按照天数格式和机构 汇总报障的记录参数每天零点5分开始跑汇总昨天的一整天----------");
try {
iRepairSummaryService.sumAllOrgByDay(LocalDate.now().minusDays(1));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
log.info("--------结束:执行按照天数格式和机构 汇总报障的记录参数每天零点5分开始跑汇总昨天的一整天----------");
}
/**
* 按照天数格式和机构问题分类 汇总报障的记录参数
* 每20分钟全量更新一次汇总之前所有数据至昨天
*/
@Transactional("devopsTransactionManager")
public void sumAllOrgGroupQByDay() {
log.info("--------开始:按照天数格式和机构、问题分类 汇总报|障的记录参数每20分钟全量更新一次汇总之前所有数据至昨天 ----------");
//佛山默认从6月1号
LocalDate startDate = LocalDate.parse("2020-06-01");
while (startDate.isBefore(LocalDate.now())) {
try {
iRepairSummaryService.sumAllOrgAndGroupQuestionByDay(startDate);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
startDate = startDate.plusDays(1);
}
log.info("--------结束:按照天数格式和机构、问题分类 汇总报障的记录参数每20分钟全量更新一次汇总之前所有数据至昨天 ----------");
}
/**
* 每月1号零点统计上个月的通报记录
*/
@Transactional("devopsTransactionManager")
public void sumMonthMakeData() {
log.info("--------开始每月1号零点统计上个月的通报记录 ----------");
LocalDate date = LocalDate.now().minusMonths(1);
iNotificationService.makeData(date);
log.info("--------结束每月1号零点统计上个月的通报记录 ----------");
}
/**
* 每天8点进行通报运维统计情况
*/
@Transactional("devopsTransactionManager")
public void sendDayJournal() throws IOException {
log.info("--------开始每天早上8点通报一次运维记录 ----------");
LocalDate date = LocalDate.now().minusDays(1);
iNotificationService.sendDayJournal(date);
log.info("--------结束每天早上8点通报一次运维记录 ----------");
}
/**
* 每天查询数据库密码过期情况符合则进行通知预警
*/
public void countDbPwdExpireAndSendWx() throws Exception {
log.info("--------开始每天早上8点查询账号密码过期情况 ----------");
iMonitorService.countDbPwdExpireAndSendWx();
log.info("--------结束每天早上8点查询账号密码过期情况 ----------");
}
}

View File

@ -0,0 +1,48 @@
package com.chinaweal.youfool.devops.repair.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.devops.repair.entity.Notification;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
/**
* <p>
* 通报 服务类
* </p>
*
* @author chinaweal
* @since 2020-11-02
*/
public interface INotificationService extends IService<Notification> {
/**
* 导出通报文件word
*/
void exportBulletinWord(LocalDate parse, HttpServletResponse response) throws Exception;
/**
* 根据月份生成通报数据
*/
void makeData(LocalDate parse);
List<Map<String, Object>> findUnitData(LocalDate parse);
/**
* 生成每日通报
*
* @param date 统计的日期
*/
File createDayJournalXlsx(LocalDate date);
/**
* 发送通报到企业微信
*
* @param date 统计的日期
*/
void sendDayJournal(LocalDate date) throws IOException;
}

View File

@ -0,0 +1,44 @@
package com.chinaweal.youfool.devops.repair.service;
import com.chinaweal.youfool.devops.repair.entity.RepairFile;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障附件 服务类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface IRepairFileService extends IService<RepairFile> {
/**
* 保存文件
*
* @return
*/
Map<String, String> loadFile(MultipartFile multipartFile, String tempRepairId, String type, String tempHandleId) throws IOException;
/**
* 根据临时的repairId记录 修改最终的repairIdhandleId
*/
void updateRepairAndHandleIdByTempRepairId(String tempRepairId, String repairId, String handleId);
List<RepairFile> listByRepairId(String repairId);
void downloadFile(String uuid, boolean online, HttpServletResponse response) throws IOException;
void deleteFile(String uuid);
/**
* 根据临时的handleId记录 修改最终的repairIdhandleId
*/
void updateHandleIdByTempHandleId(String tempHandleId, String handleId);
}

View File

@ -0,0 +1,63 @@
package com.chinaweal.youfool.devops.repair.service;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import java.util.List;
/**
* <p>
* 运维报障处理流程记录 服务类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface IRepairHandleService extends IService<RepairHandle> {
/**
* 已报障
*/
String DECLARE = "declare";
/**
* 分派
*/
String ASSIGN = "assign";
/**
* 处理中
*/
String HANDLE = "handle";
/**
* 已处理
*/
String FEEDBACK = "feedback";
/**
* 未解决
*/
String UNRESOLVED = "unresolved";
/**
* 已解决
*/
String RESOLVED = "resolved";
/**
* 结束
*/
String END = "end";
/**
* 更新处理流程记录
*/
RepairHandle updateByRepairIdHandleTodo(RepairHandle repairHandle);
/**
* 查询处理流程记录生成时间降序
*/
List<RepairHandle> listByRepairId(String repairId);
/**
* 获取当前处理流程记录
*/
RepairHandle getCurrentHandle(String repairId);
RestResult<String> unresolvedHandle(RepairHandle repairHandle, String tempHandleId);
}

View File

@ -0,0 +1,23 @@
package com.chinaweal.youfool.devops.repair.service;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairLabel;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维单标签 服务类
* </p>
*
* @author chinaweal
* @since 2020-07-10
*/
public interface IRepairLabelService extends IService<RepairLabel> {
List<Map<String, String>> listLabel();
List<Map<String, Object>> groupLabelCount(RepairTodoListQuery query);
}

View File

@ -0,0 +1,54 @@
package com.chinaweal.youfool.devops.repair.service;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.devops.repair.entity.Repair;
import com.baomidou.mybatisplus.extension.service.IService;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障信息 服务类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface IRepairService extends IService<Repair> {
RestResult<String> saveRepair(Repair repair);
RestResult<String> updateRepair(Repair repair);
Repair getRepair(String repairId);
/**
* 根据标签类型修改标签
*/
void updateLabelByType(List<String> repairIds, String labelType, String labelName);
/**
* 统计各项报障数据内容
*/
List<Map<String, Object>> sumSummary(RepairTodoListQuery query);
/**
* 根据业务标签类型进行统计
*/
List<Map<String, Object>> sumBusLabelByType(RepairTodoListQuery query, String labelType);
/**
* 导出统计项的内容
*/
void exportSumSummary(RepairTodoListQuery query, HttpServletResponse response) throws IOException;
/**
* 更新部分运维信息
*/
void updateDevInfo(Map<String, Object> map);
}

View File

@ -0,0 +1,61 @@
package com.chinaweal.youfool.devops.repair.service;
import com.chinaweal.youfool.devops.repair.entity.RepairSummary;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.commons.lang3.ArrayUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 运维报障统计汇总 服务类
* </p>
*
* @author chinaweal
* @since 2020-08-13
*/
public interface IRepairSummaryService extends IService<RepairSummary> {
/**
* 机构统计
*/
String ORG = "org";
/**
* 机构+问题分类 统计
*/
String ORG_QUESTION = "orgQuestion";
/**
* 根据机构和天汇总报障相关数量
*
* @param day
*/
void sumAllOrgByDay(LocalDate day);
/**
* 根据机构问题分类天汇总报障相关数量
*
* @param day
*/
void sumAllOrgAndGroupQuestionByDay(LocalDate day);
static List<String> getOrgNameList() {
List<String> orgList = new ArrayList<>();
orgList.add("佛山市市场监督管理局");
orgList.add("佛山市禅城区市场监督管理局");
orgList.add("佛山市顺德区市场监督管理局");
orgList.add("佛山市南海区市场监督管理局");
orgList.add("佛山市三水区市场监督管理局");
orgList.add("佛山市高明区市场监督管理局");
orgList.add("考试中心");
return orgList;
}
}

View File

@ -0,0 +1,113 @@
package com.chinaweal.youfool.devops.repair.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.Repair;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障待办 服务类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
public interface IRepairTodoService extends IService<RepairTodo> {
RepairTodo getByRepairId(String repairId);
IPage<RepairTodo> findList(RepairTodoListQuery query);
/**
* 生成待办
*/
RepairTodo generateTodo(Repair repair);
RepairTodo updateTodo(Repair repair);
/**
* 根据条件导出待办数据
*/
void exportTodo(RepairTodoListQuery query, HttpServletResponse response, String type) throws IOException;
RestResult<String> assign(RepairHandle repairHandle);
/**
* 添加生成下一步流程记录和更新表单和待办
*/
RestResult<String> generateNextHandle(RepairHandle repairHandle);
/**
* 根据申报账号查询统计的数据
*
* @param username
* @return
*/
Map<String, Integer> countRepairStepByUserId(String username);
RestResult<String> feedback(RepairHandle repairHandle, String fileHandleId);
/**
* 工程师查询自定导出表头列表
*/
Map<String, String> excelDevFields();
/**
* 业务人员查询自定导出表头列表
*/
Map<String, String> excelBusinessFields();
/**
* 运维单催单
*
* @param repairId
* @return
*/
RestResult<String> reminder(String repairId);
/**
* 根据权限查询用户列表
*/
IPage<RepairTodo> synthesizeBusinessList(RepairTodoListQuery query);
/**
* 工程师获取代办列表
*/
IPage<RepairTodo> findTodoByEngineer(RepairTodoListQuery query);
/**
* 业务人员获取代办列表
*/
IPage<RepairTodo> findTodoByBusiness(RepairTodoListQuery query);
IPage<RepairTodo> listByItemId(RepairTodoListQuery query, String itemId);
/**
* 导出统计项内容
*/
void exportListByItemId(HttpServletResponse response, RepairTodoListQuery query, String itemId, String type) throws IOException;
/**
* 综合查询
*/
IPage<RepairTodo> synthesizeEngineerList(RepairTodoListQuery query);
IPage<RepairTodo> leaderTodo(RepairTodoListQuery query);
/**
* 批量分派
* @param repairHandleList 运维单集合
* @return
*/
RestResult<String> batchAssign(List<RepairHandle> repairHandleList);
}

View File

@ -0,0 +1,537 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.repair.api.RobotApi;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.Notification;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.mapper.NotificationMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairHandleMapper;
import com.chinaweal.youfool.devops.repair.service.INotificationService;
import com.chinaweal.youfool.devops.repair.service.IRepairHandleService;
import com.chinaweal.youfool.devops.repair.service.IRepairSummaryService;
import com.chinaweal.youfool.devops.repair.service.IRepairTodoService;
import com.spire.xls.Workbook;
import com.spire.xls.Worksheet;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
/**
* <p>
* 通报 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-11-02
*/
@Service
public class NotificationServiceImpl extends ServiceImpl<NotificationMapper, Notification> implements INotificationService {
@Resource
private RepairHandleMapper repairHandleMapper;
@Resource
private RobotApi robotApi;
@Value("${file.devopsDir}")
private String devopsDir;
@Value("${noticeWebhookKeys}")
private String[] noticeWebhookKeys;
@Resource
private IRepairTodoService iRepairTodoService;
@Override
public void exportBulletinWord(LocalDate date, HttpServletResponse response) throws Exception {
date = date.with(TemporalAdjusters.firstDayOfMonth());
String templateDir = this.getClass().getResource("/word").getPath();
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDirectoryForTemplateLoading(new File(templateDir));
configuration.setDefaultEncoding("utf-8");
Template template = configuration.getTemplate("yunWeiTongGao.xml");
Map<String, Object> dataModel = new LinkedHashMap<>();
//日期
dataModel.put("year", date.getYear());
dataModel.put("month", date.getMonthValue());
dataModel.put("day", date.getDayOfMonth());
dataModel.put("currYear", LocalDate.now().getYear());
dataModel.put("currMonth", LocalDate.now().getMonthValue());
dataModel.put("currDay", LocalDate.now().getDayOfMonth());
unitSituation(dataModel, date);
// 设置下载文档名称
String fileName = new String(("佛山市市场监督管理局关于佛山市市场监管许可登记一体化系统" + date.getYear() + "年" + date.getMonthValue() + "月运维情况的通报").getBytes(StandardCharsets.UTF_8),
StandardCharsets.ISO_8859_1);
//设置:当浏览器收到这份资源的时候,以下载的方式提醒用户,而不是直接显示
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".doc\"");
Writer out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));
// 调用模板对象的process方法输出文件。
template.process(dataModel, out);
// 第八步:关闭流。
out.close();
}
@Override
public void makeData(LocalDate date) {
LocalDateTime start = LocalDateTime.of(date.with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MIN);
LocalDateTime end = LocalDateTime.of(date.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX);
List<String> orgNameList = IRepairSummaryService.getOrgNameList();
for (String org : orgNameList) {
Notification notification = new Notification();
notification.setOrg(org);
notification.setMonthDate(start.toLocalDate());
//获取历史数
RepairTodoListQuery query = new RepairTodoListQuery();
query.setLaunchTimeEnd(end);
query.setOrgListLike(Collections.singletonList(org));
BigDecimal historyTotal = repairHandleMapper.countStep(query, "total");
BigDecimal historyConfirmed = repairHandleMapper.countStep(query, "confirmed");
BigDecimal historyResolved = repairHandleMapper.countStep(query, "resolved");
BigDecimal historyUntreated = repairHandleMapper.countStep(query, "untreated");
notification.setHistoryTotal(historyTotal);
notification.setHistoryConfirmed(historyConfirmed);
notification.setHistoryResolved(historyResolved);
notification.setHistoryUntreated(historyUntreated);
//当前月
query.setLaunchTimeStart(start);
BigDecimal total = repairHandleMapper.countStep(query, "total");
BigDecimal confirmed = repairHandleMapper.countStep(query, "confirmed");
BigDecimal resolved = repairHandleMapper.countStep(query, "resolved");
BigDecimal untreated = repairHandleMapper.countStep(query, "untreated");
notification.setTotal(total);
notification.setConfirmed(confirmed);
notification.setResolved(resolved);
notification.setUntreated(untreated);
//处理次数
BigDecimal oneSuccess = repairHandleMapper.countResultSecond(query, 1);
BigDecimal twoSuccess = repairHandleMapper.countResultSecond(query, 2);
BigDecimal threeSuccess = repairHandleMapper.countResultSecond(query, 3);
notification.setOne(oneSuccess);
notification.setTwo(twoSuccess);
notification.setThree(threeSuccess);
//平均处理时长
Map<String, Object> avgFeedbackMap = repairHandleMapper.getAvgFeedbackTime(query);
BigDecimal feedbackHour = (BigDecimal) avgFeedbackMap.get("feedbackHour");
BigDecimal feedbackNumber = (BigDecimal) avgFeedbackMap.get("feedbackNumber");
BigDecimal avgHandle = feedbackNumber.compareTo(BigDecimal.valueOf(0)) > 0 ? feedbackHour.divide(feedbackNumber, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.valueOf(0);
notification.setAvgHandle(avgHandle);
//平均解决时长
Map<String, Object> avgResolvedMap = repairHandleMapper.getAvgResolvedTime(query);
BigDecimal resolvedHour = (BigDecimal) avgResolvedMap.get("resolvedHour");
BigDecimal resolvedNumber = (BigDecimal) avgResolvedMap.get("resolvedNumber");
BigDecimal avgResolved = resolvedNumber.compareTo(BigDecimal.valueOf(0)) > 0 ? resolvedHour.divide(resolvedNumber, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.valueOf(0);
notification.setAvgResolved(avgResolved);
save(notification);
}
}
@Override
public List<Map<String, Object>> findUnitData(LocalDate date) {
List<Map<String, Object>> list = new ArrayList<>();
List<String> orgNameList = IRepairSummaryService.getOrgNameList();
//本月
for (String org : orgNameList) {
LambdaQueryWrapper<Notification> lqw = Wrappers.lambdaQuery();
lqw.eq(Notification::getMonthDate, date);
lqw.eq(Notification::getOrg, org);
Notification notification = getOne(lqw, false);
//其中一个单位为空,跳出
if (notification == null) {
return new ArrayList<>();
}
Map<String, Object> map = new HashMap<>();
map.put("name", org);
map.put("total", notification.getTotal());
map.put("resolved", notification.getResolved());
map.put("feedback", notification.getConfirmed());
map.put("untreated", notification.getUntreated());
list.add(map);
}
return list;
}
@Override
public File createDayJournalXlsx(LocalDate date) {
Map<String, Object> data = new HashMap<>();
List<Map<String, Object>> handleList;//当天人员处理列表
List<Map<String, Object>> unhandledList = new ArrayList<>();//未处理运维单人员分布
//新增数
LambdaQueryWrapper<RepairTodo> lqwn = Wrappers.lambdaQuery();
lqwn.between(RepairTodo::getLaunchTime, date, date.plusDays(1));
int dailyNewly = iRepairTodoService.count(lqwn);
//已处理数
LambdaQueryWrapper<RepairTodo> lqwh = Wrappers.lambdaQuery();
lqwh.between(RepairTodo::getLaunchTime, date, date.plusDays(1));
lqwh.in(RepairTodo::getStep, IRepairHandleService.FEEDBACK, IRepairHandleService.RESOLVED);
int dailyHandled = iRepairTodoService.count(lqwh);
//未处理数
LambdaQueryWrapper<RepairTodo> lqwu = Wrappers.lambdaQuery();
lqwu.between(RepairTodo::getLaunchTime, date, date.plusDays(1));
lqwu.in(RepairTodo::getStep, IRepairHandleService.DECLARE, IRepairHandleService.ASSIGN, IRepairHandleService.HANDLE,
IRepairHandleService.UNRESOLVED);
int dailyUntreated = iRepairTodoService.count(lqwu);
//归档数
LambdaQueryWrapper<RepairTodo> lqwc = Wrappers.lambdaQuery();
lqwc.between(RepairTodo::getLaunchTime, date, date.plusDays(1));
lqwc.eq(RepairTodo::getStep, IRepairHandleService.RESOLVED);
int dailyConclude = iRepairTodoService.count(lqwc);
//待确认数
LambdaQueryWrapper<RepairTodo> lqwcf = Wrappers.lambdaQuery();
lqwcf.between(RepairTodo::getLaunchTime, date, date.plusDays(1));
lqwcf.eq(RepairTodo::getStep, IRepairHandleService.FEEDBACK);
int dailyConfirmed = iRepairTodoService.count(lqwcf);
data.put("date", date.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
data.put("createTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
data.put("dailyNewly", dailyNewly);//新增数
data.put("dailyHandled", dailyHandled);//已处理数
data.put("dailyUntreated", dailyUntreated);//未处理数
data.put("dailyConclude", dailyConclude);//归档数
data.put("dailyConfirmed", dailyConfirmed);//待确认数
data.put("dailyRate", percentage(BigDecimal.valueOf(dailyHandled), BigDecimal.valueOf(dailyNewly)));//处理完成率
//总量统计
LambdaQueryWrapper<RepairTodo> lqwT = Wrappers.lambdaQuery();
int total = iRepairTodoService.count(lqwT);
data.put("total", total);//运维单总数
LambdaQueryWrapper<RepairTodo> lqwTh = Wrappers.lambdaQuery();
lqwTh.in(RepairTodo::getStep, IRepairHandleService.FEEDBACK, IRepairHandleService.RESOLVED);
int handled = iRepairTodoService.count(lqwTh);
data.put("handled", handled);//已处理数
LambdaQueryWrapper<RepairTodo> lqwTu = Wrappers.lambdaQuery();
lqwTu.in(RepairTodo::getStep, IRepairHandleService.DECLARE, IRepairHandleService.ASSIGN, IRepairHandleService.HANDLE,
IRepairHandleService.UNRESOLVED);
int untreated = iRepairTodoService.count(lqwTu);
data.put("untreated", untreated);//未处理数
//当天人员处理列表
LambdaQueryWrapper<RepairTodo> lqwhl = Wrappers.lambdaQuery();
lqwhl.between(RepairTodo::getFeedbackTime, date, date.plusDays(1));
int dailyTotal = iRepairTodoService.count(lqwhl);//当天总处理量
handleList = baseMapper.dailyHandledUserNum(date, date.plusDays(1));
for (int i = 0; i < handleList.size(); i++) {
Map<String, Object> map = handleList.get(i);
map.put("index", i + 1);
map.put("rate", percentage((BigDecimal) map.get("num"), BigDecimal.valueOf(dailyTotal)));
}
//未处理运维单人员分布
LambdaQueryWrapper<RepairTodo> lqwul = Wrappers.lambdaQuery();
lqwul.in(RepairTodo::getStep, IRepairHandleService.DECLARE, IRepairHandleService.ASSIGN, IRepairHandleService.HANDLE,
IRepairHandleService.UNRESOLVED);
int utotal = iRepairTodoService.count(lqwul);//总量
unhandledList = baseMapper.unhandledUserNum();
for (int i = 0; i < unhandledList.size(); i++) {
Map<String, Object> map = unhandledList.get(i);
map.put("index", i + 1);
map.putIfAbsent("engineer", "待分派的单");
map.put("rate", percentage((BigDecimal) map.get("num"), BigDecimal.valueOf(utotal)));
}
String pathname = devopsDir + File.separator + "notification";
new File(pathname).mkdirs();
File file = new File(pathname + File.separator + date + ".xlsx");
//填充表格
String templateFileName = this.getClass().getClassLoader().getResource("template/daily-report.xlsx").getPath();
ExcelWriter excelWriter = EasyExcel.write(file).withTemplate(templateFileName).build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).direction(WriteDirectionEnum.VERTICAL).build();
WriteSheet summaryWriteSheet = EasyExcel.writerSheet("每日通报").build();
// 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1然后多个list必须用 FillWrapper包裹
excelWriter.fill(new FillWrapper("handleList", handleList), fillConfig, summaryWriteSheet);
excelWriter.fill(new FillWrapper("unhandledList", unhandledList), fillConfig, summaryWriteSheet);
excelWriter.fill(data, summaryWriteSheet);
// 别忘记关闭流
excelWriter.finish();
return file;
}
@Override
public void sendDayJournal(LocalDate date) throws IOException {
File file = createDayJournalXlsx(date);
Workbook workbook = new Workbook();
workbook.loadFromFile(file.getPath());
//设置x轴、y轴dpi
workbook.getConverterSetting().setXDpi(3000);
workbook.getConverterSetting().setYDpi(3000);
//获取第一张工作表
Worksheet sheet = workbook.getWorksheets().get("每日通报");
int lastRow = sheet.getLastRow();
int lastColumn = sheet.getLastColumn();
//保存到图片 注意当图片大小展示有问题时可以调整分辨为100%
BufferedImage bufferedImage = sheet.toImage(2, 2, lastRow, lastColumn);
//创建临时文件
File pngFile = File.createTempFile(file.getName(), ".png");
ImageIO.write(bufferedImage, "PNG", pngFile);
Map<String, Object> image = new HashMap<>();
FileInputStream inPng = new FileInputStream(pngFile);
byte[] bytes = IOUtils.toByteArray(inPng);
inPng.read(bytes);
String base64 = Base64.getEncoder().encodeToString(bytes);
String md5 = DigestUtils.md5Hex(bytes);
image.put("base64", base64);
image.put("md5", md5);
Map<String, Object> query = new HashMap<>();
query.put("msgtype", "image");
query.put("image", image);
for (String webhookKey : noticeWebhookKeys) {
Map<String, Object> data = robotApi.webhookSend(query, webhookKey);
}
inPng.close();
pngFile.delete();
}
/**
* 佛山通报各单位报障情况数据
*/
public void unitSituation(Map<String, Object> dataModel, LocalDate date) {
LocalDate monthDate = date.with(TemporalAdjusters.firstDayOfMonth());
LocalDate end = monthDate.with(TemporalAdjusters.lastDayOfMonth());
Map<String, String> orgMap = new LinkedHashMap<>();
orgMap.put("cityData", "佛山市市场监督管理局");
orgMap.put("chanChengData", "佛山市禅城区市场监督管理局");
orgMap.put("shunDeData", "佛山市顺德区市场监督管理局");
orgMap.put("gaoMingData", "佛山市高明区市场监督管理局");
orgMap.put("sanShuiData", "佛山市三水区市场监督管理局");
orgMap.put("nanHaiData", "佛山市南海区市场监督管理局");
BigDecimal sumTotal = new BigDecimal(0);
BigDecimal sumResolved = new BigDecimal(0);
BigDecimal sumUntreated = new BigDecimal(0);
BigDecimal sumConfirmed = new BigDecimal(0);
BigDecimal sumHistoryTotal = new BigDecimal(0);
BigDecimal sumHistoryConfirmed = new BigDecimal(0);
BigDecimal sumHistoryUntreated = new BigDecimal(0);
BigDecimal lastTotal = new BigDecimal(0);
BigDecimal lastResolved = new BigDecimal(0);
BigDecimal lastConfirmed = new BigDecimal(0);
BigDecimal lastUntreated = new BigDecimal(0);
BigDecimal lastHistoryUntreated = new BigDecimal(0);
BigDecimal lastHistoryTotal = new BigDecimal(0);
BigDecimal oneSuccess = new BigDecimal(0);
BigDecimal twoSuccess = new BigDecimal(0);
BigDecimal threeSuccess = new BigDecimal(0);
BigDecimal lastOneSuccess = new BigDecimal(0);
BigDecimal lastTwoSuccess = new BigDecimal(0);
BigDecimal lastThreeSuccess = new BigDecimal(0);
BigDecimal duration = new BigDecimal(0);
BigDecimal lastDuration = new BigDecimal(0);
//遍历各单位获取数据
for (Map.Entry<String, String> entry : orgMap.entrySet()) {
LambdaQueryWrapper<Notification> lqw = Wrappers.lambdaQuery();
lqw.eq(Notification::getMonthDate, monthDate);
lqw.eq(Notification::getOrg, entry.getValue());
//本月
Notification notification = getOne(lqw, false);
Map<String, Object> data = new LinkedHashMap<>();
data.put("total", notification.getTotal());
data.put("resolvedTotal", notification.getResolved());
data.put("resolvedProportion", percentage(notification.getResolved(), notification.getTotal()));
data.put("confirmedTotal", notification.getConfirmed());
data.put("confirmedProportion", percentage(notification.getConfirmed(), notification.getTotal()));
data.put("untreated", notification.getUntreated());
data.put("historyTotal", notification.getHistoryTotal());
data.put("historyConfirmed", notification.getHistoryConfirmed());
data.put("historyConfirmedProportion", percentage(notification.getHistoryConfirmed(), notification.getHistoryTotal()));
dataModel.put(entry.getKey(), data);
sumTotal = sumTotal.add(notification.getTotal());
sumResolved = sumResolved.add(notification.getResolved());
sumUntreated = sumUntreated.add(notification.getUntreated());
sumConfirmed = sumConfirmed.add(notification.getConfirmed());
sumHistoryTotal = sumHistoryTotal.add(notification.getHistoryTotal());
sumHistoryConfirmed = sumHistoryConfirmed.add(notification.getHistoryConfirmed());
sumHistoryUntreated = sumHistoryUntreated.add(notification.getHistoryUntreated());
oneSuccess = oneSuccess.add(notification.getOne());
twoSuccess = twoSuccess.add(notification.getTwo());
threeSuccess = threeSuccess.add(notification.getThree());
duration = duration.add(notification.getAvgHandle());
//上一月
lqw = Wrappers.lambdaQuery();
lqw.eq(Notification::getMonthDate, monthDate.minusMonths(1));
lqw.eq(Notification::getOrg, entry.getValue());
Notification lastNotification = getOne(lqw, false);
lastTotal = lastTotal.add(lastNotification.getTotal());
lastResolved = lastResolved.add(lastNotification.getResolved());
lastUntreated = lastUntreated.add(lastNotification.getUntreated());
lastConfirmed = lastConfirmed.add(lastNotification.getConfirmed());
lastHistoryUntreated = lastHistoryUntreated.add(lastNotification.getHistoryUntreated());
lastHistoryTotal = lastHistoryTotal.add(lastNotification.getHistoryTotal());
lastOneSuccess = lastOneSuccess.add(lastNotification.getOne());
lastTwoSuccess = lastTwoSuccess.add(lastNotification.getTwo());
lastThreeSuccess = lastThreeSuccess.add(lastNotification.getThree());
lastDuration = lastDuration.add(lastNotification.getAvgHandle());
}
//合计
Map<String, Object> allData = new LinkedHashMap<>();
allData.put("total", sumTotal);
allData.put("resolvedTotal", sumResolved);
allData.put("resolvedProportion", percentage(sumResolved, sumTotal));
allData.put("confirmedTotal", sumConfirmed);
allData.put("confirmedProportion", percentage(sumConfirmed, sumTotal));
allData.put("untreated", sumUntreated);
allData.put("historyTotal", sumHistoryTotal);
allData.put("historyConfirmed", sumHistoryConfirmed);
allData.put("historyConfirmedProportion", percentage(sumHistoryConfirmed, sumHistoryTotal));
dataModel.put("allData", allData);
//一、各单位报障情况
dataModel.put("reportTotal", sumTotal);
dataModel.put("average", sumTotal.divide(BigDecimal.valueOf(end.getDayOfMonth()), 1, BigDecimal.ROUND_HALF_UP));
dataModel.put("byMonth", date.getMonthValue());
dataModel.put("byDay", end.getDayOfMonth());
dataModel.put("processed", sumConfirmed.add(sumResolved));
dataModel.put("resolved", sumResolved);
dataModel.put("confirmed", sumConfirmed);
String processedProportion = percentage(sumConfirmed.add(sumResolved), sumTotal);
String lastProcessedProportion = percentage(lastConfirmed.add(lastResolved), lastTotal);
dataModel.put("processedProportion", processedProportion);
dataModel.put("untreated", sumUntreated);
// 上个月数据
String reportQoq = percentage(sumTotal.subtract(lastTotal), lastTotal);
dataModel.put("reportQoq", handleQoq(reportQoq));
dataModel.put("processedQoq", handleQoq(subtractPercentage(processedProportion, lastProcessedProportion)));
//二、众望通报障解决情况
String untreatedProportion = percentage(sumUntreated, sumTotal);
String lastUntreatedProportion = percentage(lastUntreated, lastTotal);
dataModel.put("untreatedProportion", untreatedProportion);
dataModel.put("untreatedQoq", handleQoq(subtractPercentage(untreatedProportion, lastUntreatedProportion)));
dataModel.put("historyTotal", sumHistoryTotal);
dataModel.put("historyUntreated", sumHistoryUntreated);
String historyUntreatedProportion = percentage(sumHistoryUntreated, sumHistoryTotal);
dataModel.put("historyUntreatedProportion", historyUntreatedProportion);
String lastHistoryUntreatedProportion = percentage(lastHistoryUntreated, lastHistoryTotal);
dataModel.put("historyUntreatedQoq", handleQoq(subtractPercentage(historyUntreatedProportion, lastHistoryUntreatedProportion)));
BigDecimal handleTotal = oneSuccess.add(twoSuccess).add(threeSuccess);
//上一个月的
BigDecimal lastHandleTotal = lastOneSuccess.add(lastTwoSuccess).add(lastThreeSuccess);
//一次处理
Map<String, Object> oneHandle = new LinkedHashMap<>();
oneHandle.put("total", oneSuccess);
String oneProportion = percentage(oneSuccess, handleTotal);
String oneLastProportion = percentage(lastOneSuccess, lastHandleTotal);
oneHandle.put("proportion", oneProportion);
oneHandle.put("lastProportion", oneLastProportion);
String oneQoq = subtractPercentage(oneProportion, oneLastProportion);
oneHandle.put("qoq", handleQoq(oneQoq));
oneHandle.put("qoqTable", oneQoq);
dataModel.put("oneHandle", oneHandle);
//二次处理
Map<String, Object> twoHandle = new LinkedHashMap<>();
twoHandle.put("total", twoSuccess);
String twoProportion = percentage(twoSuccess, handleTotal);
String twoLastProportion = percentage(lastTwoSuccess, lastHandleTotal);
twoHandle.put("proportion", twoProportion);
twoHandle.put("lastProportion", twoLastProportion);
String twoQoq = subtractPercentage(twoProportion, twoLastProportion);
twoHandle.put("qoq", handleQoq(twoQoq));
twoHandle.put("qoqTable", twoQoq);
dataModel.put("twoHandle", twoHandle);
//三次处理
Map<String, Object> threeHandle = new LinkedHashMap<>();
threeHandle.put("total", threeSuccess);
String threeProportion = percentage(threeSuccess, handleTotal);
String threeLastProportion = percentage(lastThreeSuccess, lastHandleTotal);
threeHandle.put("proportion", threeProportion);
threeHandle.put("lastProportion", threeLastProportion);
String treeQoq = subtractPercentage(threeProportion, threeLastProportion);
threeHandle.put("qoq", handleQoq(treeQoq));
threeHandle.put("qoqTable", treeQoq);
dataModel.put("threeHandle", threeHandle);
//各单位平均时长累加还要除于单位数据
duration = duration.divide(BigDecimal.valueOf(orgMap.size()), 2, BigDecimal.ROUND_HALF_UP);
lastDuration = lastDuration.divide(BigDecimal.valueOf(orgMap.size()), 2, BigDecimal.ROUND_HALF_UP);
dataModel.put("duration", duration);
BigDecimal durationAvg = duration.divide(BigDecimal.valueOf(24), 1, BigDecimal.ROUND_HALF_UP);
BigDecimal lastDurationAvg = lastDuration.divide(BigDecimal.valueOf(24), 1, BigDecimal.ROUND_HALF_UP);
dataModel.put("durationAvg", durationAvg.stripTrailingZeros().toPlainString());
String durationQoq = percentage(durationAvg.subtract(lastDurationAvg), lastDurationAvg);
dataModel.put("durationQoq", handleQoq(durationQoq));
dataModel.put("handleTotal", handleTotal);
}
private String percentage(BigDecimal molecule, BigDecimal divisor) {
if (divisor.compareTo(BigDecimal.valueOf(0)) <= 0) {
return "0%";
}
return molecule.multiply(BigDecimal.valueOf(100)).divide(divisor, 1, BigDecimal.ROUND_HALF_UP) + "%";
}
private String subtractPercentage(String minuendStr, String subtrahendStr) {
BigDecimal minuend = new BigDecimal(minuendStr.replace("%", ""));
BigDecimal subtrahend = new BigDecimal(subtrahendStr.replace("%", ""));
return minuend.subtract(subtrahend) + "%";
}
/**
* 处理环比改成增加或减少
*/
private String handleQoq(String qoq) {
return qoq.startsWith("-") ? "减少" + qoq.substring(1) : "增加" + qoq;
}
}

View File

@ -0,0 +1,156 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.repair.entity.RepairFile;
import com.chinaweal.youfool.devops.repair.mapper.RepairFileMapper;
import com.chinaweal.youfool.devops.repair.service.IRepairFileService;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* <p>
* 运维报障附件 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Service
@Slf4j
public class RepairFileServiceImpl extends ServiceImpl<RepairFileMapper, RepairFile> implements IRepairFileService {
@Value("${file.devopsDir}")
private String devopsDir;
@Override
public Map<String, String> loadFile(MultipartFile multipartFile, String repairId, String type, String tempHandleId) throws IOException {
RepairFile repairFile = new RepairFile();
repairFile.setRepairId(StringUtils.isNotBlank(repairId) ? repairId : UUID.randomUUID().toString().replace("-", ""));
repairFile.setFileName(multipartFile.getOriginalFilename());
repairFile.setFileType(multipartFile.getContentType());
repairFile.setType(type);
repairFile.setHandleId(tempHandleId);
repairFile.setUploadTime(LocalDateTime.now());
int i = multipartFile.getOriginalFilename().lastIndexOf(".");
String filePathName = UUID.randomUUID().toString();
if (i > 0) {
filePathName += multipartFile.getOriginalFilename().substring(i);
}
repairFile.setFilePath(filePathName);
File dir = new File(devopsDir);
dir.mkdirs();
File file = new File(devopsDir + File.separator + filePathName);
try (InputStream is = multipartFile.getInputStream();) {
if (StringUtils.containsIgnoreCase(multipartFile.getContentType(), "image")
&& multipartFile.getSize() >= 2 * 1024 * 1024) { // 大于2M进行压缩
//压缩图片
TimeInterval timer = DateUtil.timer();
Thumbnails.of(is).scale(1f).outputQuality(0.5f).toFile(file);
log.debug("图片压缩耗时: {} ms", timer.interval());
} else {
multipartFile.transferTo(file);
}
} catch (IOException e) {
log.error("上传出错", e);
throw new RuntimeException(e.getMessage());
}
repairFile.setFileSize(file.length());
save(repairFile);
Map<String, String> body = new LinkedHashMap<>();
body.put("uuid", repairFile.getUuid());
body.put("repairId", repairFile.getRepairId());
return body;
}
@Override
public void updateRepairAndHandleIdByTempRepairId(String tempRepairId, String repairId, String handleId) {
LambdaUpdateWrapper<RepairFile> qw = new LambdaUpdateWrapper<>();
qw.eq(RepairFile::getRepairId, tempRepairId)
.set(RepairFile::getRepairId, repairId)
.set(RepairFile::getHandleId, handleId);
update(qw);
}
@Override
public void updateHandleIdByTempHandleId(String tempHandleId, String handleId) {
LambdaUpdateWrapper<RepairFile> qw = new LambdaUpdateWrapper<>();
qw.eq(RepairFile::getHandleId, tempHandleId)
.set(RepairFile::getHandleId, handleId);
update(qw);
}
@Override
public List<RepairFile> listByRepairId(String repairId) {
LambdaQueryWrapper<RepairFile> qw = new LambdaQueryWrapper<>();
qw.eq(RepairFile::getRepairId, repairId)
.orderByAsc(RepairFile::getUploadTime);
return list(qw);
}
@Override
public void downloadFile(String uuid, boolean online, HttpServletResponse response) throws IOException {
RepairFile repairFile = getById(uuid);
if (repairFile == null) {
return;
}
//拼接绝对路径,获取流
InputStream is;
try {
is = new FileInputStream(devopsDir + "/" + repairFile.getFilePath());
} catch (FileNotFoundException e) {
log.warn(e.getMessage());
return;
}
OutputStream os = response.getOutputStream();
String fileName = new String(repairFile.getFileName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
if (online) {
//直接展示
response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
} else {
//设置:当浏览器收到这份资源的时候,以下载的方式提醒用户,而不是直接显示
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
}
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.close();
is.close();
}
@Override
public void deleteFile(String uuid) {
RepairFile repairFile = getById(uuid);
if (repairFile == null) {
return;
}
File file = new File(devopsDir + "/" + repairFile.getFilePath());
if (file.exists()) {
file.delete();
}
removeById(repairFile);
}
}

View File

@ -0,0 +1,99 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.mapper.RepairHandleMapper;
import com.chinaweal.youfool.devops.repair.service.IRepairFileService;
import com.chinaweal.youfool.devops.repair.service.IRepairHandleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.repair.service.IRepairTodoService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维报障处理流程记录 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Service
public class RepairHandleServiceImpl extends ServiceImpl<RepairHandleMapper, RepairHandle> implements IRepairHandleService {
@Resource
private RepairHandleMapper repairHandleMapper;
@Resource
private IRepairTodoService iRepairTodoService;
@Resource
private IRepairFileService iRepairFileService;
@Override
public synchronized RepairHandle updateByRepairIdHandleTodo(RepairHandle repairHandle) {
LambdaUpdateWrapper<RepairHandle> qw = new LambdaUpdateWrapper<>();
qw.eq(RepairHandle::getRepairId, repairHandle.getRepairId()).eq(RepairHandle::getStatus, "1")
.set(RepairHandle::getStatus, "0");
//失效以前的流程记录
update(qw);
//插入新的流程记录
//todo 自动获取用户信息
repairHandle.setHandleId(null);
repairHandle.setHappenTime(LocalDateTime.now());
repairHandle.setStatus("1");
save(repairHandle);
return repairHandle;
}
@Override
public List<RepairHandle> listByRepairId(String repairId) {
LambdaQueryWrapper<RepairHandle> qw = new LambdaQueryWrapper<>();
qw.eq(RepairHandle::getRepairId, repairId).orderByAsc(RepairHandle::getHappenTime);
return list(qw);
}
@Override
public RepairHandle getCurrentHandle(String repairId) {
LambdaQueryWrapper<RepairHandle> qw = new LambdaQueryWrapper<>();
qw.eq(RepairHandle::getRepairId, repairId).eq(RepairHandle::getStatus, "1");
return getOne(qw);
}
@Override
public RestResult<String> unresolvedHandle(RepairHandle repairHandle, String tempHandleId) {
//查询待办是否存在
RepairTodo repairTodo = iRepairTodoService.getByRepairId(repairHandle.getRepairId());
if (repairTodo == null) {
return RestResult.error(ResultCode.USCID_INVALID, "找不到对应的运维报障数据");
}
//插入流程表
repairHandle.setTodoId(repairTodo.getTodoId());
repairHandle.setStep(UNRESOLVED);
repairHandle = updateByRepairIdHandleTodo(repairHandle);
//更改待办记录
repairTodo.setHandleTime(repairHandle.getHappenTime());
repairTodo.setStep(UNRESOLVED);
iRepairTodoService.updateById(repairTodo);
//关联附件
iRepairFileService.updateHandleIdByTempHandleId(tempHandleId, repairHandle.getHandleId());
return RestResult.ok(repairHandle.getHandleId());
}
}

View File

@ -0,0 +1,64 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.chinaweal.youfool.devops.base.entity.Dict;
import com.chinaweal.youfool.devops.base.service.IDictService;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairLabel;
import com.chinaweal.youfool.devops.repair.mapper.RepairLabelMapper;
import com.chinaweal.youfool.devops.repair.service.IRepairLabelService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 运维单标签 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-07-10
*/
@Service
public class RepairLabelServiceImpl extends ServiceImpl<RepairLabelMapper, RepairLabel> implements IRepairLabelService {
@Resource
private RepairLabelMapper repairLabelMapper;
@Resource
private IDictService iDictService;
@Override
public List<Map<String, String>> listLabel() {
List<Map<String, String>> maps = repairLabelMapper.listLabelOrder();
Map<String, Map<String, String>> labels = new LinkedHashMap<>();
for (Map<String, String> map : maps) {
String name = map.get("name");
Map<String, String> labelMap = new LinkedHashMap<>();
labelMap.put("name", name);
labelMap.put("value", name);
labels.put(name, labelMap);
}
//查询基础数据去重并,合并起来
List<Dict> dicts = iDictService.listByType(IDictService.LABEL);
for (Dict dict : dicts) {
boolean b = labels.containsKey(dict.getCode());
if (!b) {
Map<String, String> labelMap = new LinkedHashMap<>();
labelMap.put("name", dict.getName());
labelMap.put("value", dict.getCode());
labels.put(dict.getCode(), labelMap);
}
}
return new ArrayList<>(labels.values());
}
@Override
public List<Map<String, Object>> groupLabelCount(RepairTodoListQuery query) {
List<Map<String, Object>> labels = repairLabelMapper.groupNameCount(query);
return labels;
}
}

View File

@ -0,0 +1,483 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.base.service.IDictService;
import com.chinaweal.youfool.devops.org.business.entity.BusinessUser;
import com.chinaweal.youfool.devops.org.business.service.BusinessUserService;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.*;
import com.chinaweal.youfool.devops.repair.mapper.RepairHandleMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairLabelMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairTodoMapper;
import com.chinaweal.youfool.devops.repair.service.*;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>
* 运维报障信息 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Service
@Slf4j
public class RepairServiceImpl extends ServiceImpl<RepairMapper, Repair> implements IRepairService {
@Resource
private IDictService iDictService;
@Resource
private IRepairHandleService iRepairHandleService;
@Resource
private IRepairFileService iRepairFileService;
@Resource
private IRepairTodoService iRepairTodoService;
@Resource
private RepairTodoMapper repairTodoMapper;
@Resource
private RepairHandleMapper repairHandleMapper;
@Resource
private RepairLabelMapper repairLabelMapper;
@Resource
private IRepairLabelService iRepairLabelService;
@Resource
private BusinessUserService businessUserService;
@Override
public RestResult<String> saveRepair(Repair repair) {
//判断来源
if ("2".equals(repair.getSource())) {
repair.setOrgId("特设网办系统");
repair.setOrg("特设网办系统");
} else if ("3".equals(repair.getSource())) {
repair.setOrgId("佛山年报系统");
repair.setOrg("佛山年报系统");
} else if ("4".equals(repair.getSource())) {
repair.setOrgId("佛山行政执法办案平台");
repair.setOrg("佛山行政执法办案平台");
} else if ("5".equals(repair.getSource())) {
repair.setOrgId("佛山消保系统");
repair.setOrg("佛山消保系统");
} else {
//内网发起,查询业务系统的用户信息
BusinessUser user;
if (StringUtils.isNotBlank(repair.getUserId())) {
user = businessUserService.getById(repair.getUserId());
} else {
user = businessUserService.getByUsername(repair.getUsername());
}
if (user == null) {
return RestResult.error(ResultCode.USCID_INVALID, "找不到申报账号信息");
}
repair.setUserId(user.getUserId());
repair.setUsername(user.getUsername());
repair.setDeptId(user.getUnitId());
repair.setDept(user.getUnitName());
repair.setOrgId(user.getOrgId());
repair.setOrg(user.getOrgName());
repair.setNickname(user.getNickname());
if (StringUtils.isBlank(repair.getPhone())) {
repair.setPhone(user.getMobile());
}
repair.setSource("1");//内网
}
String oldRepairUUID = repair.getRepairId();
String repairId = generateRepairId();
repair.setRepairId(repairId);
repair.setLaunchTime(LocalDateTime.now());
save(repair);
//生成待办
RepairTodo repairTodo = iRepairTodoService.generateTodo(repair);
//初始化流程记录
RepairHandle repairHandle = new RepairHandle(repairTodo.getTodoId(), repairTodo.getRepairId(), repairTodo.getStep(),
repair.getUsername(), repair.getNickname(), null);
repairHandle = iRepairHandleService.updateByRepairIdHandleTodo(repairHandle);
//判断是否有附件上传的工单更新附件的运维ID
if (StringUtils.isNotBlank(oldRepairUUID)) {
iRepairFileService.updateRepairAndHandleIdByTempRepairId(oldRepairUUID, repair.getRepairId(), repairHandle.getHandleId());
}
//判断标签是否已经入库了,否则重新入库
if (StringUtils.isNotBlank(repair.getBusClassify())) {
iDictService.saveNameByTypeCode("busClassify", repair.getBusClassify(), repair.getBusClassify());
}
if (StringUtils.isNotBlank(repair.getBusStep())) {
iDictService.saveNameByTypeCode("busStep", repair.getBusStep(), repair.getBusStep());
}
return RestResult.ok(repair.getRepairId());
}
private synchronized String generateRepairId() {
String prefix = "YW" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//查询当天有多少条工单
LambdaQueryWrapper<Repair> qw = new LambdaQueryWrapper<>();
qw.ge(Repair::getLaunchTime, LocalDate.now().atStartOfDay())
.lt(Repair::getLaunchTime, LocalDate.now().atStartOfDay().plusDays(1));
int count = count(qw) + 1;
//补齐零
String no = String.format("%04d", count);
String repairId = prefix + no;
Repair repair = getById(repairId);
//效验运维单号的序号唯一不
int max = 10;
while (repair != null && max != 0) {
log.warn("效验运维单号的序号有重复的,请注意检查数据!重复单号:{}", repairId);
count++;
max--;
no = String.format("%04d", count);
repairId = prefix + no;
repair = getById(repairId);
}
return repairId;
}
@Override
public RestResult<String> updateRepair(Repair repair) {
updateById(repair);
iRepairTodoService.updateTodo(repair);
//判断标签是否已经入库了,否则重新入库
if (StringUtils.isNotBlank(repair.getBusClassify())) {
iDictService.saveNameByTypeCode("busClassify", repair.getBusClassify(), repair.getBusClassify());
}
if (StringUtils.isNotBlank(repair.getBusStep())) {
iDictService.saveNameByTypeCode("busStep", repair.getBusStep(), repair.getBusStep());
}
return RestResult.ok(repair.getRepairId());
}
@Override
public Repair getRepair(String repairId) {
Repair repair = getById(repairId);
//文件列表
List<RepairFile> listFile = iRepairFileService.listByRepairId(repair.getRepairId());
repair.setQuestionFiles(listFile.stream().filter(item -> "question".equals(item.getType())).collect(Collectors.toList()));
repair.setAnswerFiles(listFile.stream().filter(item -> "answer".equals(item.getType())).collect(Collectors.toList()));
//流程记录
List<RepairHandle> listRepairHandle = iRepairHandleService.listByRepairId(repair.getRepairId());
//获取流程记录的附件列表
for (RepairHandle repairHandle : listRepairHandle) {
LambdaQueryWrapper<RepairFile> rfQw = new LambdaQueryWrapper<>();
rfQw.eq(RepairFile::getHandleId, repairHandle.getHandleId());
List<RepairFile> files = iRepairFileService.list(rfQw);
repairHandle.setFiles(files);
}
repair.setRepairHandles(listRepairHandle);
//获取当前状态流程
RepairHandle currentHandle = iRepairHandleService.getCurrentHandle(repair.getRepairId());
LambdaQueryWrapper<RepairFile> rfQw = new LambdaQueryWrapper<>();
rfQw.eq(RepairFile::getHandleId, currentHandle.getHandleId());
List<RepairFile> files = iRepairFileService.list(rfQw);
currentHandle.setFiles(files);
repair.setCurrentHandle(currentHandle);
//查询待办信息
RepairTodo repairTodo = iRepairTodoService.getByRepairId(repairId);
repair.setRepairTodo(repairTodo);
//查询标签
List<String> labels = repairLabelMapper.listNameByRepairId(repairId);
repair.setLabels(labels);
return repair;
}
@Override
public void updateLabelByType(List<String> repairIds, String labelType, String labelName) {
//判断标签是否入库字典表了,否则新入库
iDictService.saveNameByTypeCode(labelType, labelName, labelName);
LambdaUpdateWrapper<Repair> rqw = new LambdaUpdateWrapper<>();
rqw.in(Repair::getRepairId, repairIds);
if ("busClassify".equals(labelType)) {
rqw.set(Repair::getBusClassify, labelName);
} else if ("busStep".equals(labelType)) {
rqw.set(Repair::getBusStep, labelName);
} else {
return;
}
update(rqw);
}
@Override
public List<Map<String, Object>> sumSummary(RepairTodoListQuery query) {
List<Map<String, Object>> list = new LinkedList<>();
BigDecimal total = repairHandleMapper.countStep(query, "total");
BigDecimal resolved = repairHandleMapper.countStep(query, "resolved");
BigDecimal untreated = repairHandleMapper.countStep(query, "untreated");
BigDecimal confirmed = repairHandleMapper.countStep(query, "confirmed");
//报障总数量
Map<String, Object> totalData = new LinkedHashMap<>();
totalData.put("id", "total");
totalData.put("name", "报障总数");
totalData.put("value", total);
//已处理报障数量(已解决)
Map<String, Object> feedbackData = new LinkedHashMap<>();
feedbackData.put("id", "resolved");
feedbackData.put("name", "已归档");
feedbackData.put("value", resolved);
//未处理报障数量
Map<String, Object> untreatedData = new LinkedHashMap<>();
untreatedData.put("id", "untreated");
untreatedData.put("name", "未处理");
untreatedData.put("value", untreated);
//待报障单位确认的报障数量
Map<String, Object> confirmedData = new LinkedHashMap<>();
confirmedData.put("id", "confirmed");
confirmedData.put("name", "已处理待确认");
confirmedData.put("value", confirmed);
//故障处理率
Map<String, Object> processRaterDate = new LinkedHashMap<>();
processRaterDate.put("id", "processRate");
processRaterDate.put("name", "故障处理率(已确认)");
processRaterDate.put("value", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (resolved.multiply(BigDecimal.valueOf(100))
.divide(total, 2, BigDecimal.ROUND_HALF_UP) + "%") : 0);
//已解决+待确认 故障处理率
Map<String, Object> confirmedProcessRaterDate = new LinkedHashMap<>();
confirmedProcessRaterDate.put("id", "confirmedProcessRate");
confirmedProcessRaterDate.put("name", "故障处理率(已确认+待确认)");
confirmedProcessRaterDate.put("value", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (resolved.add(confirmed).multiply(BigDecimal.valueOf(100))
.divide(total, 2, BigDecimal.ROUND_HALF_UP) + "%") : 0);
//处理故障数量
BigDecimal oneSuccess = repairHandleMapper.countResultSecond(query, 1);
BigDecimal twoSuccess = repairHandleMapper.countResultSecond(query, 2);
BigDecimal threeSuccess = repairHandleMapper.countResultSecond(query, 3);
BigDecimal handleTotal = oneSuccess.add(twoSuccess).add(threeSuccess);
Map<String, Object> one = new LinkedHashMap<>();
one.put("id", "oneSuccess");
one.put("name", "处理故障1次成功数量");
one.put("value", oneSuccess);
Map<String, Object> oneRate = new LinkedHashMap<>();
oneRate.put("id", "oneSuccessRate");
oneRate.put("name", "处理故障1次成功率");
oneRate.put("value", handleTotal.compareTo(BigDecimal.valueOf(0)) > 0 ? (oneSuccess.multiply(BigDecimal.valueOf(100))
.divide(handleTotal, 2, BigDecimal.ROUND_HALF_UP) + "%") : 0);
Map<String, Object> two = new LinkedHashMap<>();
two.put("id", "twoSuccess");
two.put("name", "处理故障2次成功数量");
two.put("value", twoSuccess);
Map<String, Object> twoRate = new LinkedHashMap<>();
twoRate.put("id", "twoSuccessRate");
twoRate.put("name", "处理故障2次成功率");
twoRate.put("value", handleTotal.compareTo(BigDecimal.valueOf(0)) > 0 ? (twoSuccess.multiply(BigDecimal.valueOf(100))
.divide(handleTotal, 2, BigDecimal.ROUND_HALF_UP) + "%") : 0);
Map<String, Object> three = new LinkedHashMap<>();
three.put("id", "threeSuccess");
three.put("name", "处理故障3次及以上成功数量");
three.put("value", threeSuccess);
Map<String, Object> threeRate = new LinkedHashMap<>();
threeRate.put("id", "threeSuccessRate");
threeRate.put("name", "处理故障3次及以上成功率");
threeRate.put("value", handleTotal.compareTo(BigDecimal.valueOf(0)) > 0 ? (threeSuccess.multiply(BigDecimal.valueOf(100))
.divide(handleTotal, 2, BigDecimal.ROUND_HALF_UP) + "%") : 0);
Map<String, Object> avgResolvedMap = repairHandleMapper.getAvgResolvedTime(query);
Map<String, Object> avgResolvedTime = new LinkedHashMap<>();
BigDecimal resolvedHour = (BigDecimal) avgResolvedMap.get("resolvedHour");
BigDecimal resolvedNumber = (BigDecimal) avgResolvedMap.get("resolvedNumber");
avgResolvedTime.put("id", "avgResolvedTime");
avgResolvedTime.put("name", "故障平均解决时长");
avgResolvedTime.put("value", resolvedNumber.compareTo(BigDecimal.valueOf(0)) > 0 ? (resolvedHour.divide(resolvedNumber, 2, BigDecimal.ROUND_HALF_UP)) + " 小时" : 0);
Map<String, Object> avgFeedbackMap = repairHandleMapper.getAvgFeedbackTime(query);
Map<String, Object> avgFeedbackTime = new LinkedHashMap<>();
BigDecimal feedbackHour = (BigDecimal) avgFeedbackMap.get("feedbackHour");
BigDecimal feedbackNumber = (BigDecimal) avgFeedbackMap.get("feedbackNumber");
avgFeedbackTime.put("id", "avgFeedbackTime");
avgFeedbackTime.put("name", "故障平均处理时长");
avgFeedbackTime.put("value", feedbackNumber.compareTo(BigDecimal.valueOf(0)) > 0 ? (feedbackHour.divide(feedbackNumber, 2, BigDecimal.ROUND_HALF_UP)) + " 小时" : 0);
list.add(totalData);
list.add(feedbackData);
list.add(untreatedData);
list.add(confirmedData);
list.add(one);
list.add(two);
list.add(three);
list.add(avgFeedbackTime);
list.add(avgResolvedTime);
list.add(processRaterDate);
list.add(confirmedProcessRaterDate);
list.add(oneRate);
list.add(twoRate);
list.add(threeRate);
return list;
}
@Override
public List<Map<String, Object>> sumBusLabelByType(RepairTodoListQuery query, String labelType) {
List<Map<String, Object>> list = new LinkedList<>();
List<Map<String, Object>> labelList = null;
if ("labelBusClassify".equals(labelType)) {
labelList = repairTodoMapper.groupByBusClassifyCount(query);
} else if ("labelBusStep".equals(labelType)) {
labelList = repairTodoMapper.groupByBusStepCount(query);
}
for (Map<String, Object> map : labelList) {
String name = (String) map.get("name");
BigDecimal num = (BigDecimal) map.get("num");
Map<String, Object> data = new LinkedHashMap<>();
data.put("id", labelType + name);
data.put("name", name);
data.put("value", num);
list.add(data);
}
return list;
}
@Override
public void exportSumSummary(RepairTodoListQuery query, HttpServletResponse response) throws IOException {
String fileName = new String(("报障统计汇总.xlsx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
OutputStream os = response.getOutputStream();
String templateFileName = this.getClass().getResource("/excel/tongjineirongxiang.xlsx").getPath();
ExcelWriter excelWriter = EasyExcel.write(os).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
excelWriter.fill(sumSummary(query), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<>();
//处理时间
if (query.getLaunchTimeStart() != null) {
String start = query.getLaunchTimeStart().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
String end = query.getLaunchTimeEnd().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
map.put("date", start + " 至 " + end);
} else {
map.put("date", "全部");
}
if (query.getOrgListLike() != null && !query.getOrgListLike().isEmpty()) {
map.put("org", Strings.join(query.getOrgListLike(), '、'));
} else {
map.put("org", "全市");
}
List<Map<String, Object>> labelBusClassify = sumBusLabelByType(query, "labelBusClassify");
excelWriter.fill(new FillWrapper("labelBusClassify", labelBusClassify), fillConfig, writeSheet);
List<Map<String, Object>> labelBusStep = sumBusLabelByType(query, "labelBusStep");
excelWriter.fill(new FillWrapper("labelBusStep", labelBusStep), fillConfig, writeSheet);
excelWriter.fill(map, writeSheet);
excelWriter.finish();
}
@Override
public void updateDevInfo(Map<String, Object> map) {
String repairId = (String) map.get("repairId");
String leaderUsername = (String) map.get("leaderUsername");
String leaderNickname = (String) map.get("leaderNickname");
String questionType = (String) map.get("questionType");
Integer priority = (Integer) map.get("priority");
String thinking = (String) map.get("thinking");
String plannedTimeStr = (String) map.get("plannedTime");
String realityTimeStr = (String) map.get("realityTime");
List<String> labels = (List<String>) map.get("labels");
Repair repair = getRepair(repairId);
if (StringUtils.isNotBlank(plannedTimeStr)) {
LocalDateTime plannedTime = LocalDateTime.parse(plannedTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
repair.setPlannedTime(plannedTime);
}
if (StringUtils.isNotBlank(realityTimeStr)) {
LocalDateTime realityTime = LocalDateTime.parse(realityTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
repair.setRealityTime(realityTime);
}
if (repair == null) {
return;
}
repair.setLeaderUsername(leaderUsername);
repair.setLeaderNickname(leaderNickname);
repair.setQuestionType(questionType);
repair.setPriority(priority);
repair.setThinking(thinking);
//标签字符全量插入
if (labels != null) {
repair.setLabel(String.join(",", labels));
}
updateById(repair);
//待办列表
RepairTodo repairTodo = iRepairTodoService.getByRepairId(repairId);
repairTodo.setPriority(priority);
iRepairTodoService.updateById(repairTodo);
//删除旧的标签
LambdaQueryWrapper<RepairLabel> qw = new LambdaQueryWrapper<>();
qw.eq(RepairLabel::getRepairId, repair.getRepairId());
iRepairLabelService.remove(qw);
//全量问题标签全量插入
if (labels != null) {
for (String label : labels) {
RepairLabel repairLabel = new RepairLabel();
repairLabel.setName(label);
repairLabel.setRepairId(repair.getRepairId());
iRepairLabelService.save(repairLabel);
}
}
}
}

View File

@ -0,0 +1,111 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chinaweal.youfool.devops.base.entity.Dict;
import com.chinaweal.youfool.devops.base.service.IDictService;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.RepairSummary;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.mapper.RepairHandleMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairSummaryMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairTodoMapper;
import com.chinaweal.youfool.devops.repair.service.IRepairSummaryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.repair.service.IRepairTodoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import static com.chinaweal.youfool.devops.repair.service.IRepairHandleService.FEEDBACK;
/**
* <p>
* 运维报障统计汇总 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-08-13
*/
@Service
public class RepairSummaryServiceImpl extends ServiceImpl<RepairSummaryMapper, RepairSummary> implements IRepairSummaryService {
@Resource
private RepairTodoMapper repairTodoMapper;
@Resource
private RepairHandleMapper repairHandleMapper;
@Resource
private RepairMapper repairMapper;
@Resource
private IDictService iDictService;
@Override
public void sumAllOrgByDay(LocalDate day) {
List<RepairSummary> list = new ArrayList<>();
LocalDateTime startTime = day.atStartOfDay();
LocalDateTime endTime = startTime.plusDays(1).minusSeconds(1);
for (String orgName : IRepairSummaryService.getOrgNameList()) {
//报障数
Long reportTotal = repairTodoMapper.countByLaunchTimeAndLikeOrg(startTime, endTime, Collections.singletonList(orgName));
//业务数 todo
//处理数
Long handleTotal = repairHandleMapper.countDistinctByTimeAndOrgAndStep(startTime, endTime, Collections.singletonList(orgName), FEEDBACK);
RepairSummary repairSummary = new RepairSummary();
repairSummary.setOrg(orgName);
repairSummary.setType(ORG);
repairSummary.setTime(startTime);
repairSummary.setReportTotal(BigDecimal.valueOf(reportTotal));
repairSummary.setHandleTotal(BigDecimal.valueOf(handleTotal));
repairSummary.setBusTotal(BigDecimal.valueOf(0));// TODO: 2020/8/14
list.add(repairSummary);
}
saveBatch(list);
}
@Override
public void sumAllOrgAndGroupQuestionByDay(LocalDate day) {
List<RepairSummary> list = new ArrayList<>();
LocalDateTime startTime = day.atStartOfDay();
LocalDateTime endTime = startTime.plusDays(1).minusSeconds(1);
//获取问题分类基础数据
List<Dict> dicts = iDictService.listByType(IDictService.QUESTION);
List<String> questions = dicts.stream().map(Dict::getName).collect(Collectors.toList());
for (String orgName : IRepairSummaryService.getOrgNameList()) {
//分组问题分类 的报障数
RepairTodoListQuery query = new RepairTodoListQuery();
query.setOrgListLike(Collections.singletonList(orgName));
query.setLaunchTimeStart(startTime);
query.setLaunchTimeEnd(endTime);
//遍历问题分类
for (String question : questions) {
query.setQuestionType(question);
BigDecimal number = repairMapper.countByQuestionType(query);
RepairSummary repairSummary = new RepairSummary();
repairSummary.setOrg(orgName);
repairSummary.setType(ORG_QUESTION);
repairSummary.setTime(startTime);
repairSummary.setReportTotal(number);
repairSummary.setQuestionType(question);
list.add(repairSummary);
}
}
//删除旧的历史记录
LambdaQueryWrapper<RepairSummary> lqw = new LambdaQueryWrapper<>();
lqw.ge(RepairSummary::getTime, startTime).le(RepairSummary::getTime, endTime);
lqw.eq(RepairSummary::getType, ORG_QUESTION);
remove(lqw);
saveBatch(list);
}
}

View File

@ -0,0 +1,717 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.youfool.devops.org.business.service.BusinessUserService;
import com.chinaweal.youfool.devops.org.entity.Engineer;
import com.chinaweal.youfool.devops.org.service.IEngineerService;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.entity.Repair;
import com.chinaweal.youfool.devops.repair.entity.RepairHandle;
import com.chinaweal.youfool.devops.repair.entity.RepairLabel;
import com.chinaweal.youfool.devops.repair.entity.RepairTodo;
import com.chinaweal.youfool.devops.repair.excel.CustomRowCellWriteHandler;
import com.chinaweal.youfool.devops.repair.excel.LocalDateTimeConverter;
import com.chinaweal.youfool.devops.repair.excel.RepairTodoExcel;
import com.chinaweal.youfool.devops.repair.mapper.RepairHandleMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairTodoMapper;
import com.chinaweal.youfool.devops.repair.service.*;
import com.chinaweal.youfool.devops.websocket.server.BusinessSysServer;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.user.entity.UserBase;
import com.chinaweal.youfool.framework.springboot.user.service.UserBaseService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* <p>
* 运维报障待办 服务实现类
* </p>
*
* @author chinaweal
* @since 2020-06-05
*/
@Service
public class RepairTodoServiceImpl extends ServiceImpl<RepairTodoMapper, RepairTodo> implements IRepairTodoService {
@Resource
private RepairTodoMapper repairTodoMapper;
@Resource
private IRepairHandleService iRepairHandleService;
@Resource
private RepairHandleMapper repairHandleMapper;
@Resource
private IRepairFileService iRepairFileService;
@Resource
private IRepairService iRepairService;
@Resource
private BusinessUserService businessUserService;
@Resource
private IEngineerService iEngineerService;
@Resource
private IRepairLabelService iRepairLabelService;
@Override
public RepairTodo getByRepairId(String repairId) {
LambdaQueryWrapper<RepairTodo> qw = new LambdaQueryWrapper<>();
qw.eq(RepairTodo::getRepairId, repairId);
return getOne(qw);
}
private Page<RepairTodo> setPage(RepairTodoListQuery query) {
String[] repairField = {"question_type", "leader_nickname", "bus_classify", "bus_step"};
Page<RepairTodo> page = new Page<>(query.getCurrent(), query.getSize());
if (StringUtils.isNotBlank(query.getOrderField())) {
if ("desc".equalsIgnoreCase(query.getOrderSort())) {
//详细表的字段排序
if (ArrayUtils.contains(repairField, query.getOrderField())) {
page.addOrder(OrderItem.desc("r." + query.getOrderField()));
} else {
page.addOrder(OrderItem.desc("rt." + query.getOrderField()));
}
} else {
//详细表的字段排序
if (ArrayUtils.contains(repairField, query.getOrderField())) {
page.addOrder(OrderItem.asc("r." + query.getOrderField()));
} else {
page.addOrder(OrderItem.asc("rt." + query.getOrderField()));
}
}
} else {
page.addOrder(OrderItem.asc("rt.launch_time"));
}
return page;
}
@Override
public IPage<RepairTodo> findList(RepairTodoListQuery query) {
Page<RepairTodo> page = setPage(query);
return repairTodoMapper.listTodo(page, query);
}
@Override
public RepairTodo generateTodo(Repair repair) {
RepairTodo repairTodo = new RepairTodo();
BeanUtils.copyProperties(repair, repairTodo);
repairTodo.setSource(repair.getSource());
repairTodo.setDeleted("0");
repairTodo.setStep(IRepairHandleService.DECLARE);
save(repairTodo);
return repairTodo;
}
@Override
public RepairTodo updateTodo(Repair repair) {
RepairTodo repairTodo = getByRepairId(repair.getRepairId());
BeanUtils.copyProperties(repair, repairTodo);
updateById(repairTodo);
return repairTodo;
}
@Override
public void exportTodo(RepairTodoListQuery query, HttpServletResponse response, String type) throws IOException {
Page<RepairTodo> page = setPage(query).setCurrent(0).setSize(10000000000000000L);
IPage<RepairTodo> todoIPage;
if (query.getTodoIds() != null && query.getTodoIds().length > 0) {
todoIPage = repairTodoMapper.listByTodoId(page, query.getTodoIds());
} else {
todoIPage = repairTodoMapper.listTodo(page, query);
}
List<RepairTodoExcel> list = new ArrayList<>();
List<RepairTodo> records = todoIPage.getRecords();
int i = 0;
for (RepairTodo repairTodo : records) {
RepairTodoExcel repairTodoExcel = new RepairTodoExcel();
BeanUtils.copyProperties(repairTodo, repairTodoExcel);
repairTodoExcel.setNo(++i);
list.add(repairTodoExcel);
}
//找出最大的时间
LocalDateTime launchTimeMax = records.stream().max((o1, o2) -> {
boolean after = o1.getLaunchTime().isBefore(o2.getLaunchTime());
return after ? 0 : 1;
}).map(RepairTodo::getLaunchTime).orElse(null);
LocalDateTime launchTimeMin = records.stream().min((o1, o2) -> {
boolean before = o1.getLaunchTime().isAfter(o2.getLaunchTime());
return before ? 1 : 0;
}).map(RepairTodo::getLaunchTime).orElse(null);
String date = "";
if (launchTimeMin != null) {
date = launchTimeMin.toLocalDate().toString();
}
if (launchTimeMax != null) {
String maxDate = launchTimeMax.toLocalDate().toString();
if (!date.equals(maxDate)) {
date += " - " + maxDate;
}
}
String fileName = new String(("运维报障系统" + date + "报障记录.xlsx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
OutputStream os = response.getOutputStream();
//根据字段列表,导出那些表头字段
String[] fields = query.getFields();
List<String> exportFields = new ArrayList<>();
List<List<String>> titles = new ArrayList<>();
Map<String, String> fieldsMap;
if ("dev".equals(type)) {
fieldsMap = excelDevFields();
} else {
fieldsMap = excelBusinessFields();
}
List<String> fieldName = new ArrayList<>();
//大标题
fieldName.add("运维报障系统 " + date + " 报障记录");
//序号
fieldName.add("序号");
titles.add(fieldName);
//生成表头
if (fields != null && fields.length > 0) {
for (String fieldId : fieldsMap.keySet()) {
boolean contains = ArrayUtils.contains(fields, fieldId);
if (contains) {
fieldName = new ArrayList<>();
fieldName.add(fieldsMap.get(fieldId));
titles.add(fieldName);
exportFields.add(fieldId);
}
}
} else {
//默认导出所有表头
for (String value : fieldsMap.values()) {
fieldName = new ArrayList<>();
fieldName.add(value);
titles.add(fieldName);
}
exportFields.addAll(fieldsMap.keySet());
}
List<List<Object>> data = new ArrayList<>();
try {
for (RepairTodoExcel repairTodoExcel : list) {
Class<? extends RepairTodoExcel> aClass = repairTodoExcel.getClass();
List<Object> item = new ArrayList<>();
item.add(repairTodoExcel.getNo());
for (String field : exportFields) {
Method method = aClass.getMethod(field);
Object value = method.invoke(repairTodoExcel);
item.add(value);
}
data.add(item);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
EasyExcel.write(os).head(titles).useDefaultStyle(false).automaticMergeHead(false)
.registerWriteHandler(new CustomRowCellWriteHandler())
.registerConverter(new LocalDateTimeConverter())
.sheet(date + "报障清单").doWrite(data);
os.close();
}
@Override
public RestResult<String> assign(RepairHandle repairHandle) {
//查询待办是否存在
RepairTodo repairTodo = getByRepairId(repairHandle.getRepairId());
if (repairTodo == null) {
return RestResult.error(ResultCode.USCID_INVALID, "找不到对应的运维报障数据");
}
//插入流程表
repairHandle.setTodoId(repairTodo.getTodoId());
repairHandle = iRepairHandleService.updateByRepairIdHandleTodo(repairHandle);
//更改待办分派人员记录
repairTodo.setHandleTime(repairHandle.getHappenTime());
repairTodo.setStep(repairHandle.getStep());
repairTodo.setPriority(repairHandle.getPriority());
updateById(repairTodo);
Repair repair = new Repair();
repair.setRepairId(repairHandle.getRepairId());
repair.setPriority(repairHandle.getPriority());
repair.setQuestionType(repairHandle.getQuestionType());
repair.setPlannedTime(repairHandle.getPlannedTime());
repair.setLeaderNickname(repairHandle.getLeaderNickname());
repair.setLeaderUsername(repairHandle.getLeaderUsername());
repair.setThinking(repairHandle.getThinking());
//标签字符全量插入
if (repairHandle.getLabels() != null) {
repair.setLabel(String.join(",", repairHandle.getLabels()));
}
iRepairService.updateById(repair);
//因为分派,自动生成处理中这个环节记录
//等待300毫秒区分排序
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
RepairHandle acceptHandle = new RepairHandle(repairTodo.getTodoId(), repairTodo.getRepairId(), IRepairHandleService.HANDLE,
repairHandle.getNextHandleUsername(), repairHandle.getNextHandleNickname(), null);
acceptHandle = iRepairHandleService.updateByRepairIdHandleTodo(acceptHandle);
//更改待办
repairTodo.setHandleTime(acceptHandle.getHappenTime());
repairTodo.setEngineer(acceptHandle.getHandleNickname());
repairTodo.setEngineerUsername(acceptHandle.getHandleUsername());
repairTodo.setStep(acceptHandle.getStep());
updateById(repairTodo);
//删除旧的标签
LambdaQueryWrapper<RepairLabel> qw = new LambdaQueryWrapper<>();
qw.eq(RepairLabel::getRepairId, repair.getRepairId());
iRepairLabelService.remove(qw);
//全量标签全量插入
if (repairHandle.getLabels() != null) {
for (String labelStr : repairHandle.getLabels()) {
RepairLabel label = new RepairLabel();
label.setName(labelStr);
label.setRepairId(repair.getRepairId());
iRepairLabelService.save(label);
}
}
return RestResult.ok(repairHandle.getHandleId());
}
@Override
public RestResult<String> generateNextHandle(RepairHandle repairHandle) {
//查询待办是否存在
RepairTodo repairTodo = getByRepairId(repairHandle.getRepairId());
if (repairTodo == null) {
return RestResult.error(ResultCode.USCID_INVALID, "找不到对应的运维报障数据");
}
//插入流程表
repairHandle.setTodoId(repairTodo.getTodoId());
repairHandle = iRepairHandleService.updateByRepairIdHandleTodo(repairHandle);
//更改待办记录
repairTodo.setHandleTime(repairHandle.getHappenTime());
repairTodo.setStep(repairHandle.getStep());
updateById(repairTodo);
return RestResult.ok(repairHandle.getHandleId());
}
@Override
public Map<String, Integer> countRepairStepByUserId(String userId) {
QueryWrapper<RepairTodo> qw = new QueryWrapper<>();
qw.select("STEP AS STEP,COUNT(*) AS NUM")
.eq("USER_ID", userId)
.groupBy("STEP").orderByDesc("NUM");
List<Map<String, Object>> list = listMaps(qw);
Map<String, Integer> body = new LinkedHashMap<>();
for (Map<String, Object> map : list) {
Object step = map.get("STEP");
if (step == null) {
continue;
}
body.put(map.get("STEP").toString().toLowerCase(), ((BigDecimal) map.get("NUM")).intValue());
}
return body;
}
@Override
public RestResult<String> feedback(RepairHandle repairHandle, String tempHandleId) {
String[] labels = repairHandle.getLabels();
RepairHandle loadRepairHandle = iRepairHandleService.getById(repairHandle.getHandleId());
if (loadRepairHandle == null || !"1".equals(loadRepairHandle.getStatus())) {
return RestResult.error(ResultCode.USCID_INVALID, "当前处理记录无效");
}
//查询待办是否存在
RepairTodo repairTodo = getByRepairId(repairHandle.getRepairId());
if (repairTodo == null) {
return RestResult.error(ResultCode.USCID_INVALID, "找不到对应的运维报障数据");
}
//更新处理结果
loadRepairHandle.setResult(repairHandle.getResult());
loadRepairHandle.setHandleUsername(repairHandle.getHandleUsername());
loadRepairHandle.setHandleNickname(repairHandle.getHandleNickname());
loadRepairHandle.setHappenTime(LocalDateTime.now());
//上一步是处理中则修改,或者还是处于处理反馈环节
if (IRepairHandleService.HANDLE.equals(loadRepairHandle.getStep())
|| IRepairHandleService.FEEDBACK.equals(loadRepairHandle.getStep())) {
loadRepairHandle.setStep(IRepairHandleService.FEEDBACK);
iRepairHandleService.updateById(loadRepairHandle);
} else {
//否则生成新的记录
loadRepairHandle.setStep(IRepairHandleService.FEEDBACK);
repairHandle = iRepairHandleService.updateByRepairIdHandleTodo(loadRepairHandle);
}
//更改待办记录
repairTodo.setHandleTime(loadRepairHandle.getHappenTime());
repairTodo.setFeedbackTime(loadRepairHandle.getHappenTime());
repairTodo.setStep(loadRepairHandle.getStep());
updateById(repairTodo);
//关联附件
iRepairFileService.updateHandleIdByTempHandleId(tempHandleId, repairHandle.getHandleId());
//更新详情表-实际完成时间
Repair repair = new Repair();
repair.setRepairId(repairTodo.getRepairId());
repair.setRealityTime(loadRepairHandle.getHappenTime());
//更新标签
//标签字符全量插入
if (labels != null) {
repair.setLabel(String.join(",", labels));
}
//删除旧的标签
LambdaQueryWrapper<RepairLabel> qw = new LambdaQueryWrapper<>();
qw.eq(RepairLabel::getRepairId, repair.getRepairId());
iRepairLabelService.remove(qw);
//全量标签全量插入
if (labels != null) {
for (String s : labels) {
RepairLabel label = new RepairLabel();
label.setName(s);
label.setRepairId(repair.getRepairId());
iRepairLabelService.save(label);
}
}
iRepairService.updateById(repair);
//则推送消息
try {
Map<String, String> map = new LinkedHashMap<>();
map.put("repairId", repairTodo.getRepairId());
map.put("title", repairTodo.getTitle());
BusinessSysServer.sendToUser(repairTodo.getUserId(), JSONObject.toJSONString(map));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return RestResult.ok(repairHandle.getHandleId());
}
@Override
public Map<String, String> excelDevFields() {
Map<String, String> map = new LinkedHashMap<>();
map.put("getRepairId", "运维单号");
map.put("getTitle", "标题");
map.put("getFaultDescription", "故障内容");
map.put("getBusAcceptNo", "业务受理号");
map.put("getUsername", "申报用户账号");
map.put("getNickname", "申报用户昵称");
map.put("getQuestionType", "问题分类");
map.put("getLabel", "标签");
map.put("getBusiness", "业务模块");
map.put("getLaunchTime", "报送时间");
map.put("getSolveLimitTime", "解决期限时间");
map.put("getPlannedTime", "计划完成时间");
map.put("getFeedbackTime", "反馈时间");
map.put("getEngineer", "运维工程师");
map.put("getLeaderNickname", "负责人");
map.put("getOrg", "所属机构");
map.put("getDept", "所属单位");
map.put("getPriority", "紧急程度");
map.put("getUrgency", "优先级");
map.put("getReminder", "是否催单");
map.put("getFeedbackTimeSize", "处理时长");
map.put("getSolveTime", "归档时长");
map.put("getStep", "处理环节");
return map;
}
@Override
public Map<String, String> excelBusinessFields() {
Map<String, String> map = new LinkedHashMap<>();
map.put("getRepairId", "运维单号");
map.put("getTitle", "标题");
map.put("getFaultDescription", "故障内容");
map.put("getBusAcceptNo", "业务受理号");
map.put("getUsername", "申报用户账号");
map.put("getNickname", "申报用户昵称");
map.put("getBusiness", "业务模块");
map.put("getBusClassify", "业务分类");
map.put("getBusStep", "业务环节");
map.put("getLaunchTime", "报送时间");
map.put("getSolveLimitTime", "解决期限时间");
map.put("getFeedbackTime", "反馈时间");
map.put("getFeedbackTimeSize", "处理时长");
map.put("getSolveTime", "归档时长");
map.put("getEngineer", "运维工程师");
map.put("getOrg", "所属机构");
map.put("getDept", "所属单位");
map.put("getPriority", "紧急程度");
map.put("getReminder", "是否催单");
map.put("getStep", "处理环节");
return map;
}
@Override
public RestResult<String> reminder(String repairId) {
//查询催单记录
RepairTodo repairTodo = getByRepairId(repairId);
if (repairTodo == null) {
return RestResult.error(ResultCode.USCID_INVALID);
}
repairTodo.setReminder(repairTodo.getReminder() == null ? 1 : repairTodo.getReminder() + 1);
updateById(repairTodo);
return RestResult.ok();
}
@Override
public IPage<RepairTodo> synthesizeBusinessList(RepairTodoListQuery query) {
Optional<Object> unitId = UserBase.getTokenValueByKey("unitId");
unitId.ifPresent(o -> query.setDeptId(o.toString()));
query.setUsername(null);
query.setUserId(null);
return findList(query);
}
@Override
public IPage<RepairTodo> findTodoByEngineer(RepairTodoListQuery query) {
//获取用户token的用户信息
String username = UserBase.currentUsername();
Engineer engineer = iEngineerService.getUserByUsername(username);
String[] roles = engineer.getRoles().split(",");
boolean isAdmin = ArrayUtils.contains(roles, "admin");
query.setEngineerUsername(username);
//如果tabId不是我的待办和拥有管理员则设空
if (!"toDoList".equals(query.getTabId()) && isAdmin) {
query.setEngineerUsername(null);
}
IPage<RepairTodo> list = findList(query);
return list;
}
@Override
public IPage<RepairTodo> findTodoByBusiness(RepairTodoListQuery query) {
//获取用户token的用户信息
String userId = UserBase.currentUserId();
query.setUserId(userId);
IPage<RepairTodo> list = findList(query);
return list;
}
@Override
public IPage<RepairTodo> listByItemId(RepairTodoListQuery query, String itemId) {
Page<RepairTodo> page = setPage(query);
IPage<RepairTodo> todoIPage = new Page<>();
//总数
if ("total".equals(itemId)) {
todoIPage = findList(query);
} else if ("resolved".equals(itemId) || "avgResolvedTime".equals(itemId)) {
query.setStep(new String[]{"resolved"});
todoIPage = findList(query);
} else if ("untreated".equals(itemId)) {
query.setStep(new String[]{"handle", "declare", "assign", "unresolved"});
todoIPage = findList(query);
} else if ("confirmed".equals(itemId)) {
query.setStep(new String[]{"feedback"});
todoIPage = findList(query);
} else if ("oneSuccess".equals(itemId)) {
query.setStep(new String[]{"feedback"});
todoIPage = repairHandleMapper.listResultSecond(page, query, 1);
} else if ("twoSuccess".equals(itemId)) {
query.setStep(new String[]{"feedback"});
todoIPage = repairHandleMapper.listResultSecond(page, query, 2);
} else if ("threeSuccess".equals(itemId)) {
query.setStep(new String[]{"feedback"});
todoIPage = repairHandleMapper.listResultSecond(page, query, 3);
} else if (itemId.startsWith("labelBusClassify")) {
query.setBusClassify(itemId.replace("labelBusClassify", ""));
todoIPage = findList(query);
} else if (itemId.startsWith("labelBusStep")) {
query.setBusStep(itemId.replace("labelBusStep", ""));
todoIPage = findList(query);
} else if ("avgFeedbackTime".equals(itemId)) {
query.setStep(new String[]{"feedback", "resolved"});
todoIPage = findList(query);
}
// else {
// todoIPage = repairTodoMapper.listByItemId(page, query, itemId);
// }
return todoIPage;
}
@Override
public void exportListByItemId(HttpServletResponse response, RepairTodoListQuery query, String itemId, String type) throws IOException {
Page<RepairTodo> page = setPage(query).setCurrent(0).setSize(10000000000000000L);
IPage<RepairTodo> todoIPage;
if (query.getTodoIds() != null && query.getTodoIds().length > 0) {
todoIPage = repairTodoMapper.listByTodoId(page, query.getTodoIds());
} else {
query.setCurrent((int) page.getCurrent());
query.setSize((int) page.getSize());
todoIPage = listByItemId(query, itemId);
}
List<RepairTodoExcel> list = new ArrayList<>();
List<RepairTodo> records = todoIPage.getRecords();
int i = 0;
for (RepairTodo repairTodo : records) {
RepairTodoExcel repairTodoExcel = new RepairTodoExcel();
BeanUtils.copyProperties(repairTodo, repairTodoExcel);
repairTodoExcel.setNo(++i);
list.add(repairTodoExcel);
}
//找出最大的时间
LocalDateTime launchTimeMax = records.stream().max((o1, o2) -> {
boolean after = o1.getLaunchTime().isBefore(o2.getLaunchTime());
return after ? 0 : 1;
}).map(RepairTodo::getLaunchTime).orElse(null);
LocalDateTime launchTimeMin = records.stream().min((o1, o2) -> {
boolean before = o1.getLaunchTime().isAfter(o2.getLaunchTime());
return before ? 1 : 0;
}).map(RepairTodo::getLaunchTime).orElse(null);
String date = "";
if (launchTimeMin != null) {
date = launchTimeMin.toLocalDate().toString();
}
if (launchTimeMax != null) {
String maxDate = launchTimeMax.toLocalDate().toString();
if (!date.equals(maxDate)) {
date += " - " + maxDate;
}
}
String fileName = new String(("运维报障系统" + date + "报障记录.xlsx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
OutputStream os = response.getOutputStream();
//根据字段列表,导出那些表头字段
String[] fields = query.getFields();
List<String> exportFields = new ArrayList<>();
List<List<String>> titles = new ArrayList<>();
Map<String, String> fieldsMap;
if ("dev".equals(type)) {
fieldsMap = excelDevFields();
} else {
fieldsMap = excelBusinessFields();
}
List<String> fieldName = new ArrayList<>();
//大标题
fieldName.add("运维报障系统 " + date + " 报障记录");
//序号
fieldName.add("序号");
titles.add(fieldName);
//生成表头
if (fields != null && fields.length > 0) {
for (String fieldId : fieldsMap.keySet()) {
boolean contains = ArrayUtils.contains(fields, fieldId);
if (contains) {
fieldName = new ArrayList<>();
fieldName.add(fieldsMap.get(fieldId));
titles.add(fieldName);
exportFields.add(fieldId);
}
}
} else {
//默认导出所有表头
for (String value : fieldsMap.values()) {
fieldName = new ArrayList<>();
fieldName.add(value);
titles.add(fieldName);
}
exportFields.addAll(fieldsMap.keySet());
}
List<List<Object>> data = new ArrayList<>();
try {
for (RepairTodoExcel repairTodoExcel : list) {
Class<? extends RepairTodoExcel> aClass = repairTodoExcel.getClass();
List<Object> item = new ArrayList<>();
item.add(repairTodoExcel.getNo());
for (String field : exportFields) {
Method method = aClass.getMethod(field);
Object value = method.invoke(repairTodoExcel);
item.add(value);
}
data.add(item);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
EasyExcel.write(os).head(titles).useDefaultStyle(false).automaticMergeHead(false)
.registerWriteHandler(new CustomRowCellWriteHandler())
.registerConverter(new LocalDateTimeConverter())
.sheet(date + "报障清单").doWrite(data);
os.close();
}
@Override
public IPage<RepairTodo> synthesizeEngineerList(RepairTodoListQuery query) {
Optional<Object> source = UserBase.getTokenValueByKey("source");
source.ifPresent(o -> {
query.setSource(Arrays.asList(source.get().toString().split(",")));
});
return findList(query);
}
@Override
public IPage<RepairTodo> leaderTodo(RepairTodoListQuery query) {
String username = UserBase.currentUsername();
query.setLeaderUsername(username);
return findList(query);
}
@Override
public RestResult<String> batchAssign(List<RepairHandle> repairHandleList) {
AtomicInteger atomicInteger = new AtomicInteger();
for (RepairHandle repairHandle : repairHandleList) {
new Thread(() -> {
assign(repairHandle);
int finishedNum = atomicInteger.incrementAndGet();
synchronized (atomicInteger) {
if (finishedNum == repairHandleList.size()) {
atomicInteger.notify();
}
}
}).start();
}
synchronized (atomicInteger) {
try {
atomicInteger.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return RestResult.ok();
}
}

View File

@ -0,0 +1,286 @@
package com.chinaweal.youfool.devops.repair.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.chinaweal.youfool.devops.repair.controller.query.RepairTodoListQuery;
import com.chinaweal.youfool.devops.repair.mapper.RepairHandleMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairSummaryMapper;
import com.chinaweal.youfool.devops.repair.mapper.RepairTodoMapper;
import com.chinaweal.youfool.devops.repair.service.IRepairSummaryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import static com.chinaweal.youfool.devops.repair.service.IRepairHandleService.FEEDBACK;
/**
* 统计
*/
@Service
@Slf4j
public class StatisticServiceImpl {
@Resource
private RepairTodoMapper repairTodoMapper;
@Resource
private RepairMapper repairMapper;
@Resource
private RepairHandleMapper repairHandleMapper;
@Resource
private RepairSummaryMapper repairSummaryMapper;
public List<Map<String, Object>> groupOrgCount(RepairTodoListQuery query) {
List<Map<String, Object>> list = new ArrayList<>();
List<String> orgs = IRepairSummaryService.getOrgNameList();
for (int i = 0; i < orgs.size(); i++) {
String org = orgs.get(i);
Map<String, Object> map = new LinkedHashMap<>();
query.setOrg(org);
Map<String, Object> data = repairTodoMapper.getWhole(query);
BigDecimal total = (BigDecimal) data.get("total");
BigDecimal resolved = (BigDecimal) data.get("resolved");
BigDecimal feedback = (BigDecimal) data.get("feedback");
BigDecimal unresolved = (BigDecimal) data.get("unresolved");
BigDecimal handleAndDeclare = (BigDecimal) data.get("handleAndDeclare");
map.put("no", i + 1);
map.put("name", org);
map.put("total", total);
map.put("resolved", resolved);
map.put("resolvedRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (resolved.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
map.put("feedback", feedback);
map.put("feedbackRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (feedback.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
map.put("unresolved", unresolved);
map.put("unresolvedRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (unresolved.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
map.put("handleAndDeclare", handleAndDeclare);
map.put("handleAndDeclareRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (handleAndDeclare.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
list.add(map);
}
return list;
}
public void exportGroupOrg(RepairTodoListQuery query, HttpServletResponse response) throws IOException {
String fileName = new String(("各单位报障统计.xlsx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
OutputStream os = response.getOutputStream();
String templateFileName = this.getClass().getResource("/excel/shijuyugequbaozhantongji.xlsx").getPath();
ExcelWriter excelWriter = EasyExcel.write(os).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).forceNewRow(Boolean.TRUE).build();
List<Map<String, Object>> list = groupOrgCount(query);
excelWriter.fill(list, fillConfig, writeSheet);
Map<String, Object> map = new HashMap<>();
//处理时间
if (query.getLaunchTimeStart() != null) {
String start = query.getLaunchTimeStart().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
String end = query.getLaunchTimeEnd().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
map.put("date", start + " 至 " + end);
} else {
map.put("date", "全部");
}
//合计
BigDecimal total = list.stream().map(x -> (BigDecimal) x.get("total")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal resolved = list.stream().map(x -> (BigDecimal) x.get("resolved")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal feedback = list.stream().map(x -> (BigDecimal) x.get("feedback")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal unresolved = list.stream().map(x -> (BigDecimal) x.get("unresolved")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal handleAndDeclare = list.stream().map(x -> ((BigDecimal) x.get("handleAndDeclare"))).reduce(BigDecimal.ZERO, BigDecimal::add);
map.put("total", total);
map.put("resolved", resolved);
map.put("resolvedRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (resolved.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
map.put("feedback", feedback);
map.put("feedbackRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (feedback.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
map.put("unresolved", unresolved);
map.put("unresolvedRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (unresolved.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
map.put("handleAndDeclare", handleAndDeclare);
map.put("handleAndDeclareRate", total.compareTo(BigDecimal.valueOf(0)) > 0 ? (handleAndDeclare.multiply(BigDecimal.valueOf(100))
.divide(total, 1, BigDecimal.ROUND_HALF_UP) + "%") : 0);
excelWriter.fill(map, writeSheet);
excelWriter.finish();
}
public Map<String, Object> sumTotalType(RepairTodoListQuery query) {
BigDecimal total = repairHandleMapper.countStep(query, "total");
BigDecimal resolved = repairHandleMapper.countStep(query, "resolved");
BigDecimal untreated = repairHandleMapper.countStep(query, "untreated");
BigDecimal confirmed = repairHandleMapper.countStep(query, "confirmed");
Map<String, Object> data = new LinkedHashMap<>();
//报障总数量
data.put("total", total);
data.put("resolved", resolved);
data.put("untreated", untreated);
data.put("confirmed", confirmed);
return data;
}
public List<Map<String, Object>> sumQuestionType(RepairTodoListQuery query) {
List<Map<String, Object>> bodyList = new ArrayList<>();
//报障总数量
List<Map<String, Object>> list = repairMapper.groupByQuestionTypeCount(query);
for (Map<String, Object> dbData : list) {
Map<String, Object> data = new HashMap<>();
data.put("name", dbData.getOrDefault("questionType", "其他"));
data.put("number", dbData.get("number"));
bodyList.add(data);
}
return bodyList;
}
public List<Map<String, Object>> sumSuccess(RepairTodoListQuery query) {
List<Map<String, Object>> bodyList = new ArrayList<>();
BigDecimal oneSuccess = repairHandleMapper.countResultSecond(query, 1);
BigDecimal twoSuccess = repairHandleMapper.countResultSecond(query, 2);
BigDecimal threeSuccess = repairHandleMapper.countResultSecond(query, 3);
Map<String, Object> one = new LinkedHashMap<>();
one.put("name", "处理1次");
one.put("number", oneSuccess);
Map<String, Object> two = new LinkedHashMap<>();
two.put("name", "处理2次");
two.put("number", twoSuccess);
Map<String, Object> three = new LinkedHashMap<>();
three.put("name", "处理3次及以上");
three.put("number", threeSuccess);
bodyList.add(one);
bodyList.add(two);
bodyList.add(three);
return bodyList;
}
public Map<String, Object> sumEfficiency(RepairTodoListQuery query) {
List<Map<String, Object>> list = repairSummaryMapper.sumTotalByOrgAndDay(query.getLaunchTimeStart(), query.getLaunchTimeEnd(), query.getOrgListLike());
Map<String, Object> bodyMap = new HashMap<>();
Map<String, Object> item;
List<Map<String, Object>> totalList = new ArrayList<>();
for (Map<String, Object> dbData : list) {
BigDecimal handleTotal = (BigDecimal) dbData.get("handleTotal");
item = new LinkedHashMap<>();
item.put("date", dbData.get("dateStr"));
item.put("reportTotal", dbData.get("reportTotal"));
item.put("handleTotal", handleTotal);
item.put("busTotal", dbData.get("busTotal"));
item.put("faultRate", 0);//todo
item.put("resSpeed", handleTotal.divide(BigDecimal.valueOf(8), 0, BigDecimal.ROUND_HALF_UP));
totalList.add(item);
}
//判断结束时间是否包含当天,如是则需要实时查询当天数据(因为汇总表只有昨天的数据)
LocalDate toDay = LocalDate.now();
if (query.getLaunchTimeEnd() == null || query.getLaunchTimeEnd().toLocalDate().isAfter(toDay)
|| query.getLaunchTimeEnd().toLocalDate().isEqual(toDay)) {
LocalDateTime startTime = toDay.atStartOfDay();
LocalDateTime endTime = startTime.plusDays(1).minusSeconds(1);
Long reportTotal = repairTodoMapper.countByLaunchTimeAndLikeOrg(startTime, endTime, query.getOrgListLike());
Long handleTotal = repairHandleMapper.countDistinctByTimeAndOrgAndStep(startTime, endTime, query.getOrgListLike(), FEEDBACK);
item = new LinkedHashMap<>();
item.put("date", toDay.toString());
item.put("reportTotal", reportTotal);
item.put("handleTotal", handleTotal);
item.put("busTotal", 0);//todo
item.put("faultRate", 0);//todo
item.put("resSpeed", BigDecimal.valueOf(handleTotal).divide(BigDecimal.valueOf(8), 0, BigDecimal.ROUND_HALF_UP));
totalList.add(item);
}
bodyMap.put("totalList", totalList);
//日期范围数组
List<Object> dateRange = new ArrayList<>();
//取出最后一组数据,遍历出日期
for (Map<String, Object> map : totalList) {
dateRange.add(map.get("date"));
}
bodyMap.put("dateRange", dateRange);
return bodyMap;
}
public Map<String, Object> sumQuestionTopDay(RepairTodoListQuery query) {
Map<String, Object> bodyMap = new HashMap<>();
Map<String, Object> topMap = new LinkedHashMap<>();
//判断结束时间是否包含当天,如是则需要实时查询当天数据(因为汇总表只有昨天的数据)
LocalDate toDay = LocalDate.now();
RepairTodoListQuery toDayQuery = null;
if (query.getLaunchTimeEnd() == null || query.getLaunchTimeEnd().toLocalDate().isAfter(toDay)
|| query.getLaunchTimeEnd().toLocalDate().isEqual(toDay)) {
toDayQuery = new RepairTodoListQuery();
toDayQuery.setLaunchTimeStart(toDay.atStartOfDay());
toDayQuery.setLaunchTimeEnd(toDay.plusDays(1).atStartOfDay().minusSeconds(1));
}
//查询前五的问题分类总数
List<Map<String, Object>> top5 = repairSummaryMapper.getGroupQuestionTop(query.getLaunchTimeStart(), query.getLaunchTimeEnd(), query.getOrgListLike());
List<Map<String, Object>> list = new ArrayList<>();
for (Map<String, Object> map : top5) {
list = new ArrayList<>();
String name = String.valueOf(map.get("name"));
//根据问题分类名称查询每天最新的列表
List<Map<String, Object>> dbList = repairSummaryMapper.sumTotalByOrgAndQuestionDay(query.getLaunchTimeStart(),
query.getLaunchTimeEnd(), name, query.getOrgListLike());
for (Map<String, Object> dbData : dbList) {
map = new LinkedHashMap<>();
map.put("date", dbData.get("dateStr"));
map.put("reportTotal", dbData.get("reportTotal"));
list.add(map);
}
//是否需要补上今天实时的数据
if (toDayQuery != null) {
toDayQuery.setQuestionType(name);
BigDecimal number = repairMapper.countByQuestionType(toDayQuery);
map = new LinkedHashMap<>();
map.put("date", toDay.toString());
map.put("reportTotal", number);
list.add(map);
}
topMap.put(name, list);
}
bodyMap.put("top", topMap);
//日期范围数组
List<Object> dateRange = new ArrayList<>();
//取出最后一组数据,遍历出日期
for (Map<String, Object> map : list) {
dateRange.add(map.get("date"));
}
bodyMap.put("dateRange", dateRange);
return bodyMap;
}
}

View File

@ -0,0 +1,76 @@
package com.chinaweal.youfool.devops.util;
/*对图片进行处理的类和方法*/
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
public class VerifyCode {
public static String drawRandomText(int width, int height, OutputStream output, HttpServletRequest request) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);//设置画笔颜色-验证码背景色
graphics.fillRect(0, 0, width, height);//填充背景
graphics.setFont(new Font("微软雅黑", Font.BOLD, 40));
//数字和字母的组合
String baseNumLetter = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
StringBuffer sBuffer = new StringBuffer();
int x = 10; //旋转原点的 x 坐标
String ch = "";
Random random = new Random();
for (int i = 0; i < 4; i++) {
graphics.setColor(getRandomColor());
//设置字体旋转角度
int degree = random.nextInt() % 30; //角度小于30度
int dot = random.nextInt(baseNumLetter.length());
ch = baseNumLetter.charAt(dot) + "";
sBuffer.append(ch);
//正向旋转
graphics.rotate(degree * Math.PI / 180, x, 45);
graphics.drawString(ch, x, 45);
//反向旋转
graphics.rotate(-degree * Math.PI / 180, x, 45);
x += 35;
}
//画干扰线
for (int i = 0; i < 6; i++) {
// 设置随机颜色
graphics.setColor(getRandomColor());
// 随机画线
graphics.drawLine(random.nextInt(width), random.nextInt(height),
random.nextInt(width), random.nextInt(height));
}
//添加噪点
for (int i = 0; i < 30; i++) {
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
graphics.setColor(getRandomColor());
graphics.fillRect(x1, y1, 2, 2);
}
//记录session
request.getSession().setAttribute("vcode", sBuffer.toString());
try {
ImageIO.write(image, "png", output);
} catch (IOException e) {
e.printStackTrace();
}
return sBuffer.toString();
}
/**
* 随机取色
*/
private static Color getRandomColor() {
Random ran = new Random();
Color color = new Color(ran.nextInt(256),
ran.nextInt(256), ran.nextInt(256));
return color;
}
}

View File

@ -0,0 +1,24 @@
package com.chinaweal.youfool.devops.websocket.controller;
import com.chinaweal.youfool.devops.websocket.server.BusinessSysServer;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "1.WebSocket测试")
@ApiSort(1)
@RestController
@RequestMapping("/websocket")
public class TestWebSocketController {
@ApiOperation(value = "1.测试业务系统发送", position = 1)
@GetMapping("/countRepairStepByUsername")
public RestResult countRepairStepByUsername(String username, String message) {
BusinessSysServer.sendToUser(username, message);
return RestResult.ok();
}
}

View File

@ -0,0 +1,122 @@
package com.chinaweal.youfool.devops.websocket.server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 与业务系统的通信 websocket
*
* @author
*/
@ServerEndpoint("/websocket/businessSys/{userId}")
@Component
@Slf4j
public class BusinessSysServer {
/**
* 存储起来一个用户账号可能多页面打开存储列表
*/
private static final ConcurrentHashMap<String, List<Session>> WEB_SOCKET_SET = new ConcurrentHashMap<>();
private Session session;
private String userId;
/**
* 连接建立成功调用的方法
*
* @param userId 用户唯一标示
* @param session 可选的参数session为与某个客户端的连接会话需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(@PathParam(value = "userId") String userId, Session session) {
pushSessionByUserId(userId, session);
log.debug("用户名:{}sessionId:{},以系统连接建立成功", userId, session.getId());
}
private void pushSessionByUserId(String userId, Session session) {
this.session = session;
this.userId = userId;
List<Session> list = WEB_SOCKET_SET.getOrDefault(userId, new ArrayList<>());
list.add(session);
WEB_SOCKET_SET.put(userId, list);
}
private void removeSessionByUserIdOrSessionId() {
List<Session> sessions = WEB_SOCKET_SET.get(userId);
if (sessions == null || sessions.isEmpty()) {
return;
}
sessions.removeIf(next -> next == null || next.getId().equals(session.getId()));
if (sessions.isEmpty()) {
WEB_SOCKET_SET.remove(userId);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
removeSessionByUserIdOrSessionId();
log.debug("用户名退出:{},当前sessionId:{}", userId, session.getId());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
log.debug("来自客户端的消息:" + message);
}
/**
* 给指定的人发送消息
*
* @param message
*/
public static void sendToUser(String sendUserId, String message) {
List<Session> sessions = WEB_SOCKET_SET.get(sendUserId);
if (sessions != null) {
for (Session item : sessions) {
if (item != null && item.isOpen()) {
item.getAsyncRemote().sendText(message);
}
}
}
}
/**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
// log.error(error.getMessage(), error);
}
/**
* 发送消息
*
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
//同步发送
this.session.getBasicRemote().sendText(message);
//异步发送
//this.session.getAsyncRemote().sendText(message);
}
}

View File

@ -0,0 +1,34 @@
logging:
level:
dao: debug
youfool.dao: info
com.chinaweal.youfool.framework.springboot.log: debug
com.chinaweal.youfool.devops: debug
spring:
datasource:
youfool:
url: jdbc:oracle:thin:@172.22.80.186:1521:chinaweal
username: devops
password: 123456
devops:
url: jdbc:oracle:thin:@172.22.80.186:1521:chinaweal
username: devops
password: 123456
file:
devopsDir: D:\chinaweal\gitea-code\youfool-project\youfool-devops\upload
business:
fsLoginUrl: http://121.8.152.130:9888/tzrysb/user/loginDevops
sdLoginUrl: http://121.8.152.130:9888/tzrysb/user/loginDevops
fsUserInfoUrl: http://121.8.152.130:9888/tzrysb/user/searchUserDevops
sdUserInfoUrl: http://121.8.152.130:9888/tzrysb/user/searchUserDevops
#运维通报机器人
noticeWebhookKeys: 48de65c6-b068-4926-be25-e5935f4d1702,48de65c6-b068-4926-be25-e5935f4d1702#运维通报机器人
#数据账号密码过期机器人
dbWebhookKeys: 48de65c6-b068-4926-be25-e5935f4d1702
applicationName: devOps
swagger:
enable: true

Some files were not shown because too many files have changed in this diff Show More