#工单模块

This commit is contained in:
2026-05-13 16:12:29 +08:00
parent d3f1ece7d6
commit ac513ac5b8
7 changed files with 619 additions and 0 deletions

View File

@@ -0,0 +1 @@
package com.maibu.core.business;

View File

@@ -0,0 +1,36 @@
package com.maibu.core.business.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@ApiModel("工单派发参数")
public class WorkOrderDispatchDTO {
@ApiModelProperty("工单 ID")
private Long orderId;
@ApiModelProperty("负责人 ID")
private Long assigneeId;
@ApiModelProperty("负责人姓名")
private String assigneeName;
@ApiModelProperty("协同人员 ID 列表")
private String collaboratorIds;
@ApiModelProperty("协同人员姓名列表")
private String collaboratorNames;
@ApiModelProperty("计划开始时间")
private LocalDateTime planStartTime;
@ApiModelProperty("计划结束时间")
private LocalDateTime planEndTime;
@ApiModelProperty("截止时间")
private LocalDateTime deadlineTime;
}

View File

@@ -0,0 +1,57 @@
package com.maibu.core.business.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@ApiModel("工单查询参数")
public class WorkOrderQueryDTO {
@ApiModelProperty("工单编号")
private String orderNo;
@ApiModelProperty("工单标题")
private String orderTitle;
@ApiModelProperty("工单来源")
private Integer sourceType;
@ApiModelProperty("工单类型")
private Integer orderType;
@ApiModelProperty("优先级")
private Integer priorityLevel;
@ApiModelProperty("负责人 ID")
private Long assigneeId;
@ApiModelProperty("设备 ID")
private Long deviceId;
@ApiModelProperty("场站 ID")
private Long siteId;
@ApiModelProperty("组织 ID")
private Long orgId;
@ApiModelProperty("工单状态")
private Integer orderStatus;
@ApiModelProperty("开始时间")
private LocalDateTime startTime;
@ApiModelProperty("结束时间")
private LocalDateTime endTime;
@ApiModelProperty("搜索关键词")
private String keyword;
@ApiModelProperty("页码")
private Integer pageNum = 1;
@ApiModelProperty("每页大小")
private Integer pageSize = 10;
}

View File

@@ -0,0 +1 @@
package com.maibu.mapper;

View File

@@ -0,0 +1,9 @@
package com.maibu.mapper;
import com.maibu.core.business.IOTWorkOrder;
import com.maibu.mybatis.mapper.BaseMapperX;
import org.springframework.stereotype.Repository;
@Repository
public interface IotWorkOrderMapper extends BaseMapperX<IOTWorkOrder> {
}

View File

@@ -0,0 +1,39 @@
package com.maibu.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.maibu.core.business.IOTWorkOrder;
import com.maibu.core.business.dto.WorkOrderDispatchDTO;
import com.maibu.core.business.dto.WorkOrderQueryDTO;
import com.maibu.core.page.TableDataInfo;
import java.util.List;
import java.util.Map;
public interface IWorkOrderService extends IService<IOTWorkOrder> {
TableDataInfo selectWorkOrderPage(WorkOrderQueryDTO queryDTO);
List<IOTWorkOrder> selectWorkOrderList(WorkOrderQueryDTO queryDTO);
IOTWorkOrder selectWorkOrderById(Long id);
int insertWorkOrder(IOTWorkOrder workOrder);
int updateWorkOrder(IOTWorkOrder workOrder);
int dispatchWorkOrder(WorkOrderDispatchDTO dispatchDTO);
int startWorkOrder(Long id);
int completeWorkOrder(IOTWorkOrder workOrder);
int suspendWorkOrder(Long id);
int deleteWorkOrderById(Long id);
int deleteWorkOrderByIds(Long[] ids);
Map<String, Object> getWorkOrderStatistics();
IOTWorkOrder generateWorkOrderFromAlarm(Long alarmId);
}

View File

@@ -0,0 +1,476 @@
package com.maibu.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maibu.core.business.Device;
import com.maibu.core.business.IOTWorkOrder;
import com.maibu.core.business.dto.WorkOrderDispatchDTO;
import com.maibu.core.business.dto.WorkOrderQueryDTO;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.core.page.TableDataInfo;
import com.maibu.exception.ServiceException;
import com.maibu.mapper.DeviceMapper;
import com.maibu.mapper.IotWorkOrderMapper;
import com.maibu.service.IAlarmService;
import com.maibu.service.IWorkOrderService;
import com.maibu.utils.SecurityUtils;
import com.maibu.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWorkOrder> implements IWorkOrderService {
@Autowired
private DeviceMapper deviceMapper;
@Autowired
private IAlarmService alarmService;
@Override
public TableDataInfo selectWorkOrderPage(WorkOrderQueryDTO queryDTO) {
validateQueryParams(queryDTO);
LambdaQueryWrapper<IOTWorkOrder> wrapper = buildQueryWrapper(queryDTO);
Page<IOTWorkOrder> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
Page<IOTWorkOrder> result = baseMapper.selectPage(page, wrapper);
TableDataInfo tableDataInfo = new TableDataInfo();
tableDataInfo.setRows(result.getRecords());
tableDataInfo.setTotal(result.getTotal());
return tableDataInfo;
}
@Override
public List<IOTWorkOrder> selectWorkOrderList(WorkOrderQueryDTO queryDTO) {
validateQueryParams(queryDTO);
LambdaQueryWrapper<IOTWorkOrder> wrapper = buildQueryWrapper(queryDTO);
return baseMapper.selectList(wrapper);
}
private void validateQueryParams(WorkOrderQueryDTO queryDTO) {
Long userId = SecurityUtils.getUserId();
if (SecurityUtils.isAdmin(userId)) {
return;
}
if (queryDTO.getSiteId() != null) {
validateSiteAccess(queryDTO.getSiteId());
}
if (queryDTO.getDeviceId() != null) {
validateDeviceAccess(queryDTO.getDeviceId());
}
}
private void validateSiteAccess(Long siteId) {
if (siteId == null) return;
Long userId = SecurityUtils.getUserId();
if (SecurityUtils.isAdmin(userId)) return;
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userSiteId = loginUser.getSiteId();
Long userOrgId = loginUser.getOrgId();
if (userSiteId != null) {
if (!userSiteId.equals(siteId)) {
throw new ServiceException("无权访问该场站");
}
} else if (userOrgId != null) {
Long count = deviceMapper.selectCount(
new LambdaQueryWrapper<Device>()
.eq(Device::getSiteId, siteId)
.eq(Device::getOrgId, userOrgId)
);
if (count == 0) {
throw new ServiceException("无权访问该场站");
}
} else {
throw new ServiceException("无权访问该场站");
}
}
private void validateDeviceAccess(Long deviceId) {
if (deviceId == null) return;
Long userId = SecurityUtils.getUserId();
if (SecurityUtils.isAdmin(userId)) return;
Device device = deviceMapper.selectOne(
new LambdaQueryWrapper<Device>()
.eq(Device::getDeviceId, deviceId)
.select(Device::getOrgId, Device::getSiteId)
);
if (device == null) {
throw new ServiceException("设备不存在");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userSiteId = loginUser.getSiteId();
Long userOrgId = loginUser.getOrgId();
if (userSiteId != null && !userSiteId.equals(device.getSiteId())) {
throw new ServiceException("无权访问该设备");
}
if (userOrgId != null && !userOrgId.equals(device.getOrgId())) {
throw new ServiceException("无权访问该设备");
}
}
private LambdaQueryWrapper<IOTWorkOrder> buildQueryWrapper(WorkOrderQueryDTO queryDTO) {
LambdaQueryWrapper<IOTWorkOrder> wrapper = new LambdaQueryWrapper<>();
Long userId = SecurityUtils.getUserId();
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userOrgId = loginUser.getOrgId();
Long userSiteId = loginUser.getSiteId();
if (!SecurityUtils.isAdmin(userId)) {
if (queryDTO.getSiteId() != null) {
wrapper.eq(IOTWorkOrder::getSiteId, queryDTO.getSiteId());
if (userOrgId != null) {
wrapper.eq(IOTWorkOrder::getOrgId, userOrgId);
}
} else if (userSiteId != null) {
wrapper.eq(IOTWorkOrder::getSiteId, userSiteId);
} else if (userOrgId != null) {
wrapper.eq(IOTWorkOrder::getOrgId, userOrgId);
}
if (queryDTO.getAssigneeId() != null) {
wrapper.eq(IOTWorkOrder::getAssigneeId, queryDTO.getAssigneeId());
} else {
wrapper.and(w -> w.eq(IOTWorkOrder::getAssigneeId, userId)
.or()
.apply("FIND_IN_SET({0}, collaborator_ids)", userId));
}
} else {
if (queryDTO.getSiteId() != null) {
wrapper.eq(IOTWorkOrder::getSiteId, queryDTO.getSiteId());
}
if (queryDTO.getOrgId() != null) {
wrapper.eq(IOTWorkOrder::getOrgId, queryDTO.getOrgId());
}
if (queryDTO.getAssigneeId() != null) {
wrapper.eq(IOTWorkOrder::getAssigneeId, queryDTO.getAssigneeId());
}
}
if (queryDTO.getOrderNo() != null && !queryDTO.getOrderNo().isEmpty()) {
wrapper.like(IOTWorkOrder::getOrderNo, queryDTO.getOrderNo());
}
if (queryDTO.getOrderTitle() != null && !queryDTO.getOrderTitle().isEmpty()) {
wrapper.like(IOTWorkOrder::getOrderTitle, queryDTO.getOrderTitle());
}
if (queryDTO.getSourceType() != null) {
wrapper.eq(IOTWorkOrder::getSourceType, queryDTO.getSourceType());
}
if (queryDTO.getOrderType() != null) {
wrapper.eq(IOTWorkOrder::getOrderType, queryDTO.getOrderType());
}
if (queryDTO.getPriorityLevel() != null) {
wrapper.eq(IOTWorkOrder::getPriorityLevel, queryDTO.getPriorityLevel());
}
if (queryDTO.getOrderStatus() != null) {
wrapper.eq(IOTWorkOrder::getOrderStatus, queryDTO.getOrderStatus());
}
if (queryDTO.getDeviceId() != null) {
wrapper.eq(IOTWorkOrder::getDeviceId, queryDTO.getDeviceId());
}
if (queryDTO.getStartTime() != null) {
wrapper.ge(IOTWorkOrder::getCreateTime, queryDTO.getStartTime());
}
if (queryDTO.getEndTime() != null) {
wrapper.le(IOTWorkOrder::getCreateTime, queryDTO.getEndTime());
}
if (StringUtils.isNotEmpty(queryDTO.getKeyword())) {
wrapper.and(w -> w.like(IOTWorkOrder::getOrderNo, queryDTO.getKeyword())
.or()
.like(IOTWorkOrder::getOrderTitle, queryDTO.getKeyword()));
}
wrapper.orderByDesc(IOTWorkOrder::getCreateTime);
return wrapper;
}
@Override
public IOTWorkOrder selectWorkOrderById(Long id) {
IOTWorkOrder workOrder = baseMapper.selectById(id);
if (workOrder == null) throw new ServiceException("工单不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
validateWorkOrderAccess(workOrder);
}
return workOrder;
}
private void validateWorkOrderAccess(IOTWorkOrder workOrder) {
Long userId = SecurityUtils.getUserId();
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userSiteId = loginUser.getSiteId();
Long userOrgId = loginUser.getOrgId();
if (userSiteId != null && !userSiteId.equals(workOrder.getSiteId())) {
throw new ServiceException("无权访问该工单");
}
if (userOrgId != null && !userOrgId.equals(workOrder.getOrgId())) {
throw new ServiceException("无权访问该工单");
}
boolean isAssignee = userId.equals(workOrder.getAssigneeId());
boolean isCollaborator = workOrder.getCollaboratorIds() != null &&
workOrder.getCollaboratorIds().contains(userId.toString());
if (!isAssignee && !isCollaborator) {
throw new ServiceException("无权访问该工单");
}
}
@Override
public int insertWorkOrder(IOTWorkOrder workOrder) {
workOrder.setOrderNo(generateOrderNo());
workOrder.setTenantId(SecurityUtils.getLoginUser().getOrgId());
workOrder.setOrgId(SecurityUtils.getLoginUser().getOrgId());
workOrder.setCreateTime(LocalDateTime.now());
if (workOrder.getOrderStatus() == null) {
workOrder.setOrderStatus(1);
}
return baseMapper.insert(workOrder);
}
@Override
public int updateWorkOrder(IOTWorkOrder workOrder) {
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
IOTWorkOrder existWorkOrder = baseMapper.selectById(workOrder.getId());
if (existWorkOrder != null) {
validateWorkOrderAccess(existWorkOrder);
}
}
workOrder.setUpdateTime(LocalDateTime.now());
return baseMapper.updateById(workOrder);
}
@Override
public int dispatchWorkOrder(WorkOrderDispatchDTO dispatchDTO) {
IOTWorkOrder workOrder = baseMapper.selectById(dispatchDTO.getOrderId());
if (workOrder == null) throw new ServiceException("工单不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
validateWorkOrderAccess(workOrder);
}
IOTWorkOrder updateWorkOrder = new IOTWorkOrder();
updateWorkOrder.setId(dispatchDTO.getOrderId());
updateWorkOrder.setAssigneeId(dispatchDTO.getAssigneeId());
updateWorkOrder.setAssigneeName(dispatchDTO.getAssigneeName());
updateWorkOrder.setCollaboratorIds(dispatchDTO.getCollaboratorIds());
updateWorkOrder.setCollaboratorNames(dispatchDTO.getCollaboratorNames());
updateWorkOrder.setPlanStartTime(dispatchDTO.getPlanStartTime());
updateWorkOrder.setPlanEndTime(dispatchDTO.getPlanEndTime());
updateWorkOrder.setDeadlineTime(dispatchDTO.getDeadlineTime());
updateWorkOrder.setOrderStatus(2);
updateWorkOrder.setUpdateTime(LocalDateTime.now());
updateWorkOrder.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
return baseMapper.updateById(updateWorkOrder);
}
@Override
public int startWorkOrder(Long id) {
IOTWorkOrder workOrder = baseMapper.selectById(id);
if (workOrder == null) throw new ServiceException("工单不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
validateWorkOrderAccess(workOrder);
}
IOTWorkOrder updateWorkOrder = new IOTWorkOrder();
updateWorkOrder.setId(id);
updateWorkOrder.setOrderStatus(3);
updateWorkOrder.setActualStartTime(LocalDateTime.now());
updateWorkOrder.setUpdateTime(LocalDateTime.now());
updateWorkOrder.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
return baseMapper.updateById(updateWorkOrder);
}
@Override
public int completeWorkOrder(IOTWorkOrder workOrder) {
IOTWorkOrder existWorkOrder = baseMapper.selectById(workOrder.getId());
if (existWorkOrder == null) throw new ServiceException("工单不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
validateWorkOrderAccess(existWorkOrder);
}
IOTWorkOrder updateWorkOrder = new IOTWorkOrder();
updateWorkOrder.setId(workOrder.getId());
updateWorkOrder.setOrderStatus(4);
updateWorkOrder.setActualEndTime(LocalDateTime.now());
updateWorkOrder.setHandleResult(workOrder.getHandleResult());
updateWorkOrder.setHandleRemark(workOrder.getHandleRemark());
updateWorkOrder.setUpdateTime(LocalDateTime.now());
updateWorkOrder.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
return baseMapper.updateById(updateWorkOrder);
}
@Override
public int suspendWorkOrder(Long id) {
IOTWorkOrder workOrder = baseMapper.selectById(id);
if (workOrder == null) throw new ServiceException("工单不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
validateWorkOrderAccess(workOrder);
}
IOTWorkOrder updateWorkOrder = new IOTWorkOrder();
updateWorkOrder.setId(id);
updateWorkOrder.setOrderStatus(5);
updateWorkOrder.setUpdateTime(LocalDateTime.now());
updateWorkOrder.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
return baseMapper.updateById(updateWorkOrder);
}
@Override
public int deleteWorkOrderById(Long id) {
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
IOTWorkOrder workOrder = baseMapper.selectById(id);
if (workOrder != null) {
validateWorkOrderAccess(workOrder);
}
}
return baseMapper.deleteById(id);
}
@Override
public int deleteWorkOrderByIds(Long[] ids) {
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId)) {
for (Long id : ids) {
IOTWorkOrder workOrder = baseMapper.selectById(id);
if (workOrder != null) {
validateWorkOrderAccess(workOrder);
}
}
}
return baseMapper.deleteBatchIds(Arrays.asList(ids));
}
@Override
public Map<String, Object> getWorkOrderStatistics() {
Long userId = SecurityUtils.getUserId();
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userOrgId = loginUser.getOrgId();
Long userSiteId = loginUser.getSiteId();
LambdaQueryWrapper<IOTWorkOrder> wrapper = new LambdaQueryWrapper<>();
if (!SecurityUtils.isAdmin(userId)) {
if (userSiteId != null) {
wrapper.eq(IOTWorkOrder::getSiteId, userSiteId);
} else if (userOrgId != null) {
wrapper.eq(IOTWorkOrder::getOrgId, userOrgId);
}
wrapper.and(w -> w.eq(IOTWorkOrder::getAssigneeId, userId)
.or()
.apply("FIND_IN_SET({0}, collaborator_ids)", userId));
}
List<IOTWorkOrder> workOrders = baseMapper.selectList(wrapper);
Map<String, Object> statistics = new HashMap<>();
statistics.put("total", workOrders.size());
statistics.put("pending", workOrders.stream().filter(w -> w.getOrderStatus() == 1).count());
statistics.put("dispatched", workOrders.stream().filter(w -> w.getOrderStatus() == 2).count());
statistics.put("executing", workOrders.stream().filter(w -> w.getOrderStatus() == 3).count());
statistics.put("completed", workOrders.stream().filter(w -> w.getOrderStatus() == 4).count());
statistics.put("suspended", workOrders.stream().filter(w -> w.getOrderStatus() == 5).count());
statistics.put("todayNew", workOrders.stream()
.filter(w -> w.getCreateTime().toLocalDate().equals(LocalDateTime.now().toLocalDate()))
.count());
statistics.put("highPriority", workOrders.stream().filter(w -> w.getPriorityLevel() == 1).count());
return statistics;
}
@Override
public IOTWorkOrder generateWorkOrderFromAlarm(Long alarmId) {
com.maibu.core.business.alarm_center.Alarm alarm = alarmService.getById(alarmId);
if (alarm == null) {
throw new ServiceException("告警不存在");
}
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) {
Device device = deviceMapper.selectOne(
new LambdaQueryWrapper<Device>()
.eq(Device::getDeviceId, alarm.getDeviceId())
.select(Device::getOrgId, Device::getSiteId)
);
if (device != null) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (!loginUser.getOrgId().equals(device.getOrgId())) {
throw new ServiceException("无权访问该告警");
}
}
}
IOTWorkOrder workOrder = new IOTWorkOrder();
workOrder.setOrderNo(generateOrderNo());
workOrder.setOrderTitle(alarm.getAlarmTitle());
workOrder.setSourceType(7);
workOrder.setOrderType(2);
workOrder.setPriorityLevel(determinePriority(alarm.getAlarmLevel()));
workOrder.setDeviceId(alarm.getDeviceId());
workOrder.setDeviceName(alarm.getDeviceName());
workOrder.setDeviceType(alarm.getDeviceType());
workOrder.setOrgId(alarm.getTenantId());
workOrder.setAlarmId(alarmId);
workOrder.setAlarmNo(alarm.getAlarmNo());
workOrder.setTaskDescription(alarm.getAlarmContent());
workOrder.setAiSuggestion(alarm.getHandleSuggestion());
workOrder.setOrderStatus(1);
workOrder.setCreateTime(LocalDateTime.now());
workOrder.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
baseMapper.insert(workOrder);
return workOrder;
}
private Integer determinePriority(Integer alarmLevel) {
if (alarmLevel == 1) {
return 1;
} else if (alarmLevel == 2) {
return 2;
} else {
return 3;
}
}
private String generateOrderNo() {
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
long count = baseMapper.selectCount(new LambdaQueryWrapper<IOTWorkOrder>()
.likeRight(IOTWorkOrder::getOrderNo, "WO" + dateStr));
return "WO" + dateStr + String.format("%04d", count + 1);
}
}