EventServiceImpl.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. package com.ruoyi.web.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  7. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  9. import com.ruoyi.common.enums.BusinessType;
  10. import com.ruoyi.common.exception.ServiceException;
  11. import com.ruoyi.common.utils.SecurityUtils;
  12. import com.ruoyi.common.utils.bean.BeanUtils;
  13. import com.ruoyi.web.domain.dto.event.EventAddRequest;
  14. import com.ruoyi.web.domain.dto.event.EventQueryRequest;
  15. import com.ruoyi.web.domain.entity.Event;
  16. import com.ruoyi.web.domain.entity.EventAssign;
  17. import com.ruoyi.web.domain.entity.PersonInfo;
  18. import com.ruoyi.web.domain.vo.PersonInfoVO;
  19. import com.ruoyi.web.domain.vo.event.EventVO;
  20. import com.ruoyi.web.mapper.EventAssignMapper;
  21. import com.ruoyi.web.mapper.EventMapper;
  22. import com.ruoyi.web.service.EventAssignService;
  23. import com.ruoyi.web.service.EventService;
  24. import com.ruoyi.web.service.EventTypeAssigneeService;
  25. import com.ruoyi.web.service.PersonInfoService;
  26. import org.apache.commons.lang3.StringUtils;
  27. import org.springframework.stereotype.Service;
  28. import org.springframework.transaction.annotation.Transactional;
  29. import javax.annotation.Resource;
  30. import java.util.Arrays;
  31. import java.util.Date;
  32. import java.util.List;
  33. import java.util.stream.Collectors;
  34. /**
  35. *
  36. */
  37. @Service
  38. public class EventServiceImpl extends ServiceImpl<EventMapper, Event>
  39. implements EventService {
  40. @Resource
  41. private EventAssignMapper eventAssignMapper;
  42. @Resource
  43. private PersonInfoService personInfoService;
  44. @Resource
  45. private EventAssignService eventAssignService;
  46. @Resource
  47. private EventTypeAssigneeService eventTypeAssigneeService;
  48. /**
  49. * 添加事件并分配给对应负责人
  50. *
  51. * @param eventAddRequest
  52. * @return
  53. */
  54. @Override
  55. @Transactional(rollbackFor = Exception.class)
  56. public Integer addEvent(EventAddRequest eventAddRequest) {
  57. if (eventAddRequest == null) {
  58. throw new ServiceException("请求参数为空");
  59. }
  60. try {
  61. // 转换为实体对象
  62. Event event = new Event();
  63. BeanUtil.copyProperties(eventAddRequest, event);
  64. // 通过系统用户id 获取对应 人口表id
  65. Long userId = SecurityUtils.getUserId();
  66. QueryWrapper<PersonInfo> wrapper = new QueryWrapper<>();
  67. wrapper.select("id")
  68. .eq("user_id",userId);
  69. List<PersonInfo> personInfoList = personInfoService.list(wrapper);
  70. if (!personInfoList.isEmpty()) {
  71. PersonInfo personInfo = personInfoList.get(0);
  72. event.setSubmitterId(personInfo.getId());
  73. } else {
  74. throw new ServiceException("找不到申报人");
  75. }
  76. //数据校验
  77. validEvent(event, BusinessType.INSERT);
  78. // 保存到事件表
  79. this.save(event);
  80. // 根据事件类型自动分配负责人
  81. assignEventToPersons(event.getId(), event.getType());
  82. return event.getId();
  83. } catch (Exception e) {
  84. log.error("添加事件失败", e);
  85. throw new ServiceException("添加事件失败");
  86. }
  87. }
  88. /**
  89. * 根据事件类型分配负责人
  90. *
  91. * @param eventId 事件ID
  92. * @param eventType 事件类型
  93. */
  94. private void assignEventToPersons(Integer eventId, Integer eventType) {
  95. // 根据事件类型查找对应的负责人 id 集合
  96. List<Integer> userIds = getPersonIdsByEventType(eventType);
  97. if (userIds.isEmpty()) {
  98. throw new ServiceException("未找到事件类型对应的负责人");
  99. }
  100. Date now = new Date();
  101. for (Integer userId : userIds) {
  102. EventAssign eventAssign = new EventAssign();
  103. eventAssign.setEventId(eventId);
  104. eventAssign.setUserId(userId);
  105. eventAssign.setStatus("0"); // 未完结
  106. eventAssign.setIsReassign("0"); // 非重新分配
  107. eventAssign.setCreateTime(now);
  108. eventAssign.setUpdateTime(now);
  109. eventAssignMapper.insert(eventAssign);
  110. }
  111. }
  112. // /**
  113. // * 根据事件类型获取负责人列表
  114. // * @param eventType
  115. // * @return
  116. // */
  117. // @Override
  118. // public List<PersonInfoVO> getPersonInfoVOByEventType(Integer eventType) {
  119. // return eventTypeAssigneeService.getListEventPersonInfoVO(eventType);
  120. // }
  121. /**
  122. * 根据事件类型获取负责人系统用户ID列表
  123. *
  124. * @param eventType 事件类型
  125. * @return 负责人ID列表
  126. */
  127. private List<Integer> getPersonIdsByEventType(Integer eventType) {
  128. // 获取负责人列表
  129. List<PersonInfoVO> listEventPersonInfoVO = eventTypeAssigneeService.getListEventPersonInfoVO(eventType);
  130. List<Integer> userIds = listEventPersonInfoVO.stream().map(
  131. personInfoVO -> {
  132. return personInfoVO.getUserId();
  133. }).collect(Collectors.toList());
  134. // 同时包含超级管理员(user_id = 1)
  135. if (!userIds.contains(1)) {
  136. userIds.add(1);
  137. }
  138. return userIds;
  139. }
  140. /**
  141. * 删除
  142. *
  143. * @param ids
  144. * @return
  145. */
  146. @Override
  147. public boolean deleteEvent(String ids) {
  148. if (StrUtil.isBlank(ids)) {
  149. throw new ServiceException("id不能为空或id异常");
  150. }
  151. // 2. 分割ID字符串为List<Integer>
  152. List<Long> idList = Arrays.stream(ids.split(","))
  153. .map(String::trim)
  154. .filter(StrUtil::isNotBlank)
  155. .map(Long::parseLong)
  156. .collect(Collectors.toList());
  157. if (idList.isEmpty()) {
  158. throw new ServiceException("ID格式异常");
  159. }
  160. // 3. 构建删除条件
  161. QueryWrapper<Event> queryWrapper = new QueryWrapper<>();
  162. queryWrapper.in("id", idList);
  163. // todo 同步删除 分配表 记录
  164. // 4. 执行删除(返回是否删除成功)
  165. return remove(queryWrapper);
  166. }
  167. // /**
  168. // * 编辑
  169. // *
  170. // * @param eventEditRequest
  171. // */
  172. // @Override
  173. // public void editEvent(EventEditRequest eventEditRequest) {
  174. // // 判断是否存在
  175. // Integer id = eventEditRequest.getId();
  176. // Event oldEvent = this.getById(id);
  177. // if (oldEvent == null) {
  178. // throw new ServiceException("没有找到事件");
  179. // }
  180. // Event event = new Event();
  181. // BeanUtil.copyProperties(eventEditRequest, event);
  182. // event.setUpdateTime(new Date());
  183. // // 数据校验
  184. // validEvent(event, BusinessType.UPDATE);
  185. //
  186. // // 操作数据库
  187. // boolean result = this.updateById(event);
  188. // if (!result) {
  189. // throw new ServiceException("修改事件操作失败");
  190. // }
  191. // }
  192. /**
  193. * 校验数据
  194. *
  195. * @param event
  196. */
  197. public void validEvent(Event event, BusinessType type) {
  198. if (ObjectUtil.isEmpty(event)) {
  199. throw new ServiceException("数据为空");
  200. }
  201. // 从对象中取值
  202. Integer id = event.getId();
  203. Date occurTime = event.getOccurTime();
  204. Integer eventType = event.getType();
  205. String location = event.getLocation();
  206. String description = event.getDescription();
  207. String photoUrl = event.getPhotoUrl();
  208. String status = event.getStatus();
  209. Integer submitterId = event.getSubmitterId();
  210. String processResult = event.getProcessResult();
  211. Date processTime = event.getProcessTime();
  212. // 添加id无需校验,修改时,id 不能为空
  213. if (type != BusinessType.INSERT && ObjectUtil.isEmpty(id)) {
  214. throw new ServiceException("id不能为空");
  215. }
  216. if (ObjectUtil.isEmpty(occurTime)) {
  217. throw new ServiceException("事件时间不能为空");
  218. }
  219. if (ObjectUtil.isEmpty(eventType)) {
  220. throw new ServiceException("事件类别不能为空");
  221. }
  222. if (StrUtil.isBlank(location)) {
  223. throw new ServiceException("事件地点不能为空");
  224. }
  225. if (ObjectUtil.isEmpty(submitterId)) {
  226. throw new ServiceException("填报人不能为空");
  227. }
  228. }
  229. /**
  230. * 根据id查询
  231. *
  232. * @param id 事件id
  233. * @return
  234. */
  235. @Override
  236. public EventVO getEventById(int id) {
  237. if (id <= 0) {
  238. throw new ServiceException("id不能为空或id异常");
  239. }
  240. // 获取登录用户id
  241. Long userId = SecurityUtils.getUserId();
  242. Event event;
  243. // 若不是管理员 指定查询的 负责人id 为当前登录用户id (负责人只能查询自己的事件)
  244. // if (SecurityUtils.isAdmin(userId)) {
  245. // 管理员查询
  246. event = this.getById(id);
  247. // } else {
  248. // // 负责人查询
  249. // QueryWrapper<Event> wrapper = new QueryWrapper<>();
  250. // wrapper.eq("id", id)
  251. // .exists("SELECT 1 FROM event_assign ea WHERE ea.event_id = event.id AND ea.user_id = " + userId);
  252. // event = this.getOne(wrapper);
  253. // }
  254. return getEventVO(event);
  255. }
  256. /**
  257. * 获取事件包装类
  258. *
  259. * @param event
  260. * @return
  261. */
  262. @Override
  263. public EventVO getEventVO(Event event) {
  264. if (ObjectUtil.isEmpty(event)) {
  265. throw new ServiceException("请求参数不存在");
  266. }
  267. EventVO eventVO = new EventVO();
  268. BeanUtils.copyProperties(event, eventVO);
  269. // 查询事件的负责人信息
  270. QueryWrapper<EventAssign> queryWrapper = new QueryWrapper<>();
  271. queryWrapper.eq("event_id", event.getId());
  272. // 获取事件分配信息列表
  273. List<EventAssign> eventAssigns = eventAssignMapper.selectList(queryWrapper);
  274. // 3. 提取负责人 系统用户ID列表
  275. List<Integer> userIds = eventAssigns.stream()
  276. .map(EventAssign::getUserId)
  277. .collect(Collectors.toList());
  278. // 4. 批量查询 有效的负责人信息
  279. List<PersonInfoVO> chargeUserList ;
  280. if (ObjectUtil.isNotEmpty(userIds)){
  281. chargeUserList = personInfoService.getPersonInfoVOListByUserIds(userIds);
  282. }else{
  283. chargeUserList=null;
  284. }
  285. eventVO.setChargeUserList(chargeUserList);
  286. // 5. 通过填报人id 查询村民姓名
  287. Integer submitterId = event.getSubmitterId();
  288. PersonInfo personInfo = personInfoService.getById(submitterId);
  289. eventVO.setSubmitterName(personInfo.getRealname());
  290. // 6. 查询处理人
  291. QueryWrapper<EventAssign> wrapper = new QueryWrapper<>();
  292. wrapper.select("user_id")
  293. .eq("event_id", event.getId())
  294. .eq("status", 1);
  295. EventAssign eventAssign = eventAssignService.getOne(wrapper);
  296. if (ObjectUtil.isNotEmpty(eventAssign)){
  297. // 事件已经处理 有处理人
  298. Integer userId = eventAssign.getUserId();
  299. //if (userId == 1) {
  300. if (SecurityUtils.isAdmin(userId.longValue())) {
  301. eventVO.setProcessUserName("超级管理员");
  302. }else{
  303. QueryWrapper<PersonInfo> queryWrapper2 = new QueryWrapper<>();
  304. queryWrapper2.select("id", "realname")
  305. .eq("user_id", userId);
  306. PersonInfo processPersonInfo = personInfoService.getOne(queryWrapper2);
  307. if (processPersonInfo != null) {
  308. eventVO.setProcessUserName(processPersonInfo.getRealname());
  309. } else {
  310. eventVO.setProcessUserName(null);
  311. }
  312. }
  313. } else {
  314. // 事件还未处理 没有处理人
  315. eventVO.setProcessUserName(null);
  316. }
  317. return eventVO;
  318. }
  319. /**
  320. * 分页获取事件列表
  321. *
  322. * @param eventQueryRequest
  323. * @return
  324. */
  325. @Override
  326. public Page<EventVO> getListEventByPage(EventQueryRequest eventQueryRequest) {
  327. long current = eventQueryRequest.getPageNum();
  328. long size = eventQueryRequest.getPageSize();
  329. // 获取登录用户id
  330. Long userId = SecurityUtils.getUserId();
  331. Page<Event> page;
  332. // 若不是管理员 指定查询的 负责人id 为当前登录用户id (负责人只能查询自己的事件)
  333. if (SecurityUtils.isAdmin(userId)) {
  334. // 管理员查询
  335. page = this.page(new Page<>(current, size),
  336. getQueryWrapper(eventQueryRequest, null));
  337. } else {
  338. // 负责人查询
  339. page = this.page(new Page<>(current, size),
  340. getQueryWrapper(eventQueryRequest, Math.toIntExact(userId)));
  341. }
  342. Page<EventVO> eventVOPage = new Page<>();
  343. BeanUtils.copyProperties(page, eventVOPage, "records");
  344. List<EventVO> voList = page.getRecords().stream()
  345. .map(event -> {
  346. EventVO vo = getEventVO(event);
  347. return vo;
  348. })
  349. .collect(Collectors.toList());
  350. eventVOPage.setRecords(voList);
  351. return eventVOPage;
  352. }
  353. /**
  354. * 获取查询条件
  355. *
  356. * @param eventQueryRequest
  357. * @return
  358. */
  359. @Override
  360. public QueryWrapper<Event> getQueryWrapper(EventQueryRequest eventQueryRequest, Integer userId) {
  361. QueryWrapper<Event> queryWrapper = new QueryWrapper<>();
  362. if (eventQueryRequest == null) {
  363. return queryWrapper;
  364. }
  365. // 从对象中取值
  366. String description = eventQueryRequest.getDescription();
  367. Date startTime = eventQueryRequest.getStartTime();
  368. Date endTime = eventQueryRequest.getEndTime();
  369. Integer type = eventQueryRequest.getType();
  370. String location = eventQueryRequest.getLocation();
  371. String status = eventQueryRequest.getStatus();
  372. Integer submitterId = eventQueryRequest.getSubmitterId();
  373. String sortField = eventQueryRequest.getSortField();
  374. String sortOrder = eventQueryRequest.getSortOrder();
  375. // 事件描述、事件类别、事发地点、填报人id(人口表id)、状态
  376. queryWrapper.like(StrUtil.isNotBlank(description), "description", description);
  377. queryWrapper.eq(ObjectUtil.isNotEmpty(type), "type", type);
  378. queryWrapper.eq(StrUtil.isNotBlank(location), "location", location);
  379. queryWrapper.eq(StringUtils.isNotBlank(status), "status", status);
  380. // 修正列名:submitter_id
  381. queryWrapper.eq(ObjectUtil.isNotEmpty(submitterId), "submitter_id", submitterId);
  382. // 如果负责人查询,则查询负责人的事件
  383. if (ObjectUtil.isNotEmpty(userId)) {
  384. queryWrapper.exists("SELECT 1 FROM event_assign ea WHERE ea.event_id = event.id AND ea.user_id = " + userId);
  385. }
  386. // 事发时间范围查询(优先判断范围)
  387. if (startTime != null && endTime != null) {
  388. queryWrapper.between("occur_time", startTime, endTime);
  389. } else if (startTime != null) {
  390. queryWrapper.ge("occur_time", startTime); // >= 开始日期
  391. } else if (endTime != null) {
  392. queryWrapper.le("occur_time", endTime); // <= 结束日期
  393. }
  394. // 排序
  395. queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField);
  396. return queryWrapper;
  397. }
  398. /**
  399. * 任一负责人处理事件:主表CAS(状态) + 分配表同步
  400. */
  401. @Override
  402. @Transactional(rollbackFor = Exception.class)
  403. public boolean handleEvent(Integer eventId, String processResult,Date processTime) {
  404. Long userId = SecurityUtils.getUserId();
  405. if (eventId == null || userId == null) {
  406. throw new ServiceException("参数不能为空");
  407. }
  408. // 1. 事件主表CAS:尝试抢占锁,只能修改状态为 0 的事件
  409. UpdateWrapper<Event> casUpdate = new UpdateWrapper<>();
  410. if (ObjectUtil.isEmpty(processTime)){
  411. processTime = new Date();
  412. }
  413. casUpdate.eq("id", eventId)
  414. .eq("status", "0")
  415. .set("status", "1")
  416. .set("process_result", processResult)
  417. .set("process_time", processTime)
  418. .set("update_time", new Date());
  419. int w = this.baseMapper.update(null, casUpdate);
  420. if (w == 1) {
  421. // 抢到锁:当前负责人状态 -> 1;其他事件负责人状态 -> 2
  422. UpdateWrapper<EventAssign> meDone = new UpdateWrapper<>();
  423. meDone.eq("event_id", eventId)
  424. .eq("user_id", userId)
  425. .eq("status", "0")
  426. .set("status", "1")
  427. .set("update_time", new Date());
  428. eventAssignMapper.update(null, meDone);
  429. UpdateWrapper<EventAssign> othersDone = new UpdateWrapper<>();
  430. othersDone.eq("event_id", eventId)
  431. .ne("user_id", userId)
  432. .eq("status", "0")
  433. .set("status", "2")
  434. .set("update_time", new Date());
  435. eventAssignMapper.update(null, othersDone);
  436. return true;
  437. } else {
  438. // 抢锁失败:当前事件已经被其他负责人处理,将当前负责人状态 -> 2
  439. UpdateWrapper<EventAssign> meLose = new UpdateWrapper<>();
  440. meLose.eq("event_id", eventId)
  441. .eq("user_id", userId)
  442. .eq("status", "0")
  443. .set("status", "2")
  444. .set("update_time", new Date());
  445. eventAssignMapper.update(null, meLose);
  446. return false;
  447. }
  448. }
  449. /**
  450. * 再次派发:仅在事件未完结时允许;存在则重置为未完结并标记再派发,不存在则插入
  451. */
  452. // todo 校验事件类型 与 负责人类型 是否匹配
  453. @Override
  454. @Transactional(rollbackFor = Exception.class)
  455. public void reassignEvent(Integer eventId, List<Integer> personIds) {
  456. if (eventId == null || personIds == null || personIds.isEmpty()) {
  457. throw new ServiceException("参数不能为空");
  458. }
  459. // 校验事件未完结
  460. Event event = this.getById(eventId);
  461. if (event == null) {
  462. throw new ServiceException("事件不存在");
  463. }
  464. if (!"0".equals(event.getStatus())) {
  465. throw new ServiceException("事件已完结,无法再次派发");
  466. }
  467. Date now = new Date();
  468. // 通过人口id 获取 系统用户id
  469. List<Integer> userIds = personInfoService.getUserIdListByPersonIds(personIds);
  470. for (Integer uid : userIds) {
  471. // 先尝试更新存在的数据
  472. UpdateWrapper<EventAssign> reset = new UpdateWrapper<>();
  473. reset.eq("event_id", eventId)
  474. .eq("user_id", uid)
  475. .set("status", "0")
  476. .set("is_reassign", "1")
  477. .set("update_time", now);
  478. int a = eventAssignMapper.update(null, reset);
  479. // 如果不是原来的事件负责人,添加分配记录
  480. if (a == 0) {
  481. // 插入新记录
  482. EventAssign add = new EventAssign();
  483. add.setEventId(eventId);
  484. add.setUserId(uid);
  485. add.setStatus("0");
  486. add.setIsReassign("1");
  487. add.setCreateTime(now);
  488. add.setUpdateTime(now);
  489. eventAssignMapper.insert(add);
  490. }
  491. }
  492. }
  493. @Override
  494. public Page<Event> pageCunMin(EventQueryRequest eventQueryRequest) {
  495. long current = eventQueryRequest.getPageNum();
  496. long size = eventQueryRequest.getPageSize();
  497. String keyWord = eventQueryRequest.getKeyWord();
  498. // 获取登录用户id
  499. Long userId = SecurityUtils.getUserId();
  500. QueryWrapper<Event> wrapper = new QueryWrapper<Event>().eq("submitter_id", userId);
  501. if (StringUtils.isNotBlank(keyWord)){
  502. wrapper.and(i -> i.like("location",keyWord).or().like("description",keyWord));
  503. }
  504. Page<Event> page = this.page(new Page<>(current, size),
  505. wrapper );
  506. return page;
  507. }
  508. }