diff --git a/epmet-admin/epmet-admin-client/src/main/java/com/epmet/dto/form/LogOperationListFormDTO.java b/epmet-admin/epmet-admin-client/src/main/java/com/epmet/dto/form/LogOperationListFormDTO.java new file mode 100644 index 0000000000..05e4de0032 --- /dev/null +++ b/epmet-admin/epmet-admin-client/src/main/java/com/epmet/dto/form/LogOperationListFormDTO.java @@ -0,0 +1,15 @@ +package com.epmet.dto.form; + +import lombok.Data; + +@Data +public class LogOperationListFormDTO { + + private String operatorName; + + private String operatorMobile; + + private Integer pageNo = 1; + + private Integer pageSize = 10; +} diff --git a/epmet-admin/epmet-admin-client/src/main/java/com/epmet/dto/region/LogOperationResultDTO.java b/epmet-admin/epmet-admin-client/src/main/java/com/epmet/dto/region/LogOperationResultDTO.java new file mode 100644 index 0000000000..a052b9dd2d --- /dev/null +++ b/epmet-admin/epmet-admin-client/src/main/java/com/epmet/dto/region/LogOperationResultDTO.java @@ -0,0 +1,49 @@ +package com.epmet.dto.region; + +import lombok.Data; + +import java.util.Date; + +/** + * + */ +@Data +public class LogOperationResultDTO { + + /** + * 大类别。登录login,项目流转project + */ + private String category; + /** + * 类型枚举,小类别。登录login,logout退出,shift_project议题转项目等 + */ + private String type; + + /** + * 类型枚举名称 + */ + private String typeDisplay; + + /** + * 内容 + */ + private String content; + + /** + * 操作目标ID + */ + private String targetId; + + /** + * 操作人ID + */ + private String operatorId; + private String operatorName; + private String operatorMobile; + + /** + * 操作时间,该时间不是插入数据的时间,而是操作发生的真实时间 + */ + private Date operatingTime; + +} diff --git a/epmet-admin/epmet-admin-client/src/main/java/com/epmet/enums/LogOperationTypeEnum.java b/epmet-admin/epmet-admin-client/src/main/java/com/epmet/enums/LogOperationTypeEnum.java new file mode 100644 index 0000000000..60baf21cc7 --- /dev/null +++ b/epmet-admin/epmet-admin-client/src/main/java/com/epmet/enums/LogOperationTypeEnum.java @@ -0,0 +1,39 @@ +package com.epmet.enums; + +/** + * 操作日志类型枚举 + */ +public enum LogOperationTypeEnum { + LOGIN("login", "登录"), + LOGOUT("logout", "退出登录"), + ISSUE_SHIFT_PROJECT("issue_shift_project", "议题转项目"), + CLOSE_PROJECT("close_project", "项目结案"), + PROJECT_TRANSFER("project_transfer", "项目流转"), + PROJECT_RESPONSE("project_response", "响应处理"), + PROJECT_APPROVAL("project_approval", "项目立项"); + + private String type; + private String typeDisplay; + + LogOperationTypeEnum(String type, String typeDisplay) { + this.type = type; + this.typeDisplay = typeDisplay; + } + + public static LogOperationTypeEnum get(String type) { + for (LogOperationTypeEnum t : LogOperationTypeEnum.values()) { + if (t.type.equals(type)) { + return t; + } + } + return null; + } + + public static String getDisplay(String type) { + LogOperationTypeEnum object = get(type); + if (object == null) { + return null; + } + return object.typeDisplay; + } +} diff --git a/epmet-admin/epmet-admin-server/pom.xml b/epmet-admin/epmet-admin-server/pom.xml index df371df8a9..15e142e3dd 100644 --- a/epmet-admin/epmet-admin-server/pom.xml +++ b/epmet-admin/epmet-admin-server/pom.xml @@ -54,6 +54,21 @@ feign-httpclient 10.3.0 + + + + com.epmet + epmet-commons-rocketmq + 2.0.0 + + + + + com.epmet + epmet-user-client + 2.0.0 + compile + @@ -109,6 +124,10 @@ false + + + 192.168.1.130:9876;192.168.1.132:9876 + epmet_message @@ -122,14 +141,14 @@ - + epmet_admin_user EpmEt-db-UsEr 0 - 192.168.1.130 - 6379 + 118.190.150.119 + 47379 123456 false @@ -141,6 +160,10 @@ false + + + 192.168.1.130:9876;192.168.1.132:9876 + epmet_message @@ -170,6 +193,10 @@ true + + + 192.168.10.161:9876 + epmet_message @@ -199,6 +226,10 @@ true + + + 192.168.11.187:9876;192.168.11.184:9876 + epmet_message diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/AdminApplication.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/AdminApplication.java index 89ac2c70d8..ea0ca31624 100644 --- a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/AdminApplication.java +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/AdminApplication.java @@ -10,6 +10,8 @@ package com.epmet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; /** * 管理后台 @@ -18,6 +20,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @since 1.0.0 */ @SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients public class AdminApplication { public static void main(String[] args) { diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/controller/LogOperationController.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/controller/LogOperationController.java new file mode 100644 index 0000000000..cc19f5dc36 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/controller/LogOperationController.java @@ -0,0 +1,45 @@ +package com.epmet.controller; + +import com.epmet.commons.tools.security.user.LoginUserUtil; +import com.epmet.commons.tools.utils.Result; +import com.epmet.commons.tools.validator.ValidatorUtils; +import com.epmet.dto.form.LogOperationListFormDTO; +import com.epmet.dto.region.LogOperationResultDTO; +import com.epmet.service.LogOperationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +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 java.util.ArrayList; +import java.util.List; + +@RequestMapping("log/operation") +@RestController +public class LogOperationController { + + @Autowired + private LogOperationService logOperationService; + + @Autowired + private LoginUserUtil loginUserUtil; + + @PostMapping("/list") + public Result> listLogOperations(@RequestBody LogOperationListFormDTO input) { + ValidatorUtils.validateEntity(input); + String operatorMobile = input.getOperatorMobile(); + String operatorName = input.getOperatorName(); + Integer pageNo = input.getPageNo(); + Integer pageSize = input.getPageSize(); + + String customerId = loginUserUtil.getLoginUserCustomerId(); + List resultList = logOperationService.listOperationLogs(operatorName, operatorMobile, customerId, pageNo, pageSize); + if (CollectionUtils.isEmpty(resultList)) { + resultList = new ArrayList<>(); + } + return new Result>().ok(resultList); + } + +} diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/dao/LogOperationDao.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/dao/LogOperationDao.java new file mode 100644 index 0000000000..a63a5aa8e4 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/dao/LogOperationDao.java @@ -0,0 +1,33 @@ +/** + * Copyright 2018 人人开源 https://www.renren.io + *

+ * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.epmet.dao; + +import com.epmet.commons.mybatis.dao.BaseDao; +import com.epmet.entity.LogOperationEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 操作日指标 + * + * @author generator generator@elink-cn.com + * @since v1.0.0 2021-06-07 + */ +@Mapper +public interface LogOperationDao extends BaseDao { + +} \ No newline at end of file diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/entity/LogOperationEntity.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/entity/LogOperationEntity.java new file mode 100644 index 0000000000..54a141651a --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/entity/LogOperationEntity.java @@ -0,0 +1,70 @@ +/** + * Copyright 2018 人人开源 https://www.renren.io + *

+ * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.epmet.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import com.epmet.commons.mybatis.entity.BaseEpmetEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 操作日指标 + * + * @author generator generator@elink-cn.com + * @since v1.0.0 2021-06-07 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("log_operation") +public class LogOperationEntity extends BaseEpmetEntity { + + private static final long serialVersionUID = 1L; + + /** + * 大类别。登录login,项目流转project + */ + private String category; + /** + * 类型枚举,小类别。登录login,logout退出,shift_project议题转项目等 + */ + private String type; + + /** + * 内容 + */ + private String content; + + /** + * 操作目标ID + */ + private String targetId; + + /** + * 操作人ID + */ + private String operatorId; + + /** + * 操作时间,该时间不是插入数据的时间,而是操作发生的真实时间 + */ + private Date operatingTime; + +} diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/mq/listener/RocketMQConsumerRegister.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/mq/listener/RocketMQConsumerRegister.java new file mode 100644 index 0000000000..f722f40a72 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/mq/listener/RocketMQConsumerRegister.java @@ -0,0 +1,66 @@ +package com.epmet.mq.listener; + +import com.epmet.commons.rocketmq.constants.ConsomerGroupConstants; +import com.epmet.commons.rocketmq.constants.TopicConstants; +import com.epmet.commons.tools.enums.EnvEnum; +import com.epmet.mq.listener.listener.OperationLogListener; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +@Component +public class RocketMQConsumerRegister { + @Value("${spring.profiles.active}") + private String env; + @Value("${rocketmq.name-server}") + private String nameServer; + + /** + * @return + * @Description 注册监听器 + * @author wxz + * @date 2021.03.03 16:09 + */ + @PostConstruct + public void registerAllListeners() { + try { + //if (!EnvEnum.LOCAL.getCode().equals(env)) { + register(nameServer, ConsomerGroupConstants.OPERATION_LOG_GROUP, MessageModel.CLUSTERING, TopicConstants.OPERATION_LOG, "*", new OperationLogListener()); + //} + } catch (MQClientException e) { + e.printStackTrace(); + } + } + + public void register(String nameServer, String group, MessageModel messageModel, String topic, String subException, MessageListenerConcurrently listener) throws MQClientException { + // 实例化消费者 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(group); + + // 设置NameServer的地址 + consumer.setNamesrvAddr(nameServer); + consumer.setMessageModel(messageModel); + consumer.setInstanceName(buildInstanceName()); + // 订阅一个或者多个Topic,以及Tag来过滤需要消费的消息 + consumer.subscribe(topic, subException); + // 注册回调实现类来处理从broker拉取回来的消息 + consumer.registerMessageListener(listener); + // 启动消费者实例 + consumer.start(); + } + + private String buildInstanceName() { + String instanceName = ""; + for (int i = 0; i < 4; i++) { + int t = (int) (Math.random() * 10); + instanceName = instanceName.concat(t + ""); + } + + return instanceName; + } + +} diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/mq/listener/listener/OperationLogListener.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/mq/listener/listener/OperationLogListener.java new file mode 100644 index 0000000000..55bf16fd99 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/mq/listener/listener/OperationLogListener.java @@ -0,0 +1,76 @@ +package com.epmet.mq.listener.listener; + +import com.alibaba.fastjson.JSON; +import com.epmet.commons.rocketmq.messages.OperationLogMQMsg; +import com.epmet.commons.tools.distributedlock.DistributedLock; +import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.commons.tools.exception.RenException; +import com.epmet.commons.tools.utils.SpringContextUtils; +import com.epmet.service.LogOperationService; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import org.redisson.api.RLock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author wxz + * @Description 操作日志监听器 + + * @return + * @date 2021.06.07 16:12 + * + * + * { + * "type": "login", + * "content": "我登录了", + * "targetId": "11", + * "operatorId": "2", + * "operatingTime": "1623056525000" + * } + */ +public class OperationLogListener implements MessageListenerConcurrently { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + try { + msgs.forEach(msg -> consumeMessage(msg)); + } catch (Exception e) { + logger.error(ExceptionUtils.getErrorStackTrace(e)); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + + private void consumeMessage(MessageExt messageExt) { + String tags = messageExt.getTags(); + String msg = new String(messageExt.getBody()); + logger.info("操作日志监听器-收到消息内容:{}", msg); + OperationLogMQMsg msgObj = JSON.parseObject(msg, OperationLogMQMsg.class); + + DistributedLock distributedLock = null; + RLock lock = null; + try { + distributedLock = SpringContextUtils.getBean(DistributedLock.class); + lock = distributedLock.getLock(String.format("lock:operation_log:%s:%s", msgObj.getType(), msgObj.getTargetId()), + 30L, 30L, TimeUnit.SECONDS); + SpringContextUtils.getBean(LogOperationService.class).log(msgObj, tags); + } catch (RenException e) { + // 如果是我们手动抛出的异常,说明在业务可控范围内。目前不需要MQ重试 + logger.error("【RocketMQ】添加操作日志失败:".concat(ExceptionUtils.getErrorStackTrace(e))); + } catch (Exception e) { + // 不是我们自己抛出的异常,可以让MQ重试 + logger.error("【RocketMQ】添加操作日志失败:".concat(ExceptionUtils.getErrorStackTrace(e))); + throw e; + } finally { + distributedLock.unLock(lock); + } + } +} diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/LogOperationService.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/LogOperationService.java new file mode 100644 index 0000000000..dec11275c8 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/LogOperationService.java @@ -0,0 +1,28 @@ +package com.epmet.service; + +import com.epmet.commons.rocketmq.messages.OperationLogMQMsg; +import com.epmet.dto.region.LogOperationResultDTO; + +import java.util.List; + +/** + * 操作日志 + */ +public interface LogOperationService { + + /** + * @Description 记录日志 + * @return + * @author wxz + * @date 2021.06.07 21:56 + */ + void log(OperationLogMQMsg msg, String category); + + /** + * @Description 查询操作日志 列表 + * @return + * @author wxz + * @date 2021.06.07 21:56 + */ + List listOperationLogs(String operatorName, String operatorMobile, String customerId, Integer pageNo, Integer pageSize); +} diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/LogOperationServiceImpl.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/LogOperationServiceImpl.java new file mode 100644 index 0000000000..5d247e93a3 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/LogOperationServiceImpl.java @@ -0,0 +1,186 @@ +package com.epmet.service.impl; + +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.extension.plugins.pagination.Page; +import com.epmet.commons.rocketmq.messages.OperationLogMQMsg; +import com.epmet.commons.tools.constant.ServiceConstant; +import com.epmet.commons.tools.exception.EpmetErrorCode; +import com.epmet.commons.tools.exception.RenException; +import com.epmet.commons.tools.feign.ResultDataResolver; +import com.epmet.commons.tools.utils.Result; +import com.epmet.dao.LogOperationDao; +import com.epmet.dto.CustomerStaffDTO; +import com.epmet.dto.form.CustomerStaffFormDTO; +import com.epmet.dto.form.ThirdCustomerStaffFormDTO; +import com.epmet.dto.region.LogOperationResultDTO; +import com.epmet.entity.LogOperationEntity; +import com.epmet.enums.LogOperationTypeEnum; +import com.epmet.feign.EpmetUserOpenFeignClient; +import com.epmet.service.LogOperationService; +import com.github.pagehelper.PageHelper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class LogOperationServiceImpl implements LogOperationService, ResultDataResolver { + + @Autowired + private LogOperationDao logOperationDao; + + @Autowired + private EpmetUserOpenFeignClient userOpenFeignClient; + + @Override + public void log(OperationLogMQMsg msg, String category) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(LogOperationEntity::getType, msg.getType()); + w.eq(LogOperationEntity::getTargetId, msg.getTargetId()); + w.eq(LogOperationEntity::getOperatorId, msg.getOperatorId()); + w.eq(LogOperationEntity::getOperatingTime, msg.getOperatingTime()); + + Integer existsCount = logOperationDao.selectCount(w); + if (existsCount > 0) { + // 该日志已存在,不做任何操作 + return; + } + + LogOperationEntity insert = new LogOperationEntity(); + insert.setContent(msg.getContent()); + insert.setOperatingTime(msg.getOperatingTime()); + insert.setOperatorId(msg.getOperatorId()); + insert.setTargetId(msg.getTargetId()); + insert.setType(msg.getType()); + insert.setCategory(category); + logOperationDao.insert(insert); + } + + @Override + public List listOperationLogs(String operatorName, String operatorMobile, String customerId, Integer pageNo, Integer pageSize) { + // 1.条件查询 + if (StringUtils.isNotBlank(operatorMobile)) { + return listByOperatorMobile(operatorMobile, customerId, pageNo, pageSize); + } else if (StringUtils.isNotBlank(operatorName)) { + return listByOperatorName(operatorName, pageNo, pageSize); + } + + // 2.直接分页查询 + // 条件查询,排序 + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.orderByDesc(LogOperationEntity::getOperatingTime); + IPage iPage = logOperationDao.selectPage(new Page<>(pageNo, pageSize), w); + List logs = iPage.getRecords(); + List userIds = logs.stream().map(l -> l.getOperatorId()).collect(Collectors.toList()); + + return convertLogOperationEntity2DTO(logs, getStaffMapByUserIds(userIds)); + } + + private Map getStaffMapByUserIds(List userIds) { + CustomerStaffFormDTO form = new CustomerStaffFormDTO(); + form.setUserIds(userIds); + Result> result = userOpenFeignClient.list(form); + List staffs = getResultDataOrThrowsException(result, ServiceConstant.EPMET_USER_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "调用user服务发生异常"); + + HashMap staffMap = new HashMap<>(); + staffs.forEach(s -> { + staffMap.put(s.getUserId(), s); + }); + + return staffMap; + } + + /** + * 通过操作人手机号查询操作日志列表 + * + * @param operatorMobile + * @param customerId + */ + private List listByOperatorMobile(String operatorMobile, String customerId, Integer pageNo, Integer pageSize) { + CustomerStaffFormDTO form = new CustomerStaffFormDTO(); + form.setCustomerId(customerId); + form.setMobile(operatorMobile); + Result> result = userOpenFeignClient.list(form); + List staffs = getResultDataOrThrowsException(result, ServiceConstant.EPMET_USER_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "调用user服务发生异常"); + + if (staffs.size() == 0) { + return null; + } + CustomerStaffDTO staff = staffs.get(0); + + QueryWrapper w = new QueryWrapper<>(); + w.lambda() + .eq(LogOperationEntity::getOperatorId, staff.getUserId()) + .eq(LogOperationEntity::getDelFlag, 0) + .orderByDesc(LogOperationEntity::getOperatingTime); + + IPage iPage = logOperationDao.selectPage(new Page<>(pageNo, pageSize), w); + + HashMap staffMap = new HashMap<>(); + staffMap.put(staff.getUserId(), staff); + + return convertLogOperationEntity2DTO(iPage.getRecords(), staffMap); + } + + /** + * @Description 通过操作人姓名查询操作日志列表 + * @return + * @author wxz + * @date 2021.06.08 11:12 + */ + private List listByOperatorName(String operatorName, Integer pageNo, Integer pageSize) { + CustomerStaffFormDTO form = new CustomerStaffFormDTO(); + form.setRealName(operatorName); + Result> result = userOpenFeignClient.list(form); + List staffs = getResultDataOrThrowsException(result, ServiceConstant.EPMET_USER_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "调用user服务查询工作人员信息发生异常"); + + List userIds = new ArrayList<>(); + HashMap staffMap = new HashMap(); + staffs.forEach(s -> { + staffMap.put(s.getUserId(), s); + userIds.add(s.getUserId()); + }); + + if (CollectionUtils.isEmpty(userIds)) { + return new ArrayList<>(); + } + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.in(LogOperationEntity::getOperatorId, userIds); + w.eq(LogOperationEntity::getDelFlag, 0); + w.orderByDesc(LogOperationEntity::getOperatingTime); + + IPage iPage = logOperationDao.selectPage(new Page<>(pageNo, pageSize), w); + + return convertLogOperationEntity2DTO(iPage.getRecords(), staffMap); + } + + /** + * @Description 将操作日志entity转化为dto列表 + * @return + * @author wxz + * @date 2021.06.08 11:12 + */ + private List convertLogOperationEntity2DTO(List logOperationEntities, Map staffMap) { + return logOperationEntities.stream().map(l -> { + LogOperationResultDTO ldto = new LogOperationResultDTO(); + ldto.setCategory(l.getCategory()); + ldto.setContent(l.getContent()); + ldto.setOperatingTime(l.getOperatingTime()); + ldto.setOperatorId(l.getOperatorId()); + ldto.setTargetId(l.getTargetId()); + ldto.setType(l.getType()); + ldto.setTypeDisplay(LogOperationTypeEnum.getDisplay(l.getType())); + ldto.setOperatorMobile(staffMap.get(l.getOperatorId()).getMobile()); + ldto.setOperatorName(staffMap.get(l.getOperatorId()).getRealName()); + return ldto; + }).collect(Collectors.toList()); + } +} diff --git a/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml b/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml index 89f42ed404..0d9082cec3 100644 --- a/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml +++ b/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml @@ -134,3 +134,6 @@ shutdown: graceful: enable: true #是否开启优雅停机 waitTimeSecs: 30 # 优雅停机等待时间,超过30秒,发出告警 + +rocketmq: + name-server: @rocketmq.nameserver@ \ No newline at end of file diff --git a/epmet-admin/epmet-admin-server/src/main/resources/db/migration/V0.0.3__add_log_ope_table.sql b/epmet-admin/epmet-admin-server/src/main/resources/db/migration/V0.0.3__add_log_ope_table.sql new file mode 100644 index 0000000000..0613c1dd2c --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/resources/db/migration/V0.0.3__add_log_ope_table.sql @@ -0,0 +1,15 @@ +CREATE TABLE `log_operation` ( + `ID` varchar(64) NOT NULL COMMENT '主键ID', + `TYPE` varchar(64) NOT NULL COMMENT '类型枚举', + `CONTENT` varchar(512) NOT NULL COMMENT '内容', + `CATEGORY` varchar(64) NOT NULL COMMENT '类别', + `TARGET_ID` varchar(64) NOT NULL COMMENT '操作目标ID', + `OPERATOR_ID` varchar(64) NOT NULL COMMENT '操作人ID', + `OPERATING_TIME` datetime NOT NULL COMMENT '操作时间,该时间不是插入数据的时间,而是操作发生的真实时间', + `DEL_FLAG` int(11) NOT NULL DEFAULT '0' COMMENT '删除标识 0.未删除 1.已删除', + `REVISION` int(11) NOT NULL COMMENT '乐观锁', + `CREATED_BY` varchar(32) NOT NULL COMMENT '创建人', + `CREATED_TIME` datetime NOT NULL COMMENT '创建时间', + `UPDATED_BY` varchar(32) NOT NULL COMMENT '更新人', + `UPDATED_TIME` datetime NOT NULL COMMENT '更新时间' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日指标' \ No newline at end of file diff --git a/epmet-admin/epmet-admin-server/src/main/resources/mapper/LogOperationDao.xml b/epmet-admin/epmet-admin-server/src/main/resources/mapper/LogOperationDao.xml new file mode 100644 index 0000000000..f63500d118 --- /dev/null +++ b/epmet-admin/epmet-admin-server/src/main/resources/mapper/LogOperationDao.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/ConsomerGroupConstants.java b/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/ConsomerGroupConstants.java index 5acfebb90e..e6d4732409 100644 --- a/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/ConsomerGroupConstants.java +++ b/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/ConsomerGroupConstants.java @@ -31,4 +31,9 @@ public interface ConsomerGroupConstants { */ String GROUP_ACHIEVEMENT_COMPONENTS_GROUP = "group_achievement_components_group"; + /** + * 操作日志组 + */ + String OPERATION_LOG_GROUP = "operation_log_group"; + } diff --git a/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/TopicConstants.java b/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/TopicConstants.java index bd9fed05eb..99a9b839c9 100644 --- a/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/TopicConstants.java +++ b/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/constants/TopicConstants.java @@ -13,4 +13,9 @@ public interface TopicConstants { * 小组成就 */ String GROUP_ACHIEVEMENT = "group_achievement"; + + /** + * 操作日志 + */ + String OPERATION_LOG = "operation_log"; } diff --git a/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/messages/OperationLogMQMsg.java b/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/messages/OperationLogMQMsg.java new file mode 100644 index 0000000000..95e3956114 --- /dev/null +++ b/epmet-commons/epmet-commons-rocketmq/src/main/java/com/epmet/commons/rocketmq/messages/OperationLogMQMsg.java @@ -0,0 +1,16 @@ +package com.epmet.commons.rocketmq.messages; + +import lombok.Data; + +import java.util.Date; + +@Data +public class OperationLogMQMsg { + + private String type; + private String content; + private String targetId; + private String operatorId; + private Date operatingTime; + +} diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/feign/ResultDataResolver.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/feign/ResultDataResolver.java new file mode 100644 index 0000000000..1e44b924c2 --- /dev/null +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/feign/ResultDataResolver.java @@ -0,0 +1,50 @@ +package com.epmet.commons.tools.feign; + +import com.epmet.commons.tools.exception.EpmetErrorCode; +import com.epmet.commons.tools.exception.RenException; +import com.epmet.commons.tools.utils.Result; +import org.apache.commons.lang3.StringUtils; + +/** + * Feign请求结果解析器 + */ +public interface ResultDataResolver { + + /** + * @Description 获取Result种的data,如果失败(返回result为null或者result.success为false),那么返回null + * @return + * @author wxz + * @date 2021.06.07 22:45 + */ + //default R tryGetResultData(Result result, String targetServiceName) { + // Logger logger = LoggerFactory.getLogger(ResultDataResolver.class); + // if (result == null) { + // logger.error("调用{}服务发生错误,返回Result为null", targetServiceName); + // return null; + // } + // if (!result.success()) { + // logger.error("调用{}服务发生错误,错误信息:{}", targetServiceName, result.getInternalMsg()); + // return null; + // } + // return result.getData(); + //} + + /** + * @Description 获取Result种的data,如果失败(返回result为null或者result.success为false),那么抛出异常 + * @return + * @author wxz + * @date 2021.06.07 22:45 + */ + default R getResultDataOrThrowsException(Result result, String targetServiceName, Integer errorCode, String errorInternalMsg) { + if (result == null) { + throw new RenException(EpmetErrorCode.SERVER_ERROR.getCode(), "调用{}服务发生错误,返回Result为null", targetServiceName); + } + if (!result.success()) { + Integer finalErrorCode = errorCode == null ? result.getCode() : errorCode; + String finalErrorInternalMsg = StringUtils.isBlank(errorInternalMsg) ? result.getInternalMsg() : errorInternalMsg; + throw new RenException(finalErrorCode, finalErrorInternalMsg); + } + return result.getData(); + } + +} diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/CustomerStaffFormDTO.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/CustomerStaffFormDTO.java index 43acb11d1c..f5317723e6 100644 --- a/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/CustomerStaffFormDTO.java +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/CustomerStaffFormDTO.java @@ -4,6 +4,7 @@ import lombok.Data; import javax.validation.constraints.NotBlank; import java.io.Serializable; +import java.util.List; /** * @Description 根据手机号+客户id获取工作人员基本信息 @@ -13,9 +14,23 @@ import java.io.Serializable; @Data public class CustomerStaffFormDTO implements Serializable { private static final long serialVersionUID = 7619815083427853431L; - @NotBlank(message = "手机号不能为空") + + // 根据手机号+客户id获取工作人员基本信息 + public interface GetCustomerStaffInfo {} + + @NotBlank(message = "手机号不能为空", groups = { GetCustomerStaffInfo.class }) private String mobile; - @NotBlank(message = "客户id不能为空") + @NotBlank(message = "客户id不能为空", groups = { GetCustomerStaffInfo.class }) private String customerId; + + /** + * 姓名 + */ + private String realName; + + /** + * 用户id集合 + */ + private List userIds; } diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java index f85ba6d782..ea092ea63a 100644 --- a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java @@ -21,8 +21,8 @@ import java.util.Map; * @author yinzuomei@elink-cn.com * @date 2020/6/4 13:09 */ -//@FeignClient(name = ServiceConstant.EPMET_USER_SERVER, fallback = EpmetUserOpenFeignClientFallback.class, url = "localhost:8087") -@FeignClient(name = ServiceConstant.EPMET_USER_SERVER, fallback = EpmetUserOpenFeignClientFallback.class) +@FeignClient(name = ServiceConstant.EPMET_USER_SERVER, fallback = EpmetUserOpenFeignClientFallback.class, url = "http://127.0.0.1:8087") +//@FeignClient(name = ServiceConstant.EPMET_USER_SERVER, fallback = EpmetUserOpenFeignClientFallback.class) public interface EpmetUserOpenFeignClient { /** @@ -224,7 +224,7 @@ public interface EpmetUserOpenFeignClient { * @Author sun * @Description 根据客户ID、手机号查询政府端工作人员基本信息,校验用户是否存在 **/ - @GetMapping(value = "epmetuser/customerstaff/getCustsomerStaffByIdAndPhone") + @GetMapping(value = "/epmetuser/customerstaff/getCustsomerStaffByIdAndPhone") Result> getCustsomerStaffByIdAndPhone(@RequestBody ThirdCustomerStaffFormDTO formDTO); /** @@ -530,4 +530,24 @@ public interface EpmetUserOpenFeignClient { */ @PostMapping("/epmetuser/badge/userbadges") Result> userBadges(@RequestBody UserBadgesFormDTO formDTO); + + /** + * 根据用户ID获取工作人员基本信息 + * + * @param formDTO + * @return com.epmet.commons.tools.utils.Result + * @author zhaoqifeng + * @date 2020/4/22 10:05 + **/ + @PostMapping(value = "/epmetuser/customerstaff/getstaffinfobyuserid") + Result getCustomerStaffInfoByUserId(@RequestBody CustomerStaffDTO formDTO); + + /** + * @Description 通用批量查询 + * @return + * @author wxz + * @date 2021.06.08 10:54 + */ + @PostMapping(value = "/epmetuser/customerstaff/list") + Result> list(CustomerStaffFormDTO input); } diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java index 518cca9cef..3e0ee743e1 100644 --- a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java @@ -373,4 +373,14 @@ public class EpmetUserOpenFeignClientFallback implements EpmetUserOpenFeignClien public Result> userBadges(UserBadgesFormDTO formDTO) { return ModuleUtils.feignConError(ServiceConstant.EPMET_USER_SERVER, "userBadges", formDTO); } + + @Override + public Result getCustomerStaffInfoByUserId(CustomerStaffDTO formDTO) { + return ModuleUtils.feignConError(ServiceConstant.EPMET_USER_SERVER, "getCustomerStaffInfoByUserId", formDTO); + } + + @Override + public Result> list(CustomerStaffFormDTO input) { + return ModuleUtils.feignConError(ServiceConstant.EPMET_USER_SERVER, "list", input); + } } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/CustomerStaffController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/CustomerStaffController.java index e1eefc0a94..d488ecff59 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/CustomerStaffController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/CustomerStaffController.java @@ -20,6 +20,7 @@ package com.epmet.controller; import com.epmet.commons.tools.annotation.LoginUser; import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.security.dto.TokenDto; +import com.epmet.commons.tools.security.user.LoginUserUtil; import com.epmet.commons.tools.utils.ExcelUtils; import com.epmet.commons.tools.utils.Result; import com.epmet.commons.tools.validator.AssertUtils; @@ -32,10 +33,12 @@ import com.epmet.dto.form.*; import com.epmet.dto.result.*; import com.epmet.excel.CustomerStaffExcel; import com.epmet.service.CustomerStaffService; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotBlank; import java.util.List; import java.util.Map; @@ -53,6 +56,9 @@ public class CustomerStaffController { @Autowired private CustomerStaffService customerStaffService; + @Autowired + private LoginUserUtil loginUserUtil; + @GetMapping("page") public Result> page(@RequestParam Map params) { PageData page = customerStaffService.page(params); @@ -116,7 +122,7 @@ public class CustomerStaffController { **/ @PostMapping(value = "getcustomerstaffinfo") public Result getCustomerStaffInfo(@RequestBody CustomerStaffFormDTO formDTO) { - ValidatorUtils.validateEntity(formDTO); + ValidatorUtils.validateEntity(formDTO, CustomerStaffFormDTO.GetCustomerStaffInfo.class); return customerStaffService.getCustomerStaffInfo(formDTO); } @@ -410,4 +416,19 @@ public class CustomerStaffController { return new Result().ok(customerStaffService.getStaffBasicInfo(fromDTO)); } + /** + * @Description 通用列表查询。可以指定customerId,如果指定了,则使用指定的,如果未指定,则使用当前登录用户的customerId + * @return + * @author wxz + * @date 2021.06.08 10:54 + */ + @PostMapping("list") + public Result> list(@RequestBody CustomerStaffFormDTO input) { + String customerId = StringUtils.isBlank(input.getCustomerId()) ? loginUserUtil.getLoginUserCustomerId() : input.getCustomerId(); + + List staffs = customerStaffService.list(customerId, input.getRealName(), input.getMobile(), input.getUserIds()); + return new Result>().ok(staffs); + } + + } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/CustomerStaffDao.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/CustomerStaffDao.java index acffa2840e..fc8b35d778 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/CustomerStaffDao.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/CustomerStaffDao.java @@ -197,4 +197,12 @@ public interface CustomerStaffDao extends BaseDao { * @return */ BasicInfoResultDTO getStaffBasicInfo(StaffBasicInfoFromDTO fromDTO); + + /** + * 通用列表查询 + * @param customerId + * @param realName + * @return + */ + List listDTOS(@Param("customerId") String customerId, @Param("realName") String realName, @Param("mobile") String mobile, @Param("userIds") List userIds); } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/CustomerStaffService.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/CustomerStaffService.java index 833791fc54..7f5b43161e 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/CustomerStaffService.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/CustomerStaffService.java @@ -321,4 +321,12 @@ public interface CustomerStaffService extends BaseService { * @return */ BasicInfoResultDTO getStaffBasicInfo(StaffBasicInfoFromDTO fromDTO); + + /** + * @Description 根据姓名查询工作人员 + * @return + * @author wxz + * @date 2021.06.08 10:52 + */ + List list(String customerId, String realName, String mobile, List ids); } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/CustomerStaffServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/CustomerStaffServiceImpl.java index e52b9441ae..983ee63637 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/CustomerStaffServiceImpl.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/CustomerStaffServiceImpl.java @@ -18,6 +18,7 @@ package com.epmet.service.impl; import com.alibaba.fastjson.JSON; +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.epmet.commons.mybatis.entity.DataScope; @@ -56,6 +57,7 @@ import com.epmet.service.GovStaffRoleService; import com.epmet.service.StaffRoleService; import com.epmet.service.UserService; import com.epmet.util.ModuleConstant; +import kotlin.jvm.internal.Lambda; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; @@ -699,4 +701,8 @@ public class CustomerStaffServiceImpl extends BaseServiceImpl list(String customerId, String realName, String mobile, List userIds) { + return baseDao.listDTOS(customerId, realName, mobile, userIds); + } } diff --git a/epmet-user/epmet-user-server/src/main/resources/mapper/CustomerStaffDao.xml b/epmet-user/epmet-user-server/src/main/resources/mapper/CustomerStaffDao.xml index eab3a42191..725df08c21 100644 --- a/epmet-user/epmet-user-server/src/main/resources/mapper/CustomerStaffDao.xml +++ b/epmet-user/epmet-user-server/src/main/resources/mapper/CustomerStaffDao.xml @@ -357,4 +357,46 @@ AND user_id = #{staffId} LIMIT 1 + +