Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
804cf10a29
|
|
@ -89,7 +89,7 @@
|
|||
<dependency>
|
||||
<groupId>org.xhtmlrenderer</groupId>
|
||||
<artifactId>flying-saucer-pdf</artifactId>
|
||||
<version>9.1.22</version>
|
||||
<version>9.3.1</version>
|
||||
</dependency>
|
||||
<!-- iText (required by Flying Saucer) -->
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.nflg.mobilebroken.common.pojo.ApiResult;
|
|||
import com.nflg.mobilebroken.common.pojo.PageData;
|
||||
import com.nflg.mobilebroken.common.pojo.request.*;
|
||||
import com.nflg.mobilebroken.common.pojo.vo.*;
|
||||
import com.nflg.mobilebroken.common.util.AdminUserUtil;
|
||||
import com.nflg.mobilebroken.common.util.VUtils;
|
||||
import com.nflg.mobilebroken.repository.entity.AppUser;
|
||||
import com.nflg.mobilebroken.repository.entity.AppUserApplyfor;
|
||||
|
|
@ -195,6 +196,7 @@ public class AppUserController extends ControllerBase {
|
|||
.setAreaId(request.getAreaId())
|
||||
.setTitleId(request.getTitleId())
|
||||
.setCompanyId(StrUtil.join(",", request.getCompanyIds()))
|
||||
.setUpdateBy(AdminUserUtil.getUserName())
|
||||
.setUpdateTime(LocalDateTime.now());
|
||||
if (!Objects.equals(user.getState(), UserState.ToBeActivated.getState()) && Objects.nonNull(request.getEnable())) {
|
||||
user.setState(request.getEnable() ? UserState.Activated.getState() : UserState.Disabled.getState());
|
||||
|
|
@ -248,9 +250,9 @@ public class AppUserController extends ControllerBase {
|
|||
.setSalesUserName(request.getSalesUserName())
|
||||
.setPhone(request.getPhone())
|
||||
.setLanguageCode(request.getLanguageCode())
|
||||
.setAreaId(request.getAreaId())
|
||||
.setTitleId(request.getTitleId())
|
||||
.setCompanyId(StrUtil.join(",", request.getCompanyIds()))
|
||||
.setUpdateBy(AdminUserUtil.getUserName())
|
||||
.setUpdateTime(LocalDateTime.now());
|
||||
if (!Objects.equals(user.getState(), UserState.ToBeActivated.getState()) && Objects.nonNull(request.getEnable())) {
|
||||
user.setState(request.getEnable() ? UserState.Activated.getState() : UserState.Disabled.getState());
|
||||
|
|
|
|||
|
|
@ -108,7 +108,9 @@ public class DeviceComponentController extends ControllerBase {
|
|||
public ApiResult<Boolean> setPart(@Valid @RequestBody DeviceComponentDTO component){
|
||||
|
||||
if(CollUtil.isEmpty(component.getComponent())){
|
||||
throw new NflgException(STATE.ParamErr,"机型部件不能为空");
|
||||
//清空机型部件
|
||||
deviceComponentDetailService.delByComponentId(component.getId());
|
||||
return ApiResult.success(true);
|
||||
}
|
||||
DeviceComponent ent = Convert.convert(DeviceComponent.class, component);
|
||||
List<String> compinets = component.getComponent().stream().map(u -> u.getPartName()).collect(Collectors.toList());
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
package com.nflg.mobilebroken.admin.controller;
|
||||
|
||||
import com.nflg.mobilebroken.admin.annotation.ApiMark;
|
||||
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/sse")
|
||||
public class SSEController extends ControllerBase {
|
||||
|
||||
|
||||
@Resource
|
||||
private APPSSEManagerService sseManagerService;
|
||||
|
||||
/**
|
||||
* 建立sse连接
|
||||
*
|
||||
* @param userId 用户id
|
||||
*/
|
||||
@GetMapping(value = "connect", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@ApiMark(moduleName = "连接", apiName = "SSE", isPublic = true)
|
||||
public SseEmitter connect(@RequestParam String userId) {
|
||||
return sseManagerService.connect(Integer.valueOf(userId));
|
||||
}
|
||||
}
|
||||
|
|
@ -78,9 +78,6 @@ public class TicketController extends ControllerBase {
|
|||
@Resource
|
||||
private IAppAreaService appAreaService;
|
||||
|
||||
@Resource
|
||||
private ITBaseAreaService adminAreaService;
|
||||
|
||||
@Resource
|
||||
private IDictionaryItemService dictionaryItemService;
|
||||
|
||||
|
|
@ -99,6 +96,9 @@ public class TicketController extends ControllerBase {
|
|||
@Resource
|
||||
private ITicketFavoritesService ticketFavoritesService;
|
||||
|
||||
@Resource
|
||||
private ITBasePartService partService;
|
||||
|
||||
/**
|
||||
* 获取问题类型
|
||||
* @return 问题类型列表
|
||||
|
|
@ -195,6 +195,16 @@ public class TicketController extends ControllerBase {
|
|||
return ApiResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有设备部件
|
||||
* @param name 部件名称,模糊查询
|
||||
* @return 部件列表
|
||||
*/
|
||||
@GetMapping("getDeviceComponents")
|
||||
public ApiResult<List<String>> getDeviceComponents(@RequestParam String name){
|
||||
return ApiResult.success(partService.getSimpleList(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索工单
|
||||
* @param request 请求参数
|
||||
|
|
@ -229,7 +239,7 @@ public class TicketController extends ControllerBase {
|
|||
}
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(item.getChildren())) {
|
||||
item.getChildren().removeIf(child -> !child.getSelected());
|
||||
item.getChildren().removeIf(child -> !Objects.equals(child.getSelected(),true));
|
||||
}
|
||||
});
|
||||
vo.getServiceEvaluation().removeIf(item -> !item.getSelected());
|
||||
|
|
@ -246,10 +256,10 @@ public class TicketController extends ControllerBase {
|
|||
}
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(item.getChildren())) {
|
||||
item.getChildren().removeIf(child -> !child.getSelected());
|
||||
item.getChildren().removeIf(child ->!Objects.equals(child.getSelected(),true));
|
||||
}
|
||||
});
|
||||
vo.getExperienceEvaluation().removeIf(item -> !item.getSelected());
|
||||
vo.getExperienceEvaluation().removeIf(item -> !Objects.equals(item.getSelected(),true));
|
||||
return new TicketEvaluateVO()
|
||||
.setScore(ticketEvaluate.getScore())
|
||||
.setFeedback(ticketEvaluate.getFeedback())
|
||||
|
|
@ -290,6 +300,7 @@ public class TicketController extends ControllerBase {
|
|||
ticketChatService.addMessage(ticket.getId(), message);
|
||||
//推送消息
|
||||
ssePushService.sendTicketMessageToApp(ticket.getId(),message);
|
||||
ssePushService.sendTicketMessageToAdmin(ticket.getId(),message);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
|
|
@ -363,6 +374,18 @@ public class TicketController extends ControllerBase {
|
|||
for (Integer id : ids){
|
||||
Ticket ticket=ticketService.rejectTicket(id);
|
||||
// ticketEventPublisher.publishTicketCompleteEvent(ticket);
|
||||
ChatMessageDTO message = new ChatMessageDTO()
|
||||
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
|
||||
.setFrom("system")
|
||||
.setTicketState(ticket.getState())
|
||||
.setSenderId(0)
|
||||
.setSenderName("服务助手")
|
||||
.setContent("<b>工单驳回</b><br/>工单被驳回,请继续跟进处理。")
|
||||
.setCreateTime(Instant.now());
|
||||
ticketChatService.addMessage(id, message);
|
||||
//推送消息
|
||||
ssePushService.sendTicketMessageToAdmin(id,message);
|
||||
ssePushService.sendTicketMessageToApp(id,message);
|
||||
}
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
|
@ -414,9 +437,9 @@ public class TicketController extends ControllerBase {
|
|||
if (StrUtil.isNotBlank(ticket.getAttachments())) {
|
||||
StrUtil.split(ticket.getAttachments(), ",").forEach(item -> {
|
||||
if (item.endsWith(".jpg") || item.endsWith(".png") || item.endsWith(".jpeg")) {
|
||||
images.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),item));
|
||||
images.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),urlEncode(item)));
|
||||
} else {
|
||||
files.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),item));
|
||||
files.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),urlEncode(item)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -425,6 +448,24 @@ public class TicketController extends ControllerBase {
|
|||
images.add(new FileInfo(item.substring(item.lastIndexOf("/")+1),item));
|
||||
});
|
||||
}
|
||||
//加上聊天中的图片和文件
|
||||
List<ChatMessageVO> messageVOS=ticketChatService.getMessages(ticket.getId());
|
||||
messageVOS.forEach(messageVO -> {
|
||||
if (CollectionUtil.isNotEmpty(messageVO.getImages())){
|
||||
messageVO.getImages().forEach(image -> {
|
||||
images.add(new FileInfo(image.substring(image.lastIndexOf("/")+1),image));
|
||||
});
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(messageVO.getAttachments())){
|
||||
messageVO.getAttachments().forEach(attachment -> {
|
||||
if (attachment.endsWith(".jpg") || attachment.endsWith(".png") || attachment.endsWith(".jpeg")) {
|
||||
images.add(new FileInfo(attachment.substring(attachment.lastIndexOf("/")+1),urlEncode(attachment)));
|
||||
} else {
|
||||
files.add(new FileInfo(attachment.substring(attachment.lastIndexOf("/")+1),urlEncode(attachment)));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
TicketPdfVO vo = new TicketPdfVO()
|
||||
.setNo(ticket.getNo())
|
||||
.setTitle(ticket.getTitle())
|
||||
|
|
@ -476,7 +517,7 @@ public class TicketController extends ControllerBase {
|
|||
// renderer.layout();
|
||||
// renderer.createPDF(response.getOutputStream());
|
||||
ITextRenderer renderer = new ITextRenderer();
|
||||
BaseFont baseFont = BaseFont.createFont("fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
|
||||
// BaseFont baseFont = BaseFont.createFont("fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
|
||||
renderer.getFontResolver().addFont("fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
|
||||
renderer.setDocumentFromString(html);
|
||||
renderer.layout();
|
||||
|
|
@ -490,6 +531,13 @@ public class TicketController extends ControllerBase {
|
|||
}
|
||||
}
|
||||
|
||||
private String urlEncode(String url){
|
||||
int index = url.lastIndexOf("/");
|
||||
String pre= url.substring(0,index+1);
|
||||
String end = url.substring(index+1);
|
||||
return pre+URLEncoder.encode(end, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取工单详情
|
||||
* @param id 工单编号
|
||||
|
|
@ -499,10 +547,10 @@ public class TicketController extends ControllerBase {
|
|||
public ApiResult<TicketInfoVO> getTicket(@Valid @RequestParam @NotNull Integer id) {
|
||||
Ticket ticket = ticketService.getById(id);
|
||||
AppUser user = appUserService.getById(ticket.getUserId());
|
||||
String areaName;
|
||||
String areaName = "";
|
||||
if (user.getIsPrimary()){
|
||||
areaName=adminAreaService.getById(user.getAreaId()).getAreaName();
|
||||
}else {
|
||||
areaName=StrUtil.join(",",customerService.getAreas(Arrays.stream(user.getCompanyId().split(",")).map(Integer::parseInt).collect(Collectors.toList())));
|
||||
}else if (Objects.nonNull(user.getAreaId())){
|
||||
areaName = appAreaService.getById(user.getAreaId()).getName();
|
||||
}
|
||||
// TBaseCustomer company = customerService.getById(Integer.valueOf(user.getCompanyId()));
|
||||
|
|
|
|||
|
|
@ -23,6 +23,5 @@ public class DeviceComponentDTO {
|
|||
/**
|
||||
* 机型部件-多个以逗号隔开
|
||||
*/
|
||||
@NotEmpty(message = "机型部件不能为空")
|
||||
private List<DeviceComponentDetailDTO> component;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
package com.nflg.mobilebroken.admin.service.impl;
|
||||
|
||||
import com.nflg.mobilebroken.common.constant.Constant;
|
||||
import com.nflg.mobilebroken.common.pojo.dto.UserDTO;
|
||||
import com.nflg.mobilebroken.starter.service.INotifyPushService;
|
||||
import com.nflg.mobilebroken.starter.service.SSEManagerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class SSEINotifyPushService implements INotifyPushService {
|
||||
|
||||
@Resource
|
||||
@Qualifier("APPSSEManagerService")
|
||||
private SSEManagerService sseManagerService;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public void push(UserDTO user, String subject, String content) {
|
||||
// try {
|
||||
// SSEMessageDTO message = new SSEMessageDTO()
|
||||
// .setType(2)
|
||||
// .setData(new NotifyDTO().setSubject(subject).setContent(content));
|
||||
// sseManagerService.send(user.getId(), message);
|
||||
// } catch (IOException e) {
|
||||
// log.error("发送SSE失败", e);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(UserDTO user) {
|
||||
Object value = redisTemplate.opsForHash().get("message:config:" + user.getId(), Constant.REDIS_KEY_MESSAGECONFIG_APP);
|
||||
return Objects.isNull(value) || (boolean) value;
|
||||
}
|
||||
}
|
||||
|
|
@ -88,8 +88,8 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div th:each="file:${ticket.files}">
|
||||
<a th:href="${file.url}" th:text="${file.name}"></a>
|
||||
<div>
|
||||
<a th:each="file:${ticket.files}" th:href="${file.url}" th:text="${file.name}"></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div style="background-color: red;" th:each="file:${ticket.images}">
|
||||
<div th:each="file:${ticket.images}">
|
||||
<img class="cimg" alt="" th:src="${file.url}"/>
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
package com.nflg.mobilebroken.cfs.controller;
|
||||
|
||||
import com.nflg.mobilebroken.starter.service.impl.AdminSSEManagerService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 统计分析相关
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/analysis")
|
||||
public class AnalysisController extends ControllerBase{
|
||||
|
||||
@Resource
|
||||
private AdminSSEManagerService adminSSEManagerService;
|
||||
|
||||
/**
|
||||
* 获取当前已连接SSE的管理端用户列表
|
||||
* @return 当前已连接SSE的管理端用户列表
|
||||
*/
|
||||
@GetMapping("getSSEConnects")
|
||||
public Collection<Integer> getSSEConnects(){
|
||||
return adminSSEManagerService.getUserIds();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package com.nflg.mobilebroken.cfs.controller;
|
||||
|
||||
import com.nflg.mobilebroken.starter.service.impl.AdminSSEManagerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* sse相关接口
|
||||
* 曹鹏飞
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/sse")
|
||||
//@SaUserCheckLogin
|
||||
public class SSEController extends ControllerBase {
|
||||
|
||||
@Resource
|
||||
private AdminSSEManagerService adminSSEManagerService;
|
||||
|
||||
/**
|
||||
* 建立sse连接
|
||||
*
|
||||
* @param userId 用户id
|
||||
*/
|
||||
@GetMapping(value = "connect",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
public SseEmitter connect(@RequestParam Integer userId) {
|
||||
return adminSSEManagerService.connect(userId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,23 @@
|
|||
package com.nflg.mobilebroken.cfs.controller;
|
||||
|
||||
import com.nflg.mobilebroken.cfs.publisher.TicketEventPublisher;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import com.nflg.mobilebroken.common.constant.Constant;
|
||||
import com.nflg.mobilebroken.common.pojo.ApiResult;
|
||||
import com.nflg.mobilebroken.common.util.MultilingualUtil;
|
||||
import com.nflg.mobilebroken.repository.entity.AppUser;
|
||||
import com.nflg.mobilebroken.repository.entity.Ticket;
|
||||
import com.nflg.mobilebroken.repository.service.IAppUserService;
|
||||
import com.nflg.mobilebroken.repository.service.IDictionaryItemTranslateService;
|
||||
import com.nflg.mobilebroken.repository.service.ITicketService;
|
||||
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
|
||||
import com.nflg.mobilebroken.starter.service.EmailService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.mail.MessagingException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@RestController
|
||||
@Slf4j
|
||||
|
|
@ -19,27 +25,38 @@ import javax.annotation.Resource;
|
|||
public class TestController extends ControllerBase {
|
||||
|
||||
@Resource
|
||||
private APPSSEManagerService sseManagerService;
|
||||
|
||||
@Resource
|
||||
private TicketEventPublisher ticketEventPublisher;
|
||||
private IDictionaryItemTranslateService dictionaryItemTranslateService;
|
||||
|
||||
@Resource
|
||||
private ITicketService ticketService;
|
||||
|
||||
// @GetMapping("sse/send")
|
||||
// public ApiResult<Void> sendSse(@RequestParam String userId, @RequestParam String message) throws IOException {
|
||||
// SSEMessageDTO messageDTO = new SSEMessageDTO()
|
||||
// .setType(2)
|
||||
// .setData(new NotifyDTO().setSubject("消息测试").setContent("消息内容"));
|
||||
// sseManagerService.send(Integer.valueOf(userId), messageDTO);
|
||||
// return ApiResult.success();
|
||||
// }
|
||||
@Resource
|
||||
private IAppUserService appUserService;
|
||||
|
||||
@GetMapping("sss")
|
||||
public ApiResult sss(){
|
||||
Ticket ticket =ticketService.getById(8);
|
||||
ticketEventPublisher.publishTicketCreateEvent(ticket, MultilingualUtil.getLanguage(), MultilingualUtil.getZone());
|
||||
@Resource
|
||||
private EmailService emailService;
|
||||
|
||||
@GetMapping("sendEmail")
|
||||
public ApiResult sendEmail() throws MessagingException {
|
||||
Ticket ticket =ticketService.getById(1);
|
||||
AppUser appUser=appUserService.getById(ticket.getUserId());
|
||||
String subject=dictionaryItemTranslateService.getValueByCode(Constant.DICTIONARY_EMAIL_NOTIFY,Constant.DICTIONARY_ITEM_EMAIL_TITLE_TICKET_CREATE,Constant.DEFAULT_LANGUAGE_CODE);
|
||||
String content=dictionaryItemTranslateService.getValueByCode(Constant.DICTIONARY_EMAIL_NOTIFY,Constant.DICTIONARY_ITEM_EMAIL_CONTENT_TICKET_NOTIFY,Constant.DEFAULT_LANGUAGE_CODE)
|
||||
.replace("${no}",ticket.getNo())
|
||||
.replace("${title}",ticket.getTitle())
|
||||
.replace("${createUser}",appUser.getName())
|
||||
.replace("${handleUser}","")
|
||||
.replace("${createTime}",toTimeString(ticket.getCreateTime()))
|
||||
.replace("${msg}",subject);
|
||||
emailService.sendEmail("rakor@qq.com",subject,content);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
private String toTimeString(LocalDateTime time){
|
||||
// return time.atZone(ZoneOffset.UTC)
|
||||
// .withZoneSameInstant(ZoneId.of(zone))
|
||||
// .toLocalDateTime()
|
||||
// .format(FORMATTER);
|
||||
return time.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,10 +186,11 @@ public class TiketController extends ControllerBase {
|
|||
@GetMapping("getTicket")
|
||||
public ApiResult<TicketInfoVO> getTicket(@Valid @RequestParam @NotNull Integer id) {
|
||||
Ticket ticket = ticketService.getById(id);
|
||||
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
|
||||
AppUser user = appUserService.getById(ticket.getUserId());
|
||||
String areaName;
|
||||
if (user.getIsPrimary()){
|
||||
areaName=adminAreaService.getById(user.getAreaId()).getAreaName();
|
||||
areaName=StrUtil.join(",",customerService.getAreas(Arrays.stream(user.getCompanyId().split(",")).map(Integer::parseInt).collect(Collectors.toList())));
|
||||
}else {
|
||||
areaName = appAreaService.getById(user.getAreaId()).getName();
|
||||
}
|
||||
|
|
@ -355,6 +356,18 @@ public class TiketController extends ControllerBase {
|
|||
public ApiResult<Void> reopenTicket(@Valid @RequestParam @NotNull Integer id) {
|
||||
Ticket ticket=ticketService.reopen(id);
|
||||
ticketEventPublisher.publishTicketReopenEvent(ticket, MultilingualUtil.getLanguage(), MultilingualUtil.getZone());
|
||||
ChatMessageDTO message = new ChatMessageDTO()
|
||||
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr())
|
||||
.setFrom("system")
|
||||
.setTicketState(ticket.getState())
|
||||
.setSenderId(0)
|
||||
.setSenderName("服务助手")
|
||||
.setContent("<b>重启议题</b><br/>用户重启议题,请继续关注此工单信息。")
|
||||
.setCreateTime(Instant.now());
|
||||
ticketChatService.addMessage(id, message);
|
||||
//推送消息
|
||||
ssePushService.sendTicketMessageToAdmin(id,message);
|
||||
ssePushService.sendTicketMessageToApp(id,message);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
|
|||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.nflg.mobilebroken.cfs.service.WXQRCodeService;
|
||||
import com.nflg.mobilebroken.common.constant.Constant;
|
||||
import com.nflg.mobilebroken.common.constant.MessageSubType;
|
||||
|
|
@ -265,7 +266,16 @@ public class UserController extends ControllerBase {
|
|||
@PostMapping("deleteUser")
|
||||
//@SaUserCheckRole("primary")
|
||||
public ApiResult<Boolean> deleteUser(@Valid @RequestBody @NotEmpty List<Integer> ids){
|
||||
return ApiResult.success(appUserService.removeByIds(ids));
|
||||
appUserService.remove(new LambdaQueryWrapper<AppUser>()
|
||||
.eq(AppUser::getIsPrimary, false)
|
||||
.eq(AppUser::getCreateBy, AppUserUtil.getUserName())
|
||||
.in(AppUser::getId, ids));
|
||||
appUserApplyforService.remove(new LambdaQueryWrapper<AppUserApplyfor>()
|
||||
.eq(AppUserApplyfor::getState, 0)
|
||||
.eq(AppUserApplyfor::getIsPrimary, false)
|
||||
.eq(AppUserApplyfor::getCreateBy, AppUserUtil.getUserId())
|
||||
.in(AppUserApplyfor::getId, ids));
|
||||
return ApiResult.success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ import org.springframework.context.ApplicationEvent;
|
|||
|
||||
import javax.mail.MessagingException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -124,9 +122,10 @@ public class TicketCreateEvent extends ApplicationEvent implements ApplicationCo
|
|||
}
|
||||
|
||||
private String toTimeString(LocalDateTime time){
|
||||
return time.atZone(ZoneOffset.UTC)
|
||||
.withZoneSameInstant(ZoneId.of(zone))
|
||||
.toLocalDateTime()
|
||||
.format(FORMATTER);
|
||||
// return time.atZone(ZoneOffset.UTC)
|
||||
// .withZoneSameInstant(ZoneId.of(zone))
|
||||
// .toLocalDateTime()
|
||||
// .format(FORMATTER);
|
||||
return time.format(FORMATTER);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,17 @@ public class SsePushService {
|
|||
}
|
||||
}
|
||||
|
||||
public void sendTicketMessageToApp(Integer ticketId, ChatMessageDTO message){
|
||||
try {
|
||||
PushRequest request=new PushRequest().setTicketId(ticketId).setMessage(buildMessage(message));
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
ResponseEntity<ApiResult> response = restTemplate.postForEntity(sseUrl+"/sse/app/push",request, ApiResult.class);
|
||||
log.debug("发送消息结果:{}", JSONUtil.toJsonStr(response.getBody()));
|
||||
} catch (Exception e) {
|
||||
log.error("发送消息出错", e);
|
||||
}
|
||||
}
|
||||
|
||||
private ChatMessageVO buildMessage(ChatMessageDTO message){
|
||||
String zone = MultilingualUtil.getZone();
|
||||
ZoneId zoneId = ZoneId.of(zone);
|
||||
|
|
|
|||
|
|
@ -32,4 +32,7 @@ public class AdminTicketSearchRequest extends TicketSearchRequest {
|
|||
|
||||
//收藏夹id
|
||||
private Integer favouritesId;
|
||||
|
||||
//区域编码
|
||||
private String areaCode;
|
||||
}
|
||||
|
|
@ -3,8 +3,6 @@ package com.nflg.mobilebroken.common.pojo.request;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Data
|
||||
public class AppUserUpdateRequest extends PrimaryAppUserAddRequest {
|
||||
|
|
@ -15,6 +13,5 @@ public class AppUserUpdateRequest extends PrimaryAppUserAddRequest {
|
|||
private Boolean enable;
|
||||
|
||||
//区域id
|
||||
@NotNull
|
||||
private Integer areaId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,11 @@ public class AdminTicketVO {
|
|||
@ExcelColumn("解决方案")
|
||||
private String solution;
|
||||
|
||||
//区域名称
|
||||
//代理区域
|
||||
@ExcelColumn("代理区域")
|
||||
private String agentAreaName;
|
||||
|
||||
//区域
|
||||
@ExcelColumn("区域")
|
||||
private String areaName;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ public class AppUserForAdminVO {
|
|||
private String areaName;
|
||||
|
||||
public String getAreaName(){
|
||||
if (StrUtil.isBlank(areaName)){
|
||||
return areaName;
|
||||
}
|
||||
return StrUtil.join(",",Arrays.stream(areaName.split(",")).distinct().collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ public class FileVO {
|
|||
public String getSourceDesc() {
|
||||
if (source == 0) {
|
||||
return "工单";
|
||||
}else if (source==1){
|
||||
return "代理商";
|
||||
}else if (source==2){
|
||||
return "账号";
|
||||
}
|
||||
return "未知";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ public class AppUserApplyfor implements Serializable {
|
|||
*/
|
||||
private String salesUserName;
|
||||
|
||||
/**
|
||||
* 是否主账号
|
||||
*/
|
||||
private Boolean isPrimary;
|
||||
|
||||
/**
|
||||
* 创建人id
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.nflg.mobilebroken.common.pojo.dto.ExportPartDTO;
|
||||
import com.nflg.mobilebroken.common.pojo.query.PageBaseQuery;
|
||||
import com.nflg.mobilebroken.common.pojo.vo.DepartmentSimpleVO;
|
||||
import com.nflg.mobilebroken.repository.entity.DeviceComponent;
|
||||
import com.nflg.mobilebroken.repository.entity.TBaseDepartment;
|
||||
import com.nflg.mobilebroken.repository.entity.TBasePart;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
|
@ -25,4 +22,6 @@ public interface ITBasePartService extends IService<TBasePart> {
|
|||
Page<TBasePart> selectListByPage(@Param("query") PageBaseQuery query);
|
||||
|
||||
List<ExportPartDTO> exportPart(@Param("partNo")String partNo, @Param("partName") String partName);
|
||||
|
||||
List<String> getSimpleList(String name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,9 +172,9 @@ public class AppUserApplyforServiceImpl extends ServiceImpl<AppUserApplyforMappe
|
|||
}
|
||||
vo.setApplyfor(applyforInfo);
|
||||
appUser = appUserService.getById(applyfor.getCreateBy());
|
||||
TBaseArea area = baseAreaService.getById(appUser.getAreaId());
|
||||
List<String> areas=customerService.getAreas(Arrays.stream(appUser.getCompanyId().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
|
||||
vo.setUser(new AppUserVO()
|
||||
.setAreaName(area.getAreaName())
|
||||
.setAreaName(StrUtil.join(",",areas))
|
||||
.setSalesUserName(appUser.getSalesUserName())
|
||||
.setState(1)
|
||||
.setTitle(Objects.isNull(appUser.getTitleId()) ? "" : positionService.getById(appUser.getTitleId()).getPositionName())
|
||||
|
|
|
|||
|
|
@ -105,9 +105,6 @@ public class DictionaryItemServiceImpl extends ServiceImpl<DictionaryItemMapper,
|
|||
List<DictionaryItemTranslate> forAdd = new ArrayList<>();
|
||||
List<DictionaryItemTranslate> forUpdate = new ArrayList<>();
|
||||
for (TranslateMap translate : request.getLanguages()) {
|
||||
if(StrUtil.isBlank(translate.getValue())){
|
||||
continue;
|
||||
}
|
||||
DictionaryItemTranslate t = new DictionaryItemTranslate()
|
||||
.setDictionaryItemId(id)
|
||||
.setLanguageCode(translate.getCode())
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.nflg.mobilebroken.repository.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.nflg.mobilebroken.common.pojo.dto.ExportPartDTO;
|
||||
|
|
@ -11,6 +12,7 @@ import org.apache.ibatis.annotations.Param;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
@ -31,4 +33,15 @@ public class TBasePartServiceImpl extends ServiceImpl<TBasePartMapper, TBasePart
|
|||
public List<ExportPartDTO> exportPart(@Param("partNo")String partNo, @Param("partName") String partName){
|
||||
return this.getBaseMapper().exportPart(partNo,partName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSimpleList(String name) {
|
||||
return lambdaQuery()
|
||||
.eq(TBasePart::getEnable, 1)
|
||||
.like(StrUtil.isNotBlank(name),TBasePart::getPartName, name)
|
||||
.list()
|
||||
.stream()
|
||||
.map(TBasePart::getPartName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
|
|||
public Ticket assignmentTicket(AssignmentTicketRequest request) {
|
||||
Ticket ticket = getById(request.getTicketId());
|
||||
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
|
||||
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.PendingProcessing.getState())).throwMessage("工单状态异常");
|
||||
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.PendingProcessing.getState()))
|
||||
.throwMessage("非待处理状态不能分派工单");
|
||||
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
|
||||
VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
|
||||
.throwMessage("你无权分派工单");
|
||||
|
|
@ -172,11 +173,11 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
|
|||
public Ticket completeTicket(Integer id) {
|
||||
Ticket ticket=getById(id);
|
||||
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()))
|
||||
.throwMessage("工单状态不允许完成");
|
||||
.throwMessage("非处理中状态不允许完成");
|
||||
List<Integer> tickerMangagers = adminUserService.getTickerMangagers();
|
||||
tickerMangagers.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
|
||||
VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId())))
|
||||
.throwMessage("你无权添加处理人");
|
||||
.throwMessage("你无权完成工单");
|
||||
ticket.setState(TicketState.ProcessingCompleted.getState());
|
||||
ticket.setCurrentHandle(AdminUserUtil.getUserId());
|
||||
ticket.setUpdateTime(LocalDateTime.now());
|
||||
|
|
@ -189,7 +190,7 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
|
|||
Ticket ticket = getById(request.getTicketId());
|
||||
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
|
||||
VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.ProcessingCompleted.getState()))
|
||||
.throwMessage("工单状态不允许关闭");
|
||||
.throwMessage("非处理完成状态不允许关闭");
|
||||
VUtils.trueThrowBusinessError(!ticketEvaluateService.lambdaQuery()
|
||||
.eq(TicketEvaluate::getTicketId, request.getTicketId())
|
||||
.exists())
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
SELECT au.id
|
||||
FROM t_base_position p
|
||||
INNER JOIN admin_user au ON au.title_id=p.id
|
||||
WHERE p.position_code IN
|
||||
WHERE au.state=1 AND au.is_del=0 AND p.position_code IN
|
||||
<foreach collection="titleCodes" item="titleCode" separator="," open="(" close=")">
|
||||
#{titleCode}
|
||||
</foreach>
|
||||
|
|
|
|||
|
|
@ -102,32 +102,32 @@
|
|||
LEFT JOIN app_area aa ON au.area_id=aa.id
|
||||
LEFT JOIN app_user_applyfor aua ON aua.user_id=au.id AND aua.state=0
|
||||
LEFT JOIN t_base_position p ON au.title_id=p.id
|
||||
<where>
|
||||
<if test="loginName!=null and loginName!=''">
|
||||
AND au.login_name LIKE concat('%', #{loginName}, '%')
|
||||
</if>
|
||||
<if test="name!=null and name!=''">
|
||||
AND au.`name` LIKE concat('%', #{name}, '%')
|
||||
</if>
|
||||
<if test="companyName!=null and companyName!=''">
|
||||
AND fun_getUserCompanys(au.company_id) LIKE concat('%', #{companyName}, '%')
|
||||
</if>
|
||||
<if test="userState!=null">
|
||||
AND au.state=#{userState}
|
||||
</if>
|
||||
<if test="state==0">
|
||||
AND aua.id IS NOT NULL
|
||||
</if>
|
||||
<if test="state==1">
|
||||
AND aua.id IS NULL AND CONVERT_TZ(NOW(), @@session.time_zone, '+00:00') < au.expire_time
|
||||
</if>
|
||||
<if test="state==2">
|
||||
AND aua.id IS NULL AND CONVERT_TZ(NOW(), @@session.time_zone, '+00:00') >= au.expire_time
|
||||
</if>
|
||||
</where>
|
||||
WHERE au.is_del=0
|
||||
<if test="loginName!=null and loginName!=''">
|
||||
AND au.login_name LIKE concat('%', #{loginName}, '%')
|
||||
</if>
|
||||
<if test="name!=null and name!=''">
|
||||
AND au.`name` LIKE concat('%', #{name}, '%')
|
||||
</if>
|
||||
<if test="companyName!=null and companyName!=''">
|
||||
AND fun_getUserCompanys(au.company_id) LIKE concat('%', #{companyName}, '%')
|
||||
</if>
|
||||
<if test="userState!=null">
|
||||
AND au.state=#{userState}
|
||||
</if>
|
||||
<if test="state==0">
|
||||
AND aua.id IS NOT NULL
|
||||
</if>
|
||||
<if test="state==1">
|
||||
AND aua.id IS NULL AND CONVERT_TZ(NOW(), @@session.time_zone, '+00:00') < au.expire_time
|
||||
</if>
|
||||
<if test="state==2">
|
||||
AND aua.id IS NULL AND CONVERT_TZ(NOW(), @@session.time_zone, '+00:00') >= au.expire_time
|
||||
</if>
|
||||
UNION
|
||||
SELECT CONCAT('f-',aua.id) AS 'key',aua.id,aua.user_avatar AS 'avatar',aua.user_email AS 'loginName',aua.`user_name` AS 'userName',fun_getUserCompanys(aua.company_id) AS 'companyName',aua.user_name AS 'name',aua.user_email AS 'email',aua.sales_user_name,IF(aua.is_primary,fun_getPrimaryUserArea(aua.company_id),aa.`name`) AS 'areaName',0 AS 'userState',null AS 'expireTime',0 AS 'state',aua.create_by,aua.create_time,null AS 'updateBy',null AS 'updateTime',null AS 'lastLoginTime',aua.is_primary,aua.company_id,aua.user_phone AS 'phone',aua.area_id,aua.language_code,p.position_name AS 'title',aua.title_id
|
||||
SELECT CONCAT('f-',aua.id) AS 'key',aua.id,aua.user_avatar AS 'avatar',aua.user_email AS 'loginName',aua.`user_name` AS 'userName',fun_getUserCompanys(aua.company_id) AS 'companyName',aua.user_name AS 'name',aua.user_email AS 'email',aua.sales_user_name,IF(aua.is_primary,fun_getPrimaryUserArea(aua.company_id),aa.`name`) AS 'areaName',0 AS 'userState',null AS 'expireTime',0 AS 'state',au.name AS 'createBy',aua.create_time,null AS 'updateBy',null AS 'updateTime',null AS 'lastLoginTime',aua.is_primary,aua.company_id,aua.user_phone AS 'phone',aua.area_id,aua.language_code,p.position_name AS 'title',aua.title_id
|
||||
FROM app_user_applyfor aua
|
||||
LEFT JOIN app_user au ON au.id=aua.create_by
|
||||
LEFT JOIN app_area aa ON aua.area_id=aa.id
|
||||
LEFT JOIN t_base_position p ON aua.title_id=p.id
|
||||
WHERE aua.type=0 AND aua.state=0
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@
|
|||
SELECT d.device_no AS 'deviceNo',d.device_name AS 'deviceName',d.model_no AS 'modelNo',d.device_type AS 'deviceType',d.shipment_date AS 'shipmentDate'
|
||||
FROM device d
|
||||
INNER JOIN t_base_customer c ON d.agent_code=c.agency_company_code
|
||||
WHERE d.data_valid_state=1 AND c.id IN
|
||||
INNER JOIN dictionary_item di ON di.id=d.device_state
|
||||
WHERE d.data_valid_state=1 AND di.`code`='Normal' AND c.id IN
|
||||
<foreach collection="companyIds" open="(" close=")" item="companyId" separator=",">
|
||||
#{companyId}
|
||||
</foreach>
|
||||
|
|
@ -90,10 +91,10 @@
|
|||
</update>
|
||||
|
||||
<select id="getComponents" resultType="com.nflg.mobilebroken.common.pojo.vo.ComponentInfo">
|
||||
SELECT dcd.model_part_name AS 'name',ld.language_value AS 'languageValue'
|
||||
SELECT dcd.model_part_name AS 'name', ld.language_value AS 'languageValue'
|
||||
FROM device_component_detail dcd
|
||||
INNER JOIN t_base_part p ON dcd.model_part_id=p.id
|
||||
LEFT JOIN t_base_language_data ld ON dcd.model_part_id=ld.source_id
|
||||
WHERE dcd.device_component_id=#{componentId} AND ld.language_code=#{language}
|
||||
INNER JOIN t_base_part p ON dcd.model_part_id = p.id
|
||||
LEFT JOIN t_base_language_data ld ON dcd.model_part_id = ld.source_id
|
||||
WHERE p.enable=1 AND dcd.device_component_id=#{componentId} AND ld.language_code=#{language}
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@
|
|||
<if test="request.companyId!=null">
|
||||
AND u.company_id=#{request.companyId}
|
||||
</if>
|
||||
<if test="request.areaId!=null">
|
||||
AND u.area_id=#{request.areaId}
|
||||
<if test="request.areaCode!=null and request.areaCode!=''">
|
||||
AND FIND_IN_SET(#{request.areaCode},c.area_code)>0
|
||||
</if>
|
||||
<if test="request.question!=null and request.question!=''">
|
||||
AND t.question=#{request.question}
|
||||
|
|
@ -78,11 +78,10 @@
|
|||
</sql>
|
||||
|
||||
<select id="searchMy" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
|
||||
SELECT t.*,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
|
||||
SELECT t.*,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
|
||||
,u.`name` AS 'createBy',t.handle
|
||||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
LEFT JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=0
|
||||
WHERE t.user_id=#{userId} AND t.state!=4
|
||||
|
|
@ -91,10 +90,9 @@
|
|||
</select>
|
||||
|
||||
<select id="searchFollow" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
|
||||
SELECT t.*,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName',true AS 'followed',u.`name` AS 'createBy',true AS 'followed',t.handle
|
||||
SELECT t.*,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),a2.`name`) AS 'areaName',true AS 'followed',u.`name` AS 'createBy',true AS 'followed',t.handle
|
||||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.from=0
|
||||
WHERE tf.user_id=#{userId} AND t.state!=4
|
||||
|
|
@ -103,11 +101,10 @@
|
|||
</select>
|
||||
|
||||
<select id="searchArea" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
|
||||
SELECT t.*,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
|
||||
SELECT t.*,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),a2.`name`) AS 'areaName',IF(tf.id IS NULL, false, true) AS 'followed'
|
||||
,u.`name` AS 'createBy',t.handle
|
||||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
LEFT JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=0
|
||||
WHERE t.state!=4 AND u.company_id IN
|
||||
|
|
@ -119,7 +116,8 @@
|
|||
</select>
|
||||
|
||||
<select id="searchFromAdmin" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
|
||||
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
|
||||
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
|
||||
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
|
||||
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',IF(tf.id IS NULL, false, true) AS 'followed',auc.user_name AS 'cqm'
|
||||
|
|
@ -128,7 +126,6 @@
|
|||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_customer c ON u.company_id=c.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
|
||||
LEFT JOIN t_base_device_type dt ON d.device_type=dt.device_type
|
||||
|
|
@ -150,7 +147,8 @@
|
|||
<!-- </select>-->
|
||||
|
||||
<select id="searchAllFromAdmin" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
|
||||
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
|
||||
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
|
||||
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
|
||||
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',IF(tf.id IS NULL, false, true) AS 'followed',auc.user_name AS 'cqm'
|
||||
|
|
@ -159,7 +157,6 @@
|
|||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_customer c ON u.company_id=c.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
|
||||
LEFT JOIN t_base_device_type dt ON d.device_type=dt.device_type
|
||||
|
|
@ -172,7 +169,8 @@
|
|||
</select>
|
||||
|
||||
<select id="searchFromAdminAndFollow" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
|
||||
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
|
||||
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
|
||||
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
|
||||
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',true AS 'followed',auc.user_name AS 'cqm'
|
||||
|
|
@ -181,7 +179,6 @@
|
|||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_customer c ON u.company_id=c.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=1
|
||||
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
|
||||
|
|
@ -194,7 +191,8 @@
|
|||
</select>
|
||||
|
||||
<select id="searchAllFromAdminAndFollow" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
|
||||
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
|
||||
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
|
||||
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',true AS 'followed'
|
||||
,auc.user_name AS 'cqm',t.solve_time AS 'closeTime',u.name AS 'primaryUserName',auh.user_name AS 'currentHandle'
|
||||
|
|
@ -202,7 +200,6 @@
|
|||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_customer c ON u.company_id=c.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=1
|
||||
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
|
||||
|
|
@ -215,14 +212,18 @@
|
|||
</select>
|
||||
|
||||
<select id="getAdminFavorites" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
|
||||
SELECT t.id,t.no,t.title
|
||||
SELECT t.id, t.no, t.title
|
||||
FROM ticket_follow tf
|
||||
INNER JOIN ticket t ON tf.ticket_id=t.id
|
||||
WHERE tf.`from`=1 AND tf.user_id=#{userId} AND tf.favorites_id=#{favoritesId}
|
||||
INNER JOIN ticket t ON tf.ticket_id = t.id
|
||||
WHERE tf.`from` = 1
|
||||
AND tf.user_id = #{userId}
|
||||
AND tf.favorites_id = #{favoritesId}
|
||||
ORDER BY t.id DESC
|
||||
</select>
|
||||
|
||||
<select id="searchByFavouritesId" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO">
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,IF(u.is_primary,a1.area_name,a2.`name`) AS 'areaName'
|
||||
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution
|
||||
,IF(u.is_primary,fun_getPrimaryUserArea(u.company_id),'') AS 'areaName',IF(u.is_primary,'',a2.`name`) AS 'agentAreaName'
|
||||
,d.customer_name AS 'companyName',u.company_id AS 'companyId',u.`name` AS 'createBy',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
|
||||
,t.create_time AS 'createTime',t.update_time AS 'completeTime',di.name AS 'warrantyStatusDesc',d.device_type AS 'deviceType'
|
||||
,d.model_no AS 'equipmentModel',d.shipment_date AS 'shipmentDate',true AS 'followed',auc.user_name AS 'cqm'
|
||||
|
|
@ -231,7 +232,6 @@
|
|||
FROM ticket t
|
||||
LEFT JOIN app_user u ON t.user_id=u.id
|
||||
LEFT JOIN t_base_customer c ON u.company_id=c.id
|
||||
LEFT JOIN t_base_area a1 ON u.area_id=a1.id
|
||||
LEFT JOIN app_area a2 ON u.area_id=a2.id
|
||||
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId} AND tf.from=1 AND tf.favorites_id=#{favouritesId}
|
||||
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
package com.nflg.mobilebroken.starter.service;
|
||||
|
||||
import com.nflg.mobilebroken.common.constant.STATE;
|
||||
import com.nflg.mobilebroken.common.util.VUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
public class SSEManagerBase {
|
||||
|
||||
private static boolean IS_SHUTDOWN = false;
|
||||
|
||||
protected void check(){
|
||||
VUtils.trueThrow(IS_SHUTDOWN).throwMessage(STATE.ServiceConnectRefused,"SSE服务已关闭");
|
||||
}
|
||||
|
||||
protected static void shutdown(Map<Integer, SseEmitter> emitters) {
|
||||
IS_SHUTDOWN=true;
|
||||
log.warn("准备关闭SSE服务");
|
||||
emitters.forEach((k,v)->{
|
||||
try {
|
||||
v.send("因SSE服务关闭,连接即将断开");
|
||||
}catch (Exception ex){
|
||||
log.error("SSE发送消息失败:"+k,ex);
|
||||
}
|
||||
v.complete();
|
||||
});
|
||||
log.warn("SSE服务已关闭");
|
||||
}
|
||||
|
||||
protected static void close(SseEmitter emitter){
|
||||
emitter.complete();
|
||||
}
|
||||
|
||||
protected SseEmitter connect(Integer userId, Map<Integer, SseEmitter> emitters) {
|
||||
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
|
||||
SseEmitter old=emitters.put(userId, emitter);
|
||||
if (Objects.nonNull(old)){
|
||||
log.warn("停止旧连接:"+userId);
|
||||
try {
|
||||
old.send(SseEmitter.event().name("被踢下线").data("你已在其他地方连接"));
|
||||
old.complete();
|
||||
} catch (Exception e) {
|
||||
old.completeWithError(e);
|
||||
}
|
||||
}
|
||||
emitter.onError((ex) -> {
|
||||
emitters.remove(userId);
|
||||
emitter.complete();
|
||||
log.error("SSE异常:"+userId, ex);
|
||||
});
|
||||
emitter.onTimeout(() -> {
|
||||
emitters.remove(userId);
|
||||
emitter.complete();
|
||||
log.error("SSE超时:"+userId);
|
||||
});
|
||||
emitter.onCompletion(() -> {
|
||||
emitters.remove(userId);
|
||||
emitter.complete();
|
||||
log.error("SSE完成:"+userId);
|
||||
});
|
||||
try {
|
||||
emitter.send(SseEmitter.event().data("已连接").reconnectTime(5000));
|
||||
} catch (IOException e) {
|
||||
log.error("sse发送数据出错", e);
|
||||
}
|
||||
return emitter;
|
||||
}
|
||||
|
||||
protected void send(Object message, SseEmitter emitter) throws IOException {
|
||||
VUtils.trueThrowBusinessError(Objects.isNull(emitter)).throwMessage("没有找到sse");
|
||||
log.error("没有找到sse: ");
|
||||
emitter.send(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package com.nflg.mobilebroken.starter.service;
|
||||
|
||||
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface SSEManagerService {
|
||||
|
||||
SseEmitter connect(Integer userId);
|
||||
|
||||
void send(Integer userId, SSEMessageDTO message) throws IOException;
|
||||
|
||||
void close(Integer userId);
|
||||
|
||||
void shutdown();
|
||||
|
||||
Collection<Integer> getUserIds();
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
package com.nflg.mobilebroken.starter.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
|
||||
import com.nflg.mobilebroken.starter.service.SSEManagerBase;
|
||||
import com.nflg.mobilebroken.starter.service.SSEManagerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class APPSSEManagerService extends SSEManagerBase implements SSEManagerService {
|
||||
|
||||
public static final Map<Integer, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public SseEmitter connect(Integer userId) {
|
||||
check();
|
||||
log.info("APP端SSE已连接:"+userId);
|
||||
return connect(userId,EMITTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Integer userId, SSEMessageDTO message) throws IOException {
|
||||
log.info(StrUtil.format("APP端SSE发送消息,用户id: {},内容: {}", userId, message));
|
||||
SseEmitter emitter = EMITTERS.get(userId);
|
||||
if (Objects.isNull(emitter)) {
|
||||
log.error("用户未连接SSE: " + userId);
|
||||
} else {
|
||||
send(message, emitter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(Integer userId) {
|
||||
log.info("APP端SSE连接主动关闭:"+userId);
|
||||
close(EMITTERS.remove(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
shutdown(EMITTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Integer> getUserIds() {
|
||||
return EMITTERS.keySet();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void cleanup() {
|
||||
log.info("释放SSE连接");
|
||||
for (SseEmitter emitter : EMITTERS.values()) {
|
||||
try {
|
||||
emitter.complete();
|
||||
} catch (Exception e) {
|
||||
emitter.completeWithError(e);
|
||||
}
|
||||
}
|
||||
EMITTERS.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
package com.nflg.mobilebroken.starter.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
|
||||
import com.nflg.mobilebroken.starter.service.SSEManagerBase;
|
||||
import com.nflg.mobilebroken.starter.service.SSEManagerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AdminSSEManagerService extends SSEManagerBase implements SSEManagerService {
|
||||
|
||||
protected static final Map<Integer, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public SseEmitter connect(Integer userId) {
|
||||
check();
|
||||
log.info("管理端SSE已连接:"+userId);
|
||||
return connect(userId,EMITTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Integer userId, SSEMessageDTO message) throws IOException {
|
||||
log.info(StrUtil.format("管理端SSE发送消息,用户id: {},内容: {}", userId, message));
|
||||
SseEmitter emitter = EMITTERS.get(userId);
|
||||
if (Objects.isNull(emitter)) {
|
||||
log.error("用户未连接SSE: " + userId);
|
||||
} else {
|
||||
send(message, emitter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(Integer userId) {
|
||||
close(EMITTERS.remove(userId));
|
||||
log.info("管理端SSE连接主动关闭:"+userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
shutdown(EMITTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Integer> getUserIds() {
|
||||
return EMITTERS.keySet();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void cleanup() {
|
||||
log.info("释放SSE连接");
|
||||
for (SseEmitter emitter : EMITTERS.values()) {
|
||||
try {
|
||||
emitter.complete();
|
||||
} catch (Exception e) {
|
||||
emitter.completeWithError(e);
|
||||
}
|
||||
}
|
||||
EMITTERS.clear();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue