|
|
@@ -0,0 +1,488 @@
|
|
|
+package com.ruoyi.web.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.ruoyi.common.core.domain.entity.SysUser;
|
|
|
+import com.ruoyi.common.enums.BusinessType;
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
+import com.ruoyi.common.utils.SecurityUtils;
|
|
|
+import com.ruoyi.common.utils.bean.BeanUtils;
|
|
|
+import com.ruoyi.system.mapper.SysUserMapper;
|
|
|
+import com.ruoyi.system.service.ISysRoleService;
|
|
|
+import com.ruoyi.system.service.ISysUserService;
|
|
|
+import com.ruoyi.web.domain.dto.event.EventAddRequest;
|
|
|
+import com.ruoyi.web.domain.dto.event.EventEditRequest;
|
|
|
+import com.ruoyi.web.domain.dto.event.EventQueryRequest;
|
|
|
+import com.ruoyi.web.domain.entity.Event;
|
|
|
+import com.ruoyi.web.domain.entity.EventAssign;
|
|
|
+import com.ruoyi.web.domain.vo.event.EventVO;
|
|
|
+import com.ruoyi.web.mapper.EventAssignMapper;
|
|
|
+import com.ruoyi.web.mapper.EventMapper;
|
|
|
+import com.ruoyi.web.service.EventService;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class EventServiceImpl extends ServiceImpl<EventMapper, Event>
|
|
|
+ implements EventService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private EventAssignMapper eventAssignMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ISysUserService sysUserService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ISysRoleService sysRoleService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SysUserMapper sysUserMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加事件并分配给对应负责人
|
|
|
+ *
|
|
|
+ * @param eventAddRequest
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Integer addEvent(EventAddRequest eventAddRequest) {
|
|
|
+ if (eventAddRequest == null) {
|
|
|
+ throw new ServiceException("请求参数为空");
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 转换为实体对象
|
|
|
+ Event event = new Event();
|
|
|
+ BeanUtil.copyProperties(eventAddRequest, event);
|
|
|
+ //数据校验
|
|
|
+ validEvent(event, BusinessType.INSERT);
|
|
|
+
|
|
|
+ // 保存到事件表
|
|
|
+ this.save(event);
|
|
|
+
|
|
|
+ // 根据事件类型分配负责人
|
|
|
+ assignEventToPersons(event.getId(), event.getType());
|
|
|
+ return event.getId();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("添加事件失败", e);
|
|
|
+ throw new ServiceException("添加事件失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据事件类型分配负责人
|
|
|
+ *
|
|
|
+ * @param eventId 事件ID
|
|
|
+ * @param eventType 事件类型
|
|
|
+ */
|
|
|
+ private void assignEventToPersons(Integer eventId, Integer eventType) {
|
|
|
+ // 根据事件类型查找对应的负责人
|
|
|
+ List<Integer> personIds = getPersonIdsByEventType(eventType);
|
|
|
+
|
|
|
+ if (personIds.isEmpty()) {
|
|
|
+ throw new ServiceException("未找到事件类型对应的负责人");
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+ for (Integer personId : personIds) {
|
|
|
+ EventAssign eventAssign = new EventAssign();
|
|
|
+ eventAssign.setEventId(eventId);
|
|
|
+ eventAssign.setPersonId(personId);
|
|
|
+ eventAssign.setStatus("0"); // 未完结
|
|
|
+ eventAssign.setIsReassign("0"); // 非重新分配
|
|
|
+ eventAssign.setCreateTime(now);
|
|
|
+ eventAssign.setUpdateTime(now);
|
|
|
+ eventAssignMapper.insert(eventAssign);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据事件类型获取负责人ID列表
|
|
|
+ *
|
|
|
+ * @param eventType 事件类型
|
|
|
+ * @return 负责人ID列表
|
|
|
+ */
|
|
|
+ private List<Integer> getPersonIdsByEventType(Integer eventType) {
|
|
|
+ // 约定基于角色来选择负责人:通用命名:event_type_{n}
|
|
|
+ // 角色:event_type_0 -> 矛盾纠纷类 、 event_type_2 -> 消防隐患类
|
|
|
+ String key = "event_type_" + eventType;
|
|
|
+
|
|
|
+ // 使用专门的方法查询用户ID,避免数据权限问题
|
|
|
+ List<String> roleKeys = Arrays.asList(key);
|
|
|
+ List<Long> userIds = sysUserService.selectUserIdsByRoleKeysForEvent(roleKeys);
|
|
|
+
|
|
|
+ List<Integer> matchedUserIds = userIds.stream()
|
|
|
+ .map(Long::intValue)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 同时包含超级管理员(user_id = 1)
|
|
|
+ if (!matchedUserIds.contains(1)) {
|
|
|
+ matchedUserIds.add(1);
|
|
|
+ }
|
|
|
+ return matchedUserIds;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除
|
|
|
+ *
|
|
|
+ * @param ids
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean deleteEvent(String ids) {
|
|
|
+ if (StrUtil.isBlank(ids)) {
|
|
|
+ throw new ServiceException("id不能为空或id异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 分割ID字符串为List<Integer>
|
|
|
+ List<Long> idList = Arrays.stream(ids.split(","))
|
|
|
+ .map(String::trim)
|
|
|
+ .filter(StrUtil::isNotBlank)
|
|
|
+ .map(Long::parseLong)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (idList.isEmpty()) {
|
|
|
+ throw new ServiceException("ID格式异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 构建删除条件
|
|
|
+ QueryWrapper<Event> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.in("id", idList);
|
|
|
+
|
|
|
+ // 4. 执行删除(返回是否删除成功)
|
|
|
+ return remove(queryWrapper);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 编辑
|
|
|
+ *
|
|
|
+ * @param eventEditRequest
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void editEvent(EventEditRequest eventEditRequest) {
|
|
|
+ // 判断是否存在
|
|
|
+ Integer id = eventEditRequest.getId();
|
|
|
+ Event oldEvent = this.getById(id);
|
|
|
+ if (oldEvent == null) {
|
|
|
+ throw new ServiceException("没有找到事件");
|
|
|
+ }
|
|
|
+ Event event = new Event();
|
|
|
+ BeanUtil.copyProperties(eventEditRequest, event);
|
|
|
+ event.setUpdateTime(new Date());
|
|
|
+ // 数据校验
|
|
|
+ validEvent(event, BusinessType.UPDATE);
|
|
|
+
|
|
|
+ // 操作数据库
|
|
|
+ boolean result = this.updateById(event);
|
|
|
+ if (!result) {
|
|
|
+ throw new ServiceException("修改事件操作失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验数据
|
|
|
+ *
|
|
|
+ * @param event
|
|
|
+ */
|
|
|
+ public void validEvent(Event event, BusinessType type) {
|
|
|
+ if (ObjectUtil.isEmpty(event)) {
|
|
|
+ throw new ServiceException("数据为空");
|
|
|
+ }
|
|
|
+ // 从对象中取值
|
|
|
+ Integer id = event.getId();
|
|
|
+ Date occurTime = event.getOccurTime();
|
|
|
+ Integer eventType = event.getType();
|
|
|
+ String location = event.getLocation();
|
|
|
+ String description = event.getDescription();
|
|
|
+ String photoUrl = event.getPhotoUrl();
|
|
|
+ String status = event.getStatus();
|
|
|
+ Integer submitterId = event.getSubmitterId();
|
|
|
+ String processResult = event.getProcessResult();
|
|
|
+ Date processTime = event.getProcessTime();
|
|
|
+
|
|
|
+
|
|
|
+ // 添加id无需校验,修改时,id 不能为空
|
|
|
+ if (type != BusinessType.INSERT && ObjectUtil.isEmpty(id)) {
|
|
|
+ throw new ServiceException("id不能为空");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(occurTime)) {
|
|
|
+ throw new ServiceException("事件时间不能为空");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(eventType)) {
|
|
|
+ throw new ServiceException("事件类别不能为空");
|
|
|
+ }
|
|
|
+ if (StrUtil.isBlank(location)) {
|
|
|
+ throw new ServiceException("事件地点不能为空");
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(submitterId)) {
|
|
|
+ throw new ServiceException("填报人不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据id查询
|
|
|
+ *
|
|
|
+ * @param id
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public EventVO getEventById(int id) {
|
|
|
+ if (id <= 0) {
|
|
|
+ throw new ServiceException("id不能为空或id异常");
|
|
|
+ }
|
|
|
+ // 获取登录用户id
|
|
|
+ Long userId = SecurityUtils.getUserId();
|
|
|
+ Event event = new Event();
|
|
|
+ // 若不是管理员 指定查询的 负责人id 为当前登录用户id (负责人只能查询自己的事件)
|
|
|
+ if (SecurityUtils.isAdmin(userId)) {
|
|
|
+ // 管理员查询
|
|
|
+ event = this.getById(id);
|
|
|
+ } else {
|
|
|
+ // 负责人查询
|
|
|
+ QueryWrapper<Event> wrapper = new QueryWrapper<>();
|
|
|
+ wrapper.eq("id", id)
|
|
|
+ .exists("SELECT 1 FROM event_assign ea WHERE ea.event_id = event.id AND ea.person_id = " + userId);
|
|
|
+ event = this.getOne(wrapper);
|
|
|
+ }
|
|
|
+ return getEventVO(event);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取事件包装类
|
|
|
+ *
|
|
|
+ * @param event
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public EventVO getEventVO(Event event) {
|
|
|
+ if (ObjectUtil.isEmpty(event)) {
|
|
|
+ throw new ServiceException("请求参数不存在");
|
|
|
+ }
|
|
|
+ EventVO eventVO = new EventVO();
|
|
|
+ BeanUtils.copyProperties(event, eventVO);
|
|
|
+
|
|
|
+ // 查询事件的负责人信息
|
|
|
+ QueryWrapper<EventAssign> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("event_id", event.getId());
|
|
|
+ // 获取事件分配信息列表
|
|
|
+ List<EventAssign> eventAssigns = eventAssignMapper.selectList(queryWrapper);
|
|
|
+ // 3. 提取负责人ID列表
|
|
|
+ List<Integer> userIds = eventAssigns.stream()
|
|
|
+ .map(EventAssign::getPersonId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 4. 批量查询有效的用户信息
|
|
|
+ List<SysUser> chargeUserList = userIds.isEmpty() ?
|
|
|
+ Collections.emptyList() :
|
|
|
+ sysUserMapper.selectUserListForEvent(userIds);
|
|
|
+
|
|
|
+ // 实际项目中需要根据personId查询用户信息
|
|
|
+ eventVO.setChargeUserList(chargeUserList);
|
|
|
+
|
|
|
+ // 5. 查询处理人
|
|
|
+// queryWrapper.eq()
|
|
|
+
|
|
|
+ return eventVO;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页获取事件列表
|
|
|
+ *
|
|
|
+ * @param eventQueryRequest
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Page<EventVO> getListEventByPage(EventQueryRequest eventQueryRequest) {
|
|
|
+ long current = eventQueryRequest.getPageNum();
|
|
|
+ long size = eventQueryRequest.getPageSize();
|
|
|
+ // 获取登录用户id
|
|
|
+ Long userId = SecurityUtils.getUserId();
|
|
|
+ Page<Event> page;
|
|
|
+ // 若不是管理员 指定查询的 负责人id 为当前登录用户id (负责人只能查询自己的事件)
|
|
|
+ if (SecurityUtils.isAdmin(userId)) {
|
|
|
+ // 管理员查询
|
|
|
+ page = this.page(new Page<>(current, size),
|
|
|
+ getQueryWrapper(eventQueryRequest, null));
|
|
|
+ } else {
|
|
|
+ // 负责人查询
|
|
|
+ page = this.page(new Page<>(current, size),
|
|
|
+ getQueryWrapper(eventQueryRequest, Math.toIntExact(userId)));
|
|
|
+ }
|
|
|
+ Page<EventVO> eventVOPage = new Page<>();
|
|
|
+ BeanUtils.copyProperties(page, eventVOPage, "records");
|
|
|
+ List<EventVO> voList = page.getRecords().stream()
|
|
|
+ .map(event -> {
|
|
|
+ EventVO vo = getEventVO(event);
|
|
|
+ return vo;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ eventVOPage.setRecords(voList);
|
|
|
+ return eventVOPage;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取查询条件
|
|
|
+ *
|
|
|
+ * @param eventQueryRequest
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public QueryWrapper<Event> getQueryWrapper(EventQueryRequest eventQueryRequest, Integer userId) {
|
|
|
+ QueryWrapper<Event> queryWrapper = new QueryWrapper<>();
|
|
|
+ if (eventQueryRequest == null) {
|
|
|
+ return queryWrapper;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从对象中取值
|
|
|
+ Date startTime = eventQueryRequest.getStartTime();
|
|
|
+ Date endTime = eventQueryRequest.getEndTime();
|
|
|
+ Integer type = eventQueryRequest.getType();
|
|
|
+ String location = eventQueryRequest.getLocation();
|
|
|
+ String status = eventQueryRequest.getStatus();
|
|
|
+ Integer submitterId = eventQueryRequest.getSubmitterId();
|
|
|
+ String sortField = eventQueryRequest.getSortField();
|
|
|
+ String sortOrder = eventQueryRequest.getSortOrder();
|
|
|
+
|
|
|
+ // 事件类别、事发地点、填报人、状态
|
|
|
+ queryWrapper.eq(ObjectUtil.isNotEmpty(type), "type", type);
|
|
|
+ queryWrapper.eq(StrUtil.isNotBlank(location), "location", location);
|
|
|
+ queryWrapper.eq(StringUtils.isNotBlank(status), "status", status);
|
|
|
+ // 修正列名:submitter_id
|
|
|
+ queryWrapper.eq(ObjectUtil.isNotEmpty(submitterId), "submitter_id", submitterId);
|
|
|
+
|
|
|
+ // 如果负责人查询,则查询负责人的事件
|
|
|
+ if (ObjectUtil.isNotEmpty(userId)) {
|
|
|
+ queryWrapper.exists("SELECT 1 FROM event_assign ea WHERE ea.event_id = event.id AND ea.person_id = " + userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 事发时间范围查询(优先判断范围)
|
|
|
+ if (startTime != null && endTime != null) {
|
|
|
+ queryWrapper.between("occur_time", startTime, endTime);
|
|
|
+ } else if (startTime != null) {
|
|
|
+ queryWrapper.ge("occur_time", startTime); // >= 开始日期
|
|
|
+ } else if (endTime != null) {
|
|
|
+ queryWrapper.le("occur_time", endTime); // <= 结束日期
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField);
|
|
|
+ return queryWrapper;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 任一负责人处理事件:主表CAS(状态) + 分配表同步
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean handleEvent(Integer eventId, Integer personId, String processResult) {
|
|
|
+ if (eventId == null || personId == null) {
|
|
|
+ throw new ServiceException("参数不能为空");
|
|
|
+ }
|
|
|
+ // 1. 事件主表CAS:尝试抢占锁,只能修改状态为 0 的事件
|
|
|
+ UpdateWrapper<Event> casUpdate = new UpdateWrapper<>();
|
|
|
+ casUpdate.eq("id", eventId)
|
|
|
+ .eq("status", "0")
|
|
|
+ .set("status", "1")
|
|
|
+ .set("process_result", processResult)
|
|
|
+ .set("process_time", new Date())
|
|
|
+ .set("update_time", new Date());
|
|
|
+ int w = this.baseMapper.update(null, casUpdate);
|
|
|
+
|
|
|
+ if (w == 1) {
|
|
|
+ // 抢到锁:当前负责人状态 -> 1;其他事件负责人状态 -> 2
|
|
|
+ UpdateWrapper<EventAssign> meDone = new UpdateWrapper<>();
|
|
|
+ meDone.eq("event_id", eventId)
|
|
|
+ .eq("person_id", personId)
|
|
|
+ .eq("status", "0")
|
|
|
+ .set("status", "1")
|
|
|
+ .set("update_time", new Date());
|
|
|
+ eventAssignMapper.update(null, meDone);
|
|
|
+
|
|
|
+ UpdateWrapper<EventAssign> othersDone = new UpdateWrapper<>();
|
|
|
+ othersDone.eq("event_id", eventId)
|
|
|
+ .ne("person_id", personId)
|
|
|
+ .eq("status", "0")
|
|
|
+ .set("status", "2")
|
|
|
+ .set("update_time", new Date());
|
|
|
+ eventAssignMapper.update(null, othersDone);
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ // 抢锁失败:将当前负责人状态-> 2
|
|
|
+ UpdateWrapper<EventAssign> meLose = new UpdateWrapper<>();
|
|
|
+ meLose.eq("event_id", eventId)
|
|
|
+ .eq("person_id", personId)
|
|
|
+ .eq("status", "0")
|
|
|
+ .set("status", "2")
|
|
|
+ .set("update_time", new Date());
|
|
|
+ eventAssignMapper.update(null, meLose);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 再次派发:仅在事件未完结时允许;存在则重置为未完结并标记再派发,不存在则插入
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void reassignEvent(Integer eventId, List<Integer> personIds) {
|
|
|
+ if (eventId == null || personIds == null || personIds.isEmpty()) {
|
|
|
+ throw new ServiceException("参数不能为空");
|
|
|
+ }
|
|
|
+ // 校验事件未完结
|
|
|
+ Event event = this.getById(eventId);
|
|
|
+ if (event == null) {
|
|
|
+ throw new ServiceException("事件不存在");
|
|
|
+ }
|
|
|
+ if (!"0".equals(event.getStatus())) {
|
|
|
+ throw new ServiceException("事件已完结,无法再次派发");
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+ for (Integer uid : personIds) {
|
|
|
+ // 先尝试更新存在的数据
|
|
|
+ UpdateWrapper<EventAssign> reset = new UpdateWrapper<>();
|
|
|
+ reset.eq("event_id", eventId)
|
|
|
+ .eq("person_id", uid)
|
|
|
+ .set("status", "0")
|
|
|
+ .set("is_reassign", "1")
|
|
|
+ .set("update_time", now);
|
|
|
+ int a = eventAssignMapper.update(null, reset);
|
|
|
+ // 如果不是原来的事件负责人,添加分配记录
|
|
|
+ if (a == 0) {
|
|
|
+ // 插入新记录
|
|
|
+ EventAssign add = new EventAssign();
|
|
|
+ add.setEventId(eventId);
|
|
|
+ add.setPersonId(uid);
|
|
|
+ add.setStatus("0");
|
|
|
+ add.setIsReassign("1");
|
|
|
+ add.setCreateTime(now);
|
|
|
+ add.setUpdateTime(now);
|
|
|
+ eventAssignMapper.insert(add);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|