feat(ticket): 优化工单处理逻辑和消息提醒功能

- 添加工单处理人获取接口
- 优化工单查询和处理逻辑
- 增加工单解决方案措施获取接口
- 修复工单状态和权限相关问题
- 优化消息提醒功能,支持艾特提醒
This commit is contained in:
曹鹏飞 2025-04-02 11:54:02 +08:00
parent 4d1b8c784d
commit 3b70ad41ac
19 changed files with 86 additions and 48 deletions

View File

@ -370,7 +370,7 @@ public class TicketController extends ControllerBase {
@ApiMark(moduleName = "工单管理", apiName = "添加工单处理人")
public ApiResult<Void> addTicketHandle(@Valid @RequestBody TicketHandleAddRequest request){
Ticket ticket=ticketService.getById(request.getTicketId());
List<Integer> handleIds= Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> handleIds= StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
VUtils.trueThrowBusinessError(handleIds.stream().anyMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId()))
&& request.getUserIds().stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
.throwMessage("不可以移除自己");
@ -708,8 +708,7 @@ public class TicketController extends ControllerBase {
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()))
.throwMessage("当前工单状态不允许发送消息");
List<Integer> adminUsers=adminUserService.getTickerMangagers();
adminUsers.addAll(Arrays.stream(ticket.getHandle().split(","))
.map(Integer::parseInt).collect(Collectors.toList()));
adminUsers.addAll(StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList()));
VUtils.trueThrowBusinessError(adminUsers.stream()
.noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
.throwMessage("你无权发送消息");
@ -726,7 +725,8 @@ public class TicketController extends ControllerBase {
.setContent(request.getContent())
.setCreateTime(Instant.now())
.setAttachments(request.getAttachments())
.setImages(request.getImages());
.setImages(request.getImages())
.setRemindUserIds(request.getRemindUserIds());
if(Objects.nonNull(request.getQuoteId())){
ChatMessageDTO quoteMessage = ticketChatService.getMessage(request.getTicketId(), request.getQuoteId());
message.setQuote(quoteMessage);
@ -1156,4 +1156,14 @@ public class TicketController extends ControllerBase {
titleStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框颜色
return titleStyle;
}
/**
* 获取工单处理人
* @param ticketId 工单编号
*/
@GetMapping("/getHandlers")
@ApiMark(moduleName = "工单管理", apiName = "获取工单处理人")
public ApiResult<List<AdminUserSimpleVO>> getHandlers(@Valid @RequestParam @NotNull Integer ticketId) {
return ApiResult.success(ticketService.getTicketHandle(ticketId));
}
}

View File

@ -17,7 +17,6 @@ import org.springframework.context.ApplicationEvent;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -54,7 +53,7 @@ public class TicketCloseEvent extends ApplicationEvent implements ApplicationCon
private void sendUserMessage(){
//我的待办
List<Integer> userIds= Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> userIds= StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> adminUsers=adminUserService.listByIds(userIds);
if (CollectionUtil.isNotEmpty(adminUsers)){
adminUsers.forEach(c -> adminMessageService.add(

View File

@ -17,7 +17,6 @@ import org.springframework.context.ApplicationEvent;
import javax.mail.MessagingException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -85,7 +84,7 @@ public class TicketCompleteEvent extends ApplicationEvent implements Application
if (CollectionUtil.isNotEmpty(cqmUserIds)) {
List<AdminUser> cqmUsers = adminUserService.listByIds(cqmUserIds);
if (CollectionUtil.isNotEmpty(cqmUsers)) {
List<Integer> handleUserIds = Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> handleUserIds = StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> handleUsers = adminUserService.listByIds(handleUserIds);
AppUser appUser = appUserService.getById(ticket.getUserId());
String subject = dictionaryItemTranslateService.getValueByCode(Constant.DICTIONARY_EMAIL_NOTIFY, Constant.DICTIONARY_ITEM_EMAIL_TITLE_TICKET_ASSIGNED, Constant.DEFAULT_LANGUAGE_CODE);

View File

@ -19,7 +19,6 @@ import org.springframework.context.ApplicationEvent;
import javax.mail.MessagingException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -69,7 +68,7 @@ public class TicketReplyEvent extends ApplicationEvent implements ApplicationCon
private void sendEmail(){
try {
List<Integer> userIds = Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> userIds = StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> adminUsers = adminUserService.listByIds(userIds);
if (CollectionUtil.isNotEmpty(adminUsers)) {
AppUser appUser=appUserService.getById(ticket.getUserId());

View File

@ -7,9 +7,9 @@ import cn.hutool.json.JSONUtil;
import com.nflg.mobilebroken.admin.pojo.dto.SyncFromCrmDTO;
import com.nflg.mobilebroken.admin.pojo.dto.TiketTimeoutDTO;
import com.nflg.mobilebroken.admin.publisher.TicketEventPublisher;
import com.nflg.mobilebroken.admin.service.SsePushService;
import com.nflg.mobilebroken.admin.service.AdminCustomerService;
import com.nflg.mobilebroken.admin.service.AdminDeviceService;
import com.nflg.mobilebroken.admin.service.SsePushService;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.constant.MessageSubType;
import com.nflg.mobilebroken.common.constant.UserState;
@ -28,13 +28,12 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@Component
@ -251,9 +250,7 @@ public class TicketScheduledTasks {
private void ticketHande(Ticket ticket) {
AppUser createUser=appUserService.getById(ticket.getUserId());
//处理人
Set<Integer> adminUserIds = Arrays.stream(ticket.getHandle().split(","))
.map(Integer::parseInt)
.collect(Collectors.toSet());
Set<Integer> adminUserIds = StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toSet());
//CQM
adminUserIds.add(ticket.getCqm());
//管理端关注人

View File

@ -70,7 +70,7 @@ public class TiketController extends ControllerBase {
private IAppAreaService appAreaService;
@Resource
private ITBaseAreaService adminAreaService;
private ITicketSolutionService ticketSolutionService;
@Resource
private ITBaseCustomerService customerService;
@ -325,7 +325,8 @@ public class TiketController extends ControllerBase {
.setContent(request.getContent())
.setCreateTime(Instant.now())
.setAttachments(request.getAttachments())
.setImages(request.getImages());
.setImages(request.getImages())
.setRemindUserIds(request.getRemindUserIds());
if(Objects.nonNull(request.getQuoteId())){
ChatMessageDTO quoteMessage = ticketChatService.getMessage(request.getTicketId(), request.getQuoteId());
message.setQuote(quoteMessage);
@ -417,4 +418,14 @@ public class TiketController extends ControllerBase {
}
return ApiResult.success();
}
/**
* 获取工单解决方案措施
* @param ticketId 工单编号
* @return 解决方案措施
**/
@GetMapping("getSolutionMeasures")
public ApiResult<SolutionMeasuresVO> getSolutionMeasures(@Valid @RequestParam @NotNull Integer ticketId){
return ApiResult.success(ticketSolutionService.getSolutionMeasures(ticketId));
}
}

View File

@ -16,7 +16,6 @@ import org.springframework.context.ApplicationEvent;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -52,7 +51,7 @@ public class TicketCloseEvent extends ApplicationEvent implements ApplicationCon
private void sendUserMessage(){
//我的待办
List<Integer> userIds= Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> userIds= StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> adminUsers=adminUserService.listByIds(userIds);
if (CollectionUtil.isNotEmpty(adminUsers)){
adminUsers.forEach(c -> adminMessageService.add(

View File

@ -25,7 +25,6 @@ import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -66,7 +65,7 @@ public class TicketReplyEvent extends ApplicationEvent implements ApplicationCon
private void sendUserMessage(){
//我的待办
if(StrUtil.isNotBlank(ticket.getHandle())) {
List<Integer> userIds = Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> userIds = StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> adminUsers = adminUserService.listByIds(userIds);
if (CollectionUtil.isNotEmpty(adminUsers)) {
adminUsers.forEach(c -> adminMessageService.add(
@ -87,7 +86,7 @@ public class TicketReplyEvent extends ApplicationEvent implements ApplicationCon
private void sendEmail() {
try {
List<Integer> userIds = Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> userIds = StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> adminUsers = adminUserService.listByIds(userIds);
if (CollectionUtil.isNotEmpty(adminUsers)) {
AppUser appUser = appUserService.getById(ticket.getUserId());

View File

@ -20,7 +20,6 @@ import org.springframework.context.ApplicationEvent;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -73,7 +72,7 @@ public class TicketRevokeEvent extends ApplicationEvent implements ApplicationCo
.setIsRead(false)
.setCreateTime(LocalDateTime.now()));
//处理人
List<Integer> userIds= Arrays.stream(ticket.getHandle().split(",")).filter(StrUtil::isNotBlank).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> userIds= StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
List<AdminUser> adminUsers=adminUserService.listByIds(userIds);
if (CollectionUtil.isNotEmpty(adminUsers)){
adminUsers.forEach(c -> adminMessageService.add(

View File

@ -43,4 +43,7 @@ public class ChatMessageDTO {
// 引用的消息
private ChatMessageDTO quote;
//被艾特的用户id列表
private List<Integer> remindUserIds;
}

View File

@ -23,4 +23,7 @@ public class AddChatMessageRequest {
// 引用的消息
private String quoteId;
//被艾特的用户id列表
private List<Integer> remindUserIds;
}

View File

@ -167,7 +167,7 @@ public class AdminTicketVO {
if (Objects.isNull(accidentLevel)) {
return "";
}
return TicketAccidentLevel.findByValue(accidentLevel).getDescription();
return Objects.requireNonNull(TicketAccidentLevel.findByValue(accidentLevel), "无效的事故等级:" + accidentLevel).getDescription();
}
//是否已关注
@ -178,14 +178,14 @@ public class AdminTicketVO {
private String followedDesc;
public String getStateDesc() {
return TicketState.findByValue(state).getDescription();
return Objects.requireNonNull(TicketState.findByValue(state), "无效的状态:" + state).getDescription();
}
public String getUrgencyDesc() {
if (Objects.isNull(urgency)) {
return "";
}
return TicketUrgency.findByValue(urgency).getDescription();
return Objects.requireNonNull(TicketUrgency.findByValue(urgency), "无效的紧急程度:" + urgency).getDescription();
}
public String getFollowedDesc() {

View File

@ -8,6 +8,9 @@ public class AdminUserSimpleVO {
// 用户ID
private Integer userId;
// 头像
private String avatar;
// 用户名
private String userName;

View File

@ -91,11 +91,12 @@ public class TicketSolution implements Serializable {
Objects.equals(description, that.description) &&
Objects.equals(superintendent, that.superintendent) &&
Objects.equals(scheduleDate, that.scheduleDate) &&
Objects.equals(confirmedDate, that.confirmedDate);
Objects.equals(confirmedDate, that.confirmedDate) &&
Objects.equals(remark, that.remark);
}
@Override
public int hashCode() {
return Objects.hash(id, ticketId, dictionaryItemId, description, superintendent, scheduleDate, confirmedDate);
return Objects.hash(id, ticketId, dictionaryItemId, description, superintendent, scheduleDate, confirmedDate,remark);
}
}

View File

@ -120,17 +120,17 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
@Override
public IPage<AdminTicketVO> searchPage(AdminTicketSearchRequest request) {
Integer userId = AdminUserUtil.getUserId();
if (Objects.nonNull(request.getFavouritesId())){
return baseMapper.searchByFavouritesId(AdminUserUtil.getUserId(),request.getFavouritesId(), new Page<>(request.getPage(), request.getPageSize()));
return baseMapper.searchByFavouritesId(userId,request.getFavouritesId(), new Page<>(request.getPage(), request.getPageSize()));
}else {
if (Objects.nonNull(request.getEndTime())) {
request.setEndTime(request.getEndTime().plusDays(1));
}
Integer userId = AdminUserUtil.getUserId();
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
request.setTicketManager(tickerMangagers.stream().anyMatch(uid -> Objects.equals(uid, userId)));
if (request.getType() == 2) {
return baseMapper.searchFromAdminAndFollow(request, AdminUserUtil.getUserId(), new Page<>(request.getPage(), request.getPageSize()));
return baseMapper.searchFromAdminAndFollow(request, userId, new Page<>(request.getPage(), request.getPageSize()));
} else if (request.getType() == 4) {
return baseMapper.searchFromAdmin(request, userId, new Page<>(request.getPage(), request.getPageSize()));
}
@ -198,7 +198,7 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()))
.throwMessage("非处理中状态不允许完成");
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
tickerMangagers.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
tickerMangagers.addAll(StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList()));
VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
.throwMessage("你无权完成工单");
VUtils.trueThrowBusinessError(!ticketSolutionService.lambdaQuery().eq(TicketSolution::getTicketId, id).exists())
@ -306,7 +306,7 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState())).throwMessage("工单状态异常");
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
tickerMangagers.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
tickerMangagers.addAll(StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList()));
VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
.throwMessage("你无权添加处理人");
ticket.setHandle(StrUtil.join(",", request.getUserIds()));
@ -327,8 +327,11 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
@Override
public List<AdminUserSimpleVO> getTicketHandle(Integer id) {
Ticket ticket=getById(id);
List<Integer> handles=Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList());
Ticket ticket=lambdaQuery().select(Ticket::getHandle).eq(Ticket::getId,id).one();
List<Integer> handles=StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
if (CollectionUtil.isEmpty(handles)){
return Collections.emptyList();
}
return adminUserService.getSimples(handles);
}

View File

@ -85,10 +85,22 @@ public class TicketSolutionAuditServiceImpl extends ServiceImpl<TicketSolutionAu
if (Objects.isNull(detp.getId())){
forAdd.add(audit);
VUtils.trueThrowBusinessError(lambdaQuery()
.eq(TicketSolutionAudit::getTicketId,request.getTicketId())
.eq(TicketSolutionAudit::getDeptName,detp.getDeptName())
.exists())
.throwMessage(detp.getDeptName()+"部门已设置了审核人员");
.eq(TicketSolutionAudit::getTicketId, request.getTicketId())
.eq(TicketSolutionAudit::getDeptName, detp.getDeptName())
.exists())
.throwMessage(detp.getDeptName() + "部门已设置了审核人员");
adminMessageService.add(
new AdminMessage()
.setNo(ticket.getNo())
.setTitle(ticket.getTitle())
.setUserId(detp.getUserId())
.setSourceId(ticket.getId())
.setSource(0)
.setType(MessageType.WorkOrderAssignment.getState())
.setSubType(MessageSubType.TicketSolutionAudit.getState())
.setIsRead(false)
.setCreateTime(LocalDateTime.now())
);
}else {
audit.setId(detp.getId());
TicketSolutionAudit entity=getById(detp.getId());

View File

@ -1,6 +1,7 @@
package com.nflg.mobilebroken.repository.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
@ -119,7 +120,7 @@ public class TicketSolutionServiceImpl extends ServiceImpl<TicketSolutionMapper,
.throwMessage("当前工单状态不允许修改解决方案");
Integer userId=AdminUserUtil.getUserId();
List<Integer> cqmIds=adminUserService.getCQMIds();
List<Integer> handleIds=Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList());
List<Integer> handleIds= StrUtil.split(ticket.getHandle(),",").stream().map(Integer::parseInt).collect(Collectors.toList());
VUtils.trueThrowBusinessError(cqmIds.stream().noneMatch(uid -> Objects.equals(uid, userId))
&& handleIds.stream().noneMatch(uid -> Objects.equals(uid, userId)))
.throwMessage("无权修改解决方案");

View File

@ -11,7 +11,7 @@
</select>
<select id="getSimples" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminUserSimpleVO">
SELECT au.id AS 'userId',au.user_code,au.user_name,dp.dept_name AS 'departmentName'
SELECT au.id AS 'userId',au.avatar,au.user_code,au.user_name,dp.dept_name AS 'departmentName'
FROM admin_user au
LEFT JOIN t_base_department dp ON au.department_id=dp.id
WHERE au.id IN

View File

@ -33,7 +33,7 @@
<where>
t.state!=4
<if test="!request.ticketManager">
AND FIND_IN_SET(#{userId},t.handle)>0
AND (FIND_IN_SET(#{userId},t.handle)>0 OR fun_inAduit(t.id,#{userId})=1)
</if>
<if test="request.state!=null">
AND t.state=#{request.state}