|
|
@@ -22,6 +22,7 @@ import com.zksy.dispatch.dto.EventUrgePageDTO;
|
|
|
import com.zksy.dispatch.dto.EventUrgeRowVO;
|
|
|
import com.zksy.dispatch.dto.EventVerifyDTO;
|
|
|
import com.zksy.dispatch.dto.EventReleaseDTO;
|
|
|
+import com.zksy.dispatch.support.DispatchAttachUrlSupport;
|
|
|
import com.zksy.dispatch.dto.SseMessageDto;
|
|
|
import com.zksy.dispatch.enums.EventLogOperTypeEnum;
|
|
|
import com.zksy.dispatch.enums.EventStatusEnum;
|
|
|
@@ -61,14 +62,9 @@ import java.util.Objects;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
- * 应急事件统一档案 Service 实现(全生命周期闭环)。
|
|
|
- *
|
|
|
- * <p>改造要点:所有环节共用一张 {@code dis_event} 主表 + 一张 {@code dis_event_log} 日志表。
|
|
|
- * 状态变更覆盖主表当前值,过程留痕一律追加日志;状态取值全部走 {@link EventStatusEnum},
|
|
|
- * 代码中不出现任何状态中文字面量。</p>
|
|
|
- *
|
|
|
- * <p>并发控制:流转前统一 {@code SELECT ... FOR UPDATE} 锁行,编号生成前持有
|
|
|
- * {@code pg_advisory_xact_lock},避免并发重复流转与撞号。</p>
|
|
|
+ * 应急事件 Service 实现。
|
|
|
+ * 状态变更只覆盖主表当前值,过程留痕一律追加日志;流转前锁行(SELECT ... FOR UPDATE
|
|
|
+ * + pg_advisory_xact_lock),防止并发重复流转与撞号。
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@@ -88,6 +84,10 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
@Autowired
|
|
|
private DisEventLogService eventLogService;
|
|
|
|
|
|
+ /** 附件地址支撑:库内相对路径 ↔ 展示完整 URL(MinIO 配置拼接) */
|
|
|
+ @Autowired
|
|
|
+ private DispatchAttachUrlSupport attachUrlSupport;
|
|
|
+
|
|
|
/** 人员引用查询(选人下拉 + 按ID批量反查昵称) */
|
|
|
@Autowired
|
|
|
private DispatchUserMapper userMapper;
|
|
|
@@ -98,8 +98,13 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
public Page<DisEventVO> findByPage(DisEventPageDTO dto) {
|
|
|
Page<DisEvent> page = new Page<>(dto.getPageNum(), dto.getPageSize());
|
|
|
LambdaQueryWrapper<DisEvent> wrapper = buildWrapper(dto);
|
|
|
- // 默认按接报时间倒序,接报时间为空的排在最后
|
|
|
- wrapper.orderByDesc(DisEvent::getReportTime).orderByDesc(DisEvent::getId);
|
|
|
+ // 排序规则:orderAsc=true 按接报时间升序(核实/转接报送/跟踪解除等「先报先办」队列页),
|
|
|
+ // 默认倒序(接报管理等记录回看页);接报时间为空的排在最后
|
|
|
+ if (Boolean.TRUE.equals(dto.getOrderAsc())) {
|
|
|
+ wrapper.orderByAsc(DisEvent::getReportTime).orderByAsc(DisEvent::getId);
|
|
|
+ } else {
|
|
|
+ wrapper.orderByDesc(DisEvent::getReportTime).orderByDesc(DisEvent::getId);
|
|
|
+ }
|
|
|
page(page, wrapper);
|
|
|
|
|
|
Page<DisEventVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
|
|
|
@@ -517,8 +522,21 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
db.setEventCategory(dto.getEventCategory());
|
|
|
db.setEventLevel(dto.getEventLevel());
|
|
|
db.setEventRegion(dto.getEventRegion());
|
|
|
- db.setHandler(dto.getHandler());
|
|
|
- db.setHandlerId(dto.getHandlerId());
|
|
|
+ // 责任处置人必须关联系统用户账号:handlerId 是后续催办通知/SSE 推送的投递目标
|
|
|
+ Long handlerId = dto.getHandlerId();
|
|
|
+ if (handlerId == null && StringUtils.isNotBlank(dto.getHandler())) {
|
|
|
+ handlerId = userMapper.selectUserIdByName(dto.getHandler());
|
|
|
+ }
|
|
|
+ if (handlerId == null) {
|
|
|
+ throw new ServiceException("责任处置人必须从系统用户中选择");
|
|
|
+ }
|
|
|
+ String handlerName = dto.getHandler();
|
|
|
+ if (StringUtils.isBlank(handlerName)) {
|
|
|
+ List<DisUserOptionVO> hit = userMapper.selectUserNamesByIds(Collections.singletonList(handlerId));
|
|
|
+ handlerName = hit.isEmpty() ? null : hit.get(0).getNickName();
|
|
|
+ }
|
|
|
+ db.setHandler(handlerName);
|
|
|
+ db.setHandlerId(handlerId);
|
|
|
db.setHandlerPhone(dto.getHandlerPhone());
|
|
|
db.setDepartment(dto.getDepartment());
|
|
|
db.setStatus(EventStatusEnum.VERIFIED.getCode());
|
|
|
@@ -567,7 +585,7 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
DisEventLog log = buildLog(db, operType, null, null);
|
|
|
log.setTargets(String.join("、", depts));
|
|
|
log.setOperDesc(dto.getOperDesc());
|
|
|
- log.setAttachUrl(dto.getAttachUrl());
|
|
|
+ log.setAttachUrl(attachUrlSupport.toRelative(dto.getAttachUrl()));
|
|
|
eventLogService.append(log);
|
|
|
}
|
|
|
|
|
|
@@ -591,7 +609,7 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
|
|
|
DisEventLog log = buildLog(db, EventLogOperTypeEnum.START_DISPOSE, statusFrom, db.getStatus());
|
|
|
log.setOperDesc(StringUtils.defaultIfBlank(dto.getOperDesc(), "开始处置"));
|
|
|
- log.setAttachUrl(dto.getAttachUrl());
|
|
|
+ log.setAttachUrl(attachUrlSupport.toRelative(dto.getAttachUrl()));
|
|
|
eventLogService.append(log);
|
|
|
}
|
|
|
|
|
|
@@ -620,7 +638,7 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
log.setTrend(dto.getTrend());
|
|
|
log.setNeedUpgrade(dto.getNeedUpgrade());
|
|
|
log.setNextVisitTime(dto.getNextVisitTime());
|
|
|
- log.setAttachUrl(dto.getAttachUrl());
|
|
|
+ log.setAttachUrl(attachUrlSupport.toRelative(dto.getAttachUrl()));
|
|
|
eventLogService.append(log);
|
|
|
}
|
|
|
|
|
|
@@ -644,9 +662,9 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
if (dto.getLossAmount() != null) {
|
|
|
db.setLossAmount(dto.getLossAmount());
|
|
|
}
|
|
|
- // 处置前/后佐证附件(解除原因为「事件已处置完成」时上传,多文件逗号分隔)
|
|
|
- db.setBeforeUrl(dto.getBeforeUrl());
|
|
|
- db.setAfterUrl(dto.getAfterUrl());
|
|
|
+ // 处置前/后佐证附件(解除原因为「事件已处置完成」时上传,多文件逗号分隔);库内存相对路径
|
|
|
+ db.setBeforeUrl(attachUrlSupport.toRelative(dto.getBeforeUrl()));
|
|
|
+ db.setAfterUrl(attachUrlSupport.toRelative(dto.getAfterUrl()));
|
|
|
db.setUpdateBy(DispatchUserSupport.currentLoginName());
|
|
|
db.setUpdateUserId(DispatchUserSupport.currentUserId());
|
|
|
db.setUpdateTime(now);
|
|
|
@@ -681,8 +699,7 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
log.setOperDesc(dto.getOperDesc());
|
|
|
eventLogService.append(log);
|
|
|
|
|
|
- // 催办方式含「系统消息」时,向接收人推一条站内催办通知(旁路动作,失败不阻断):
|
|
|
- // ① 落 dispatch_notify 表(离线可查,首页铃铛);② SSE 实时下发(在线立即弹窗)。
|
|
|
+ // 催办方式含「系统消息」时推站内通知:落 dispatch_notify 表 + SSE 实时下发;失败不阻断主流程
|
|
|
if (dto.getMethod().contains("系统消息")) {
|
|
|
Long receiverUserId = db.getHandlerId();
|
|
|
if (receiverUserId == null && StringUtils.isNotBlank(dto.getReceiver())) {
|
|
|
@@ -773,13 +790,15 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
|
|
|
/**
|
|
|
* 实体转展示 VO,补齐状态名称、可编辑标记与已过时长。
|
|
|
- *
|
|
|
- * <p>接报人 / 核验人 / 责任处置人:库里以「用户ID + 名称快照」双存,
|
|
|
- * 这里按用户ID反查 sys_user 的**最新昵称**覆盖快照,用户改名后列表即刻跟上。</p>
|
|
|
+ * 接报人 / 核验人 / 责任处置人:库里以「用户ID + 名称快照」双存,
|
|
|
+ * 这里按用户ID反查 sys_user 的最新昵称覆盖快照,用户改名后列表即刻跟上。
|
|
|
*/
|
|
|
private DisEventVO toVO(DisEvent event, Map<Long, String> userNames) {
|
|
|
DisEventVO vo = new DisEventVO();
|
|
|
BeanUtils.copyProperties(event, vo);
|
|
|
+ // 佐证附件:库内相对路径 → 拼上 MinIO 配置地址返回前端展示/下载
|
|
|
+ vo.setBeforeUrl(attachUrlSupport.toAccessibleUrl(event.getBeforeUrl()));
|
|
|
+ vo.setAfterUrl(attachUrlSupport.toAccessibleUrl(event.getAfterUrl()));
|
|
|
vo.setReporter(resolveUserName(userNames, event.getReporterId(), event.getReporter()));
|
|
|
vo.setVerifier(resolveUserName(userNames, event.getVerifierId(), event.getVerifier()));
|
|
|
vo.setHandler(resolveUserName(userNames, event.getHandlerId(), event.getHandler()));
|
|
|
@@ -791,7 +810,6 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
|
|
|
/**
|
|
|
* 批量取出事件列表里出现的人员ID,一次查询回昵称映射,避免逐行查库。
|
|
|
- *
|
|
|
* @return 用户ID -> 昵称;列表里没有任何人员ID时返回空映射
|
|
|
*/
|
|
|
private Map<Long, String> loadUserNames(List<DisEvent> events) {
|
|
|
@@ -834,9 +852,8 @@ public class DisEventServiceImpl extends ServiceImpl<DisEventMapper, DisEvent>
|
|
|
|
|
|
/**
|
|
|
* 构造日志骨架:事件标识 + 操作类型 + 状态变更轨迹
|
|
|
- *
|
|
|
* @param statusFrom 变更前状态,留痕型动作传 null
|
|
|
- * @param statusTo 变更后状态,留痕型动作传 null
|
|
|
+ * @param statusTo 变更后状态,留痕型动作传 null
|
|
|
*/
|
|
|
private DisEventLog buildLog(DisEvent event, EventLogOperTypeEnum operType,
|
|
|
Integer statusFrom, Integer statusTo) {
|