Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
luolm 2025-02-05 23:06:30 +08:00
commit 1cde6c4ad2
44 changed files with 577 additions and 96 deletions

View File

@ -1,13 +1,16 @@
package com.nflg.mobilebroken.admin.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.AdminMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.PageUtil;
import com.nflg.mobilebroken.repository.entity.AdminUser;
import com.nflg.mobilebroken.repository.service.IAdminMessageService;
import com.nflg.mobilebroken.repository.service.IAdminUserService;
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -17,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
/**
* 消息相关接口
@ -30,6 +34,9 @@ public class MessageController extends ControllerBase {
@Resource
private IAdminMessageService adminMessageService;
@Resource
private IAdminUserService adminUserService;
/**
* 搜索消息
*
@ -39,11 +46,15 @@ public class MessageController extends ControllerBase {
@PostMapping("searchMessages")
@MethodInfoMark(value = "搜索消息", menuName = "消息管理")
public ApiResult<PageData<AdminMessageVO>> searchMessages(@RequestBody AdminMessageSearchRequest request) {
IPage<AdminMessageVO> page = new Page<>();
page.setCurrent(request.getPage());
page.setSize(request.getPageSize());
adminMessageService.search(Constant.USER_ID, request, page);
return ApiResult.success(page);
IPage<AdminMessageVO> pageData = adminMessageService.search(AdminUserUtil.getUserId(), request);
PageUtil.convert(pageData, d -> {
d.setTicketHandleBy(adminUserService.listByIds(StrUtil.split(",", d.getTicketHandleByIds()))
.stream()
.map(AdminUser::getUserName)
.collect(Collectors.toList()));
return d;
});
return ApiResult.success(pageData);
}
/**
@ -57,4 +68,16 @@ public class MessageController extends ControllerBase {
adminMessageService.setReaded(ids);
return ApiResult.success();
}
/**
* 设置消息未读
*
* @param ids 消息id列表
*/
@PostMapping("setNotRead")
@MethodInfoMark(value = "设置消息未读", menuName = "消息管理")
public ApiResult<Void> setNotRead(@Valid @RequestBody List<Integer> ids) {
adminMessageService.setNotRead(ids);
return ApiResult.success();
}
}

View File

@ -57,7 +57,7 @@ public class MultilingualController extends ControllerBase {
*
* @return 语言列表
*/
@PostMapping("/getLanguage")
@GetMapping("/getLanguage")
@MethodInfoMark(value = "获取语言列表", menuName = "系统管理")
public ApiResult<List<LanguageVO>> getLanguage() {
List<Language> languages = languageService.getAllLanguages();

View File

@ -0,0 +1,37 @@
package com.nflg.mobilebroken.admin.controller;
import com.nflg.mobilebroken.common.constant.STATE;
import com.nflg.mobilebroken.common.exception.NflgException;
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;
import java.io.IOException;
@RestController
@Slf4j
@RequestMapping("/sse")
public class SSEController extends ControllerBase {
@Resource
private AdminSSEManagerService adminSSEManagerService;
@GetMapping(value = "connect", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter connect(@RequestParam String userId) {
SseEmitter sse = adminSSEManagerService.connect(userId);
try {
sse.send("您已连接");
} catch (IOException e) {
log.error("sse发送数据出错", e);
sse.complete();
throw new NflgException(STATE.BusinessError, "sse发送数据出错");
}
return sse;
}
}

View File

@ -1,13 +1,12 @@
package com.nflg.mobilebroken.admin.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.AdminTicketSearchRequest;
import com.nflg.mobilebroken.common.pojo.request.AssignmentTicketRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO;
import com.nflg.mobilebroken.common.util.EecExcelUtil;
import com.nflg.mobilebroken.common.util.PageUtil;
import com.nflg.mobilebroken.repository.service.ITicketService;
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
import lombok.extern.slf4j.Slf4j;
@ -43,11 +42,7 @@ public class TicketController extends ControllerBase {
@PostMapping("searchTicket")
@MethodInfoMark(value = "搜索工单", menuName = "工单管理")
public ApiResult<PageData<AdminTicketVO>> searchTicket(@RequestBody AdminTicketSearchRequest request) {
IPage<AdminTicketVO> page = new Page<>();
page.setCurrent(request.getPageNum());
page.setSize(request.getPageSize());
ticketService.search(request, page);
return ApiResult.success(page);
return ApiResult.success(PageUtil.convert(ticketService.searchPage(request), d -> d));
}
/**
@ -58,7 +53,7 @@ public class TicketController extends ControllerBase {
@PostMapping("exportSearchTicket")
@MethodInfoMark(value = "导出搜索工单", menuName = "工单管理")
public void exportSearchTicket(HttpServletResponse response, @RequestBody AdminTicketSearchRequest request) throws IOException {
List<AdminTicketVO> datas = ticketService.search(request);
List<AdminTicketVO> datas = ticketService.exportSearch(request);
EecExcelUtil.export("工单", "sheet1", datas, response);
}

View File

@ -1,15 +1,18 @@
package com.nflg.mobilebroken.admin.service.impl;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.constant.STATE;
import com.nflg.mobilebroken.common.exception.NflgException;
import com.nflg.mobilebroken.common.pojo.dto.UserDTO;
import com.nflg.mobilebroken.starter.service.EmailService;
import com.nflg.mobilebroken.starter.service.INotifyPushService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Objects;
@Service
@Slf4j
@ -18,6 +21,9 @@ public class EmailINotifyPushService implements INotifyPushService {
@Resource
private EmailService emailService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Override
public void push(UserDTO user, String subject, String content) {
try {
@ -30,6 +36,10 @@ public class EmailINotifyPushService implements INotifyPushService {
@Override
public boolean check(UserDTO user) {
return StrUtil.isNotBlank(user.getEmail());
Object value = redisTemplate.opsForHash().get("message:config:" + user.getId(), Constant.REDIS_KEY_MESSAGECONFIG_EMAIL);
if (Objects.isNull(value) || (boolean) value) {
return StrUtil.isNotBlank(user.getEmail());
}
return false;
}
}

View File

@ -1,14 +1,17 @@
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.io.IOException;
import java.util.Objects;
@Service
@Slf4j
@ -18,6 +21,9 @@ public class SSEINotifyPushService implements INotifyPushService {
@Qualifier("APPSSEManagerService")
private SSEManagerService sseManagerService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Override
public void push(UserDTO user, String subject, String content) {
try {
@ -29,6 +35,7 @@ public class SSEINotifyPushService implements INotifyPushService {
@Override
public boolean check(UserDTO user) {
return true;
Object value = redisTemplate.opsForHash().get("message:config:" + user.getId(), Constant.REDIS_KEY_MESSAGECONFIG_APP);
return Objects.isNull(value) || (boolean) value;
}
}

View File

@ -1,14 +1,18 @@
package com.nflg.mobilebroken.admin.service.impl;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.dto.UserDTO;
import com.nflg.mobilebroken.starter.service.INotifyPushService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Objects;
@Service
@Slf4j
@ -23,6 +27,9 @@ public class WXINotifyPushService implements INotifyPushService {
@Resource
private WxMpConfigStorage wxMpConfigStorage;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Override
public void push(UserDTO user,String subject, String content) {
//TODO
@ -42,6 +49,10 @@ public class WXINotifyPushService implements INotifyPushService {
@Override
public boolean check(UserDTO user) {
Object value = redisTemplate.opsForHash().get("message:config:" + user.getId(), Constant.REDIS_KEY_MESSAGECONFIG_WX);
if (Objects.isNull(value) || (boolean) value) {
return StrUtil.isNotBlank(user.getWxOpenId());
}
return false;
}
}

View File

@ -2,7 +2,6 @@ package com.nflg.mobilebroken.cfs.controller;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.AreaSaveRequest;
@ -10,6 +9,7 @@ import com.nflg.mobilebroken.common.pojo.request.AreaSearchRequest;
import com.nflg.mobilebroken.common.pojo.request.EnableRequest;
import com.nflg.mobilebroken.common.pojo.vo.AreaSimpleVO;
import com.nflg.mobilebroken.common.pojo.vo.AreaVO;
import com.nflg.mobilebroken.common.util.AppUserUtil;
import com.nflg.mobilebroken.repository.entity.AppArea;
import com.nflg.mobilebroken.repository.service.IAppAreaService;
import org.springframework.web.bind.annotation.*;
@ -84,7 +84,7 @@ public class AreaController extends ControllerBase {
AppArea area=new AppArea()
.setId(request.getId())
.setEnable(request.getEnable())
.setUpdateBy(Constant.USER_NAME)
.setUpdateBy(AppUserUtil.getUserName())
.setUpdateTime(LocalDateTime.now());
return ApiResult.success(appAreaService.updateById(area));
}

View File

@ -9,6 +9,7 @@ import com.nflg.mobilebroken.common.pojo.request.AppMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.request.MessageConfigRequest;
import com.nflg.mobilebroken.common.pojo.vo.AppMessageVO;
import com.nflg.mobilebroken.common.pojo.vo.MessageConfigVO;
import com.nflg.mobilebroken.common.util.AppUserUtil;
import com.nflg.mobilebroken.repository.service.IAppMessageService;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
@ -45,7 +46,7 @@ public class MessageController extends ControllerBase {
IPage<AppMessageVO> page = new Page<>();
page.setCurrent(request.getPage());
page.setSize(request.getPageSize());
appMessageService.search(Constant.USER_ID, request.getTitle(), page);
appMessageService.search(AppUserUtil.getUserId(), request.getTitle(), page);
return ApiResult.success(page);
}
@ -60,6 +61,17 @@ public class MessageController extends ControllerBase {
return ApiResult.success();
}
/**
* 设置消息未读
*
* @param ids 消息id列表
*/
@PostMapping("setNotRead")
public ApiResult<Void> setNotRead(@Valid @RequestBody List<Integer> ids) {
appMessageService.setNotRead(ids);
return ApiResult.success();
}
/**
* 获取未读消息
* @param num 获取未读消息的数量
@ -70,7 +82,7 @@ public class MessageController extends ControllerBase {
IPage<AppMessageVO> page = new Page<>();
page.setCurrent(1);
page.setSize(num);
appMessageService.getNotReadMessage(Constant.USER_ID, num, page);
appMessageService.getNotReadMessage(AppUserUtil.getUserId(), num, page);
return ApiResult.success(page);
}
@ -81,11 +93,11 @@ public class MessageController extends ControllerBase {
@GetMapping("getConfig")
public ApiResult<MessageConfigVO> getConfig(){
HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
Map<String, Object> maps=hashOps.entries("message:config:" + Constant.USER_ID);
Map<String, Object> maps = hashOps.entries("message:config:" + AppUserUtil.getUserId());
return ApiResult.success(new MessageConfigVO()
.setAppNotifyEnabled((Boolean) maps.getOrDefault("appNotifyEnabled",true))
.setEmailNotifyEnabled((Boolean) maps.getOrDefault("emailNotifyEnabled",true))
.setWxNotifyEnabled((Boolean) maps.getOrDefault("wxNotifyEnabled",true))
.setAppNotifyEnabled((Boolean) maps.getOrDefault(Constant.REDIS_KEY_MESSAGECONFIG_APP, true))
.setEmailNotifyEnabled((Boolean) maps.getOrDefault(Constant.REDIS_KEY_MESSAGECONFIG_EMAIL, true))
.setWxNotifyEnabled((Boolean) maps.getOrDefault(Constant.REDIS_KEY_MESSAGECONFIG_WX, true))
);
}
@ -96,11 +108,11 @@ public class MessageController extends ControllerBase {
@PostMapping("setConfig")
public ApiResult<Void> setConfig(@Valid @RequestBody MessageConfigRequest request) {
Map<String, Object> maps = new HashMap<>();
maps.put("wxNotifyEnabled", request.isWxNotifyEnabled());
maps.put("emailNotifyEnabled", request.isEmailNotifyEnabled());
maps.put("appNotifyEnabled", request.isAppNotifyEnabled());
maps.put(Constant.REDIS_KEY_MESSAGECONFIG_WX, request.isWxNotifyEnabled());
maps.put(Constant.REDIS_KEY_MESSAGECONFIG_EMAIL, request.isEmailNotifyEnabled());
maps.put(Constant.REDIS_KEY_MESSAGECONFIG_APP, request.isAppNotifyEnabled());
HashOperations<String, String, Object> operations = redisTemplate.opsForHash();
operations.putAll("message:config:" + Constant.USER_ID, maps);
operations.putAll("message:config:" + AppUserUtil.getUserId(), maps);
return ApiResult.success();
}
}

View File

@ -40,7 +40,7 @@ public class SystemController extends ControllerBase {
.map(l->new LanguageVO()
.setCode(l.getCode())
.setName(l.getName())
.setVaLue(l.getValue())
.setValue(l.getValue())
.setIco(l.getIco())
.setSort(l.getSort())
.setEnable(l.getEnable()))

View File

@ -7,6 +7,7 @@ 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.AppUserUtil;
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.entity.TicketChat;
@ -51,6 +52,12 @@ public class TiketController extends ControllerBase {
@Resource
private ITicketEvaluateService ticketEvaluateService;
@Resource
private IAdminMessageService adminMessageService;
@Resource
private IDictionaryItemTranslateService dictionaryItemTranslateService;
/**
* 搜索设备
*
@ -90,7 +97,8 @@ public class TiketController extends ControllerBase {
**/
@PostMapping("/addTiket")
public ApiResult<Void> addTiket(@Valid @RequestBody TicketAddRequest request) {
ticketService.add(request, AppUserUtil.getUserId());
Integer ticketId = ticketService.add(request, AppUserUtil.getUserId());
adminMessageService.addCQMNotify(ticketId);
return ApiResult.success();
}
@ -175,6 +183,15 @@ public class TiketController extends ControllerBase {
return ApiResult.success();
}
/**
* 获取工单评价数据
**/
@GetMapping("getTicketEvaluateSelect")
public ApiResult<TicketEvaluateVO> getTicketEvaluateSelect() {
String language = MultilingualUtil.getLanguage();
return ApiResult.success(dictionaryItemTranslateService.getTicketEvaluateSelect(language));
}
/**
* 添加工单评价
*

View File

@ -0,0 +1,33 @@
package com.nflg.mobilebroken.cfs.runner;
import cn.hutool.core.collection.CollectionUtil;
import com.nflg.mobilebroken.common.util.MultilingualUtil;
import com.nflg.mobilebroken.repository.entity.Language;
import com.nflg.mobilebroken.repository.service.ILanguageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@Slf4j
public class InitZoneMap implements CommandLineRunner {
@Resource
private ILanguageService languageService;
@Override
public void run(String... args) {
log.info("初始化语言区域映射");
List<Language> languages = languageService.getLanguages();
if (CollectionUtil.isNotEmpty(languages)) {
Map<String, String> map = languages.stream()
.collect(Collectors.toMap(Language::getCode, Language::getZone));
MultilingualUtil.setZoneMap(map);
}
}
}

View File

@ -2,13 +2,26 @@ package com.nflg.mobilebroken.common.constant;
public class Constant {
public static final String USER_NAME="admin";
public static final Integer USER_ID=1;
public static final String DICTIONARY_TYPE_SERVICE_EVALUATION = "ServiceEvaluation";
public static final String DICTIONARY_TYPE_SERVICE_EVALUATION_SELECT = "ServiceEvaluationSelect";
public static final String DICTIONARY_TYPE_EXPERIENCE_EVALUATION = "ExperienceEvaluation";
public static final String DICTIONARY_TYPE_EXPERIENCE_EVALUATION_SELECT = "ExperienceEvaluationSelect";
//字典 类型 用户职位
public static final String DICTIONARY_TYPE_TITLE="UserTitle";
public static final String DICTIONARY_TYPE_LANGUAGE="Language";
public static final String DICTIONARY_TYPE_TITLE_CQM = "CQM";
public static final String REDIS_KEY_USER_UPDATE_KAPTCHA = "kaptcha:userupdate:{}";
public static final String DICTIONARY_TYPE_SYSTEMERROR_CQMNOTCONFIG = "CQMNotConfig";
public static final String REDIS_KEY_MESSAGECONFIG_WX = "wxNotifyEnabled";
public static final String REDIS_KEY_MESSAGECONFIG_EMAIL = "emailNotifyEnabled";
public static final String REDIS_KEY_MESSAGECONFIG_APP = "appNotifyEnabled";
}

View File

@ -3,6 +3,7 @@ package com.nflg.mobilebroken.common.pojo.request;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@ -11,6 +12,10 @@ public class SaveDictionaryItemRequest {
//字典值id
private Integer id;
//字典id
@NotNull
private Integer dictionaryId;
//字典值名称
@NotBlank(message = "字典名称不能为空")
private String name;

View File

@ -1,14 +1,16 @@
package com.nflg.mobilebroken.common.pojo.request;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = false)
@Data
public class TicketSearchRequest {
public class TicketSearchRequest extends PageRequest {
//搜索类型1: 我的工单,2: 我的关注,3: 区域工单
//搜索类型1: 我的工单,2: 我的关注,3: 区域工单,4: 全部工单
@NotNull(message = "搜索类型不能为空")
private Integer type;
@ -32,10 +34,4 @@ public class TicketSearchRequest {
//结束日期
private LocalDateTime endTime;
//页码
private Integer pageNum=1;
//每页数量
private Integer pageSize=10;
}

View File

@ -1,14 +1,28 @@
package com.nflg.mobilebroken.common.pojo.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.nflg.mobilebroken.common.constant.MessageType;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Accessors(chain = true)
public class AdminMessageVO {
//任务id
private Integer ticketId;
//任务编号
private String ticketNo;
//任务事项
private String content;
//任务类别
@JsonIgnore
private Integer type;
//任务类别名称
@ -17,4 +31,22 @@ public class AdminMessageVO {
public String getTypeName() {
return MessageType.findByValue(type).getDescription();
}
//消息时间
private LocalDateTime createTime;
//提交人
private String createUserName;
//任务提交时间
private LocalDateTime ticketCreateTime;
@JsonIgnore
private String ticketHandleByIds;
//待处理人
private List<String> ticketHandleBy;
//是否已读
private boolean isRead;
}

View File

@ -10,6 +10,7 @@ import org.ttzero.excel.annotation.IgnoreExport;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
@Data
public class AdminTicketVO {
@ -34,77 +35,101 @@ public class AdminTicketVO {
//解决状态
@ExcelColumn("解决状态")
private String stateDesc;
//紧急程度
@IgnoreExport
@JsonIgnore
private Integer urgency;
//紧急程度
@ExcelColumn("紧急程度")
private String urgencyDesc;
//问题部位
@ExcelColumn("问题部位")
private String component;
//问题类型
@ExcelColumn("问题类型")
private String question;
//解决方案
@ExcelColumn("解决方案")
private String solution;
//区域名称
@ExcelColumn("区域")
private String areaName;
//代理商名称
@ExcelColumn("代理商")
private String companyName;
//客户
@ExcelColumn("客户")
private String createUserName;
//设备编号
@ExcelColumn("设备编号")
private String deviceNo;
//设备类型
@ExcelColumn("设备类型")
private String deviceType;
//设备机型
@ExcelColumn("设备机型")
private String equipmentModel;
//发货日期
@ExcelColumn("发货日期")
private String shipmentDate;
//使用时长
@ExcelColumn("使用时长(小时)")
private Integer useTime;
//质保状态
@ExcelColumn("质保状态")
private String warrantyStatusDesc;
//提交时间
@ExcelColumn("提交时间")
private LocalDateTime createTime;
//提交人
@ExcelColumn("提交人")
private String createBy;
//所属CQM
@ExcelColumn("所属CQM")
private String cqm;
//处理人
@JsonIgnore
@IgnoreExport
private String handle;
//处理人
@ExcelColumn("处理人")
private List<String> handleBy;
//当前处理人
@ExcelColumn("当前处理人")
private List<String> currentProcessor;
//处理完成时间
@ExcelColumn("处理完成时间")
private LocalDateTime solveTime;
//关闭时间
@ExcelColumn("关闭时间")
private LocalDateTime closeTime;
//是否已关注
@IgnoreExport
private boolean followed;
@ExcelColumn("关注")
private String followedDesc;
@ -113,6 +138,9 @@ public class AdminTicketVO {
}
public String getUrgencyDesc() {
if (Objects.isNull(urgency)) {
return "";
}
return TicketUrgency.findByValue(urgency).getDescription();
}

View File

@ -14,7 +14,7 @@ public class LanguageVO {
private String name;
//语言名称
private String vaLue;
private String value;
//图标url
private String ico;

View File

@ -0,0 +1,13 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
@Data
public class TicketEvaluateItemVO {
//编码
private String code;
//描述
private String desc;
}

View File

@ -0,0 +1,21 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import java.util.List;
@Data
public class TicketEvaluateVO {
// 售后服务评价
private List<TicketEvaluateItemVO> serviceEvaluation;
// 售后服务评价选择项
private List<TicketEvaluateItemVO> serviceEvaluationSelect;
// 产品体验评价
private List<TicketEvaluateItemVO> experienceEvaluation;
// 产品体验评价选择项
private List<TicketEvaluateItemVO> experienceEvaluationSelect;
}

View File

@ -0,0 +1,40 @@
package com.nflg.mobilebroken.common.util;
import cn.hutool.core.map.MapUtil;
import java.util.Map;
public class MultilingualUtil {
private static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>();
private static final Map<String, String> ZONE_MAP = MapUtil.newHashMap();
public static String getLanguage() {
String language = THREAD_LOCAL.get();
if (language == null) {
language = "cn";
}
return language;
}
public static void setLanguage(String language) {
THREAD_LOCAL.set(language);
}
public static void clear() {
THREAD_LOCAL.remove();
}
public static void setZoneMap(Map<String, String> map) {
ZONE_MAP.putAll(map);
}
public static String getZone(String language) {
return ZONE_MAP.get(language);
}
public static String getZone() {
return ZONE_MAP.get(getLanguage());
}
}

View File

@ -2,11 +2,12 @@ package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 字典
@ -45,6 +46,11 @@ public class Language implements Serializable {
*/
private String ico;
/**
* 时区
*/
private String zone;
/**
* 排序从大到小
*/

View File

@ -2,12 +2,13 @@ package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 工单
@ -76,6 +77,11 @@ public class Ticket implements Serializable {
*/
private LocalDateTime createTime;
/**
* 所属CQM
*/
private Integer cqm;
/**
* 紧急程度0非紧急1普通2紧急
*/

View File

@ -16,5 +16,5 @@ import com.nflg.mobilebroken.repository.entity.AdminMessage;
*/
public interface AdminMessageMapper extends BaseMapper<AdminMessage> {
void search(Integer userId, AdminMessageSearchRequest request, IPage<AdminMessageVO> page);
IPage<AdminMessageVO> search(Integer userId, AdminMessageSearchRequest request, IPage<AdminMessageVO> page);
}

View File

@ -2,6 +2,7 @@ package com.nflg.mobilebroken.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nflg.mobilebroken.common.pojo.vo.DictionaryItemTranslateVO;
import com.nflg.mobilebroken.common.pojo.vo.TicketEvaluateItemVO;
import com.nflg.mobilebroken.common.pojo.vo.TitleVO;
import com.nflg.mobilebroken.repository.entity.DictionaryItemTranslate;
@ -20,4 +21,8 @@ public interface DictionaryItemTranslateMapper extends BaseMapper<DictionaryItem
List<DictionaryItemTranslateVO> getListByDictionaryItemId(Integer id);
List<TitleVO> getTitles(String language);
String getErrorMsg(String language, String errorCode);
List<TicketEvaluateItemVO> getListByDictionaryCode(String dictionaryCode, String language);
}

View File

@ -26,7 +26,7 @@ public interface TicketMapper extends BaseMapper<Ticket> {
IPage<TicketVO> searchArea(IPage<?> page, TicketSearchRequest request, List<Integer> companyIds);
void searchFromAdmin(AdminTicketSearchRequest request, IPage<AdminTicketVO> page);
IPage<AdminTicketVO> searchFromAdmin(AdminTicketSearchRequest request, IPage<?> page);
void completeTicket(List<Integer> ids, Integer userId);
@ -34,7 +34,7 @@ public interface TicketMapper extends BaseMapper<Ticket> {
List<AdminTicketVO> searchAllFromAdmin(AdminTicketSearchRequest request);
void searchFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId, IPage<AdminTicketVO> page);
IPage<AdminTicketVO> searchFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId, IPage<?> page);
List<AdminTicketVO> searchAllFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId);
}

View File

@ -6,7 +6,6 @@ import com.nflg.mobilebroken.common.pojo.request.AdminMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO;
import com.nflg.mobilebroken.repository.entity.AdminMessage;
import javax.validation.Valid;
import java.util.List;
/**
@ -19,7 +18,11 @@ import java.util.List;
*/
public interface IAdminMessageService extends IService<AdminMessage> {
void search(Integer userId, AdminMessageSearchRequest request, IPage<AdminMessageVO> page);
IPage<AdminMessageVO> search(Integer userId, AdminMessageSearchRequest request);
void setReaded(@Valid List<Integer> ids);
void setReaded(List<Integer> ids);
void setNotRead(List<Integer> ids);
void addCQMNotify(Integer ticketId);
}

View File

@ -9,6 +9,8 @@ import com.nflg.mobilebroken.common.pojo.request.SearchAccountRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminUserVO;
import com.nflg.mobilebroken.repository.entity.AdminUser;
import java.util.List;
/**
* <p>
* 后台-用户 服务类
@ -28,4 +30,6 @@ public interface IAdminUserService extends IService<AdminUser> {
void enable(EnableAccountRequest request);
PageData<AdminUserVO> search(SearchAccountRequest request);
List<AdminUser> getCQM();
}

View File

@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.vo.AppMessageVO;
import com.nflg.mobilebroken.repository.entity.AppMessage;
import javax.validation.Valid;
import java.util.List;
/**
@ -22,5 +21,7 @@ public interface IAppMessageService extends IService<AppMessage> {
void search(Integer userId, String title, IPage<AppMessageVO> page);
void setReaded(@Valid List<Integer> ids);
void setReaded(List<Integer> ids);
void setNotRead(List<Integer> ids);
}

View File

@ -3,6 +3,7 @@ package com.nflg.mobilebroken.repository.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.dto.DictionaryItemTranslateDTO;
import com.nflg.mobilebroken.common.pojo.vo.DictionaryItemTranslateVO;
import com.nflg.mobilebroken.common.pojo.vo.TicketEvaluateVO;
import com.nflg.mobilebroken.common.pojo.vo.TitleVO;
import com.nflg.mobilebroken.repository.entity.DictionaryItemTranslate;
@ -25,4 +26,8 @@ public interface IDictionaryItemTranslateService extends IService<DictionaryItem
Integer getId(Integer dictionaryItemId, String code);
List<TitleVO> getTitles(String language);
String getErrorMsg(String language, String errorCode);
TicketEvaluateVO getTicketEvaluateSelect(String language);
}

View File

@ -23,11 +23,11 @@ import java.util.List;
*/
public interface ITicketService extends IService<Ticket> {
void add(TicketAddRequest request,Integer userId);
Integer add(TicketAddRequest request, Integer userId);
IPage<TicketVO> search(TicketSearchRequest request, UserDTO user);
void search(AdminTicketSearchRequest request, IPage<AdminTicketVO> page);
IPage<AdminTicketVO> searchPage(AdminTicketSearchRequest request);
void assignmentTicket(AssignmentTicketRequest request);
@ -35,7 +35,7 @@ public interface ITicketService extends IService<Ticket> {
void closeTicket(List<Integer> ids);
List<AdminTicketVO> search(AdminTicketSearchRequest request);
List<AdminTicketVO> exportSearch(AdminTicketSearchRequest request);
List<Ticket> getEmergencys(int days);

View File

@ -1,15 +1,24 @@
package com.nflg.mobilebroken.repository.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.MessageType;
import com.nflg.mobilebroken.common.pojo.request.AdminMessageSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO;
import com.nflg.mobilebroken.repository.entity.AdminMessage;
import com.nflg.mobilebroken.repository.entity.AdminUser;
import com.nflg.mobilebroken.repository.mapper.AdminMessageMapper;
import com.nflg.mobilebroken.repository.service.IAdminMessageService;
import com.nflg.mobilebroken.repository.service.IAdminUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
@ -22,9 +31,12 @@ import java.util.List;
@Service
public class AdminMessageServiceImpl extends ServiceImpl<AdminMessageMapper, AdminMessage> implements IAdminMessageService {
@Resource
private IAdminUserService adminUserService;
@Override
public void search(Integer userId, AdminMessageSearchRequest request, IPage<AdminMessageVO> page) {
baseMapper.search(userId, request, page);
public IPage<AdminMessageVO> search(Integer userId, AdminMessageSearchRequest request) {
return baseMapper.search(userId, request, new Page<>(request.getPage(), request.getPageSize()));
}
@Override
@ -34,4 +46,30 @@ public class AdminMessageServiceImpl extends ServiceImpl<AdminMessageMapper, Adm
.in(AdminMessage::getId, ids)
.update();
}
@Override
public void setNotRead(List<Integer> ids) {
lambdaUpdate()
.set(AdminMessage::getIsRead, false)
.in(AdminMessage::getId, ids)
.update();
}
@Transactional
@Override
public void addCQMNotify(Integer ticketId) {
List<AdminUser> cqmUsers = adminUserService.getCQM();
if (CollectionUtil.isEmpty(cqmUsers)) {
log.error("未设置CQM负责人");
} else {
List<AdminMessage> messages = cqmUsers.stream().map(c -> new AdminMessage()
.setUserId(c.getId())
.setTicketId(ticketId)
.setIsRead(false)
.setType(MessageType.WorkOrderAssignment.getState().byteValue())
.setContent("工单待分配")
.setCreateTime(LocalDateTime.now())).collect(Collectors.toList());
saveBatch(messages);
}
}
}

View File

@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.PageData;
import com.nflg.mobilebroken.common.pojo.request.AccountAddRequest;
import com.nflg.mobilebroken.common.pojo.request.AccountUpdateRequest;
@ -23,6 +24,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@ -51,6 +53,9 @@ public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser
@Resource
private IAdminUserRoleMapService adminUserRoleMapService;
@Resource
private IDictionaryItemService dictionaryItemService;
@Override
public AdminUser getUser(String userName, String password) {
String encodePassword= PASSWORDENCODER.encode(password);
@ -127,6 +132,17 @@ public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser
return pageData;
}
@Override
public List<AdminUser> getCQM() {
DictionaryItem cqm = dictionaryItemService
.lambdaQuery()
.eq(DictionaryItem::getCode, Constant.DICTIONARY_TYPE_TITLE_CQM)
.one();
return lambdaQuery()
.eq(AdminUser::getTitleId, cqm.getId())
.list();
}
private String getDepartmentName(Integer departmentId) {
TBaseDepartment department = departmentService.lambdaQuery()
.eq(TBaseDepartment::getId, departmentId)

View File

@ -7,9 +7,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.request.AreaSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AreaVO;
import com.nflg.mobilebroken.common.util.AppUserUtil;
import com.nflg.mobilebroken.repository.entity.AppArea;
import com.nflg.mobilebroken.repository.mapper.AppAreaMapper;
import com.nflg.mobilebroken.repository.service.IAppAreaService;
@ -36,11 +36,11 @@ public class AppAreaServiceImpl extends ServiceImpl<AppAreaMapper, AppArea> impl
@Override
public boolean saveOrUpdate(AppArea entity) {
if (Objects.isNull(entity.getId()) || entity.getId()<=0){
entity.setCreateBy(Constant.USER_NAME);
entity.setCreateBy(AppUserUtil.getUserName());
entity.setCreateTime(LocalDateTime.now());
return save(entity);
}else {
entity.setUpdateBy(Constant.USER_NAME);
entity.setUpdateBy(AppUserUtil.getUserName());
entity.setUpdateTime(LocalDateTime.now());
return updateById(entity);
}

View File

@ -38,4 +38,12 @@ public class AppMessageServiceImpl extends ServiceImpl<AppMessageMapper, AppMess
.in(AppMessage::getId, ids)
.update();
}
@Override
public void setNotRead(List<Integer> ids) {
lambdaUpdate()
.set(AppMessage::getIsRead, false)
.in(AppMessage::getId, ids)
.update();
}
}

View File

@ -10,11 +10,14 @@ import com.nflg.mobilebroken.common.pojo.request.DictionaryItemSearchRequest;
import com.nflg.mobilebroken.common.pojo.request.SaveDictionaryItemRequest;
import com.nflg.mobilebroken.common.pojo.request.TranslateMap;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.Dictionary;
import com.nflg.mobilebroken.repository.entity.DictionaryItem;
import com.nflg.mobilebroken.repository.entity.DictionaryItemTranslate;
import com.nflg.mobilebroken.repository.mapper.DictionaryItemMapper;
import com.nflg.mobilebroken.repository.service.IDictionaryItemService;
import com.nflg.mobilebroken.repository.service.IDictionaryItemTranslateService;
import com.nflg.mobilebroken.repository.service.IDictionaryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -39,6 +42,9 @@ public class DictionaryItemServiceImpl extends ServiceImpl<DictionaryItemMapper,
@Resource
private IDictionaryItemTranslateService dictionaryItemTranslateService;
@Resource
private IDictionaryService dictionaryService;
@Override
public void search(DictionaryItemSearchRequest request, IPage page) {
LambdaQueryWrapper<DictionaryItem> queryWrapper = new LambdaQueryWrapper<>();
@ -64,25 +70,33 @@ public class DictionaryItemServiceImpl extends ServiceImpl<DictionaryItemMapper,
@Transactional
@Override
public void save(SaveDictionaryItemRequest request) {
Dictionary dictionary = dictionaryService.getById(request.getDictionaryId());
VUtils.trueThrowBusinessError(Objects.isNull(dictionary)).throwMessage("字典不存在");
Integer id = request.getId();
VUtils.trueThrowBusinessError(lambdaQuery()
.eq(DictionaryItem::getCode, request.getCode())
.eq(DictionaryItem::getDictionaryId, request.getDictionaryId())
.ne(Objects.nonNull(id), DictionaryItem::getId, id)
.exists()).throwMessage("字典中已存在编码为" + request.getCode() + "的字典值");
if (Objects.isNull(request.getId())) {
DictionaryItem dictionary = new DictionaryItem()
DictionaryItem dictionaryItem = new DictionaryItem()
.setDictionaryId(request.getDictionaryId())
.setName(request.getName())
.setCode(request.getCode())
.setValue(request.getValue())
.setCreateBy(AdminUserUtil.getUserName())
.setCreateTime(LocalDateTime.now());
save(dictionary);
save(dictionaryItem);
id = dictionary.getId();
} else {
DictionaryItem dictionary = new DictionaryItem()
DictionaryItem dictionaryItem = new DictionaryItem()
.setId(request.getId())
.setName(request.getName())
.setCode(request.getCode())
.setValue(request.getValue())
.setUpdateBy(AdminUserUtil.getUserName())
.setUpdateTime(LocalDateTime.now());
updateById(dictionary);
updateById(dictionaryItem);
}
if (CollectionUtil.isNotEmpty(request.getLanguages())) {
dictionaryItemTranslateService.remove(new LambdaQueryWrapper<DictionaryItemTranslate>()

View File

@ -3,8 +3,10 @@ package com.nflg.mobilebroken.repository.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.dto.DictionaryItemTranslateDTO;
import com.nflg.mobilebroken.common.pojo.vo.DictionaryItemTranslateVO;
import com.nflg.mobilebroken.common.pojo.vo.TicketEvaluateVO;
import com.nflg.mobilebroken.common.pojo.vo.TitleVO;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.Dictionary;
@ -86,4 +88,19 @@ public class DictionaryItemTranslateServiceImpl extends ServiceImpl<DictionaryIt
public List<TitleVO> getTitles(String language) {
return baseMapper.getTitles(language);
}
@Override
public String getErrorMsg(String language, String errorCode) {
return baseMapper.getErrorMsg(language, errorCode);
}
@Override
public TicketEvaluateVO getTicketEvaluateSelect(String language) {
TicketEvaluateVO vo = new TicketEvaluateVO();
vo.setServiceEvaluation(baseMapper.getListByDictionaryCode(Constant.DICTIONARY_TYPE_SERVICE_EVALUATION, language));
vo.setServiceEvaluationSelect(baseMapper.getListByDictionaryCode(Constant.DICTIONARY_TYPE_SERVICE_EVALUATION_SELECT, language));
vo.setExperienceEvaluation(baseMapper.getListByDictionaryCode(Constant.DICTIONARY_TYPE_EXPERIENCE_EVALUATION, language));
vo.setExperienceEvaluationSelect(baseMapper.getListByDictionaryCode(Constant.DICTIONARY_TYPE_EXPERIENCE_EVALUATION_SELECT, language));
return vo;
}
}

View File

@ -1,5 +1,6 @@
package com.nflg.mobilebroken.repository.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -18,12 +19,16 @@ import com.nflg.mobilebroken.common.util.TicketUtl;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.Ticket;
import com.nflg.mobilebroken.repository.mapper.TicketMapper;
import com.nflg.mobilebroken.repository.service.IAdminUserService;
import com.nflg.mobilebroken.repository.service.ITicketService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* <p>
@ -36,14 +41,17 @@ import java.util.Objects;
@Service
public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> implements ITicketService {
@Resource
private IAdminUserService adminUserService;
@Override
public void add(TicketAddRequest request,Integer userId) {
public Integer add(TicketAddRequest request, Integer userId) {
Ticket lastTicket=lambdaQuery()
.ge(Ticket::getCreateTime, LocalDateTime.now().toLocalDate())
.orderByDesc(Ticket::getId)
.last("LIMIT 1")
.one();
String no=lastTicket==null? TicketUtl.getNextNo(null):TicketUtl.getNextNo(lastTicket.getNo());
String no = lastTicket == null ? TicketUtl.getNextNo(null) : TicketUtl.getNextNo(lastTicket.getNo());
Ticket ticket = new Ticket()
.setNo(no)
.setDeviceNo(request.getDeviceNo())
@ -51,32 +59,34 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
.setUseTime(request.getUseTime())
.setTitle(request.getTitle())
.setDescription(request.getDescription())
.setAttachments(StrUtil.join(",",request.getAttachments()))
.setState(TicketState.PendingProcessing.getState().byteValue())
.setAttachments(StrUtil.join(",", request.getAttachments()))
.setState(TicketState.PendingProcessing.getState())
.setUserId(userId)
.setCreateTime(LocalDateTime.now());
save(ticket);
return ticket.getId();
}
@Override
public IPage<TicketVO> search(TicketSearchRequest request, UserDTO user) {
if (request.getType()==1){
return baseMapper.searchMy(new Page<>(request.getPageNum(), request.getPageSize()), request, user.getId());
return baseMapper.searchMy(new Page<>(request.getPage(), request.getPageSize()), request, user.getId());
}else if (request.getType()==2){
return baseMapper.searchFollow(new Page<>(request.getPageNum(), request.getPageSize()), request, user.getId());
return baseMapper.searchFollow(new Page<>(request.getPage(), request.getPageSize()), request, user.getId());
}else if (request.getType()==3) {
return baseMapper.searchArea(new Page<>(request.getPageNum(), request.getPageSize()), request, user.getCompanyIds());
return baseMapper.searchArea(new Page<>(request.getPage(), request.getPageSize()), request, user.getCompanyIds());
}
return null;
}
@Override
public void search(AdminTicketSearchRequest request, IPage<AdminTicketVO> page) {
public IPage<AdminTicketVO> searchPage(AdminTicketSearchRequest request) {
if (request.getType() == 2) {
baseMapper.searchFromAdminAndFollow(request, AdminUserUtil.getUserId(), page);
} else {
baseMapper.searchFromAdmin(request, page);
return baseMapper.searchFromAdminAndFollow(request, AdminUserUtil.getUserId(), new Page<>(request.getPage(), request.getPageSize()));
} else if (request.getType() == 4) {
return baseMapper.searchFromAdmin(request, new Page<>(request.getPage(), request.getPageSize()));
}
return new Page<>(request.getPage(), request.getPageSize(), 0);
}
@Override
@ -84,10 +94,13 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
Ticket ticket = getById(request.getTickerId());
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单");
VUtils.trueThrowBusinessError(ticket.getState() != TicketState.PendingProcessing.getState().byteValue()).throwMessage("工单状态异常");
VUtils.trueThrowBusinessError(Objects.nonNull(ticket.getCqm()) && !Objects.equals(ticket.getCqm(), AdminUserUtil.getUserId()))
.throwMessage("当前工单已归属别的CQM负责人");
ticket.setUrgency(TicketUrgency.findByValue(request.getUrgency()).getState().byteValue());
ticket.setQuestion(request.getQuestion());
ticket.setRemark(request.getRemark());
ticket.setHandle(StrUtil.join(",", request.getUserIds()));
ticket.setCqm(AdminUserUtil.getUserId());
ticket.setUpdateTime(LocalDateTime.now());
updateById(ticket);
}
@ -99,18 +112,21 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
@Override
public void closeTicket(List<Integer> ids) {
//TokenUtil.getUserId()
//TODO 判断用户是否有权限关闭工单
baseMapper.closeTicket(ids);
List<Ticket> tickets = listByIds(ids);
List<Integer> tids = tickets.stream().map(Ticket::getId).filter(cqm -> Objects.equals(AdminUserUtil.getUserId(), cqm)).collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(tids)) {
baseMapper.closeTicket(ids);
}
}
@Override
public List<AdminTicketVO> search(AdminTicketSearchRequest request) {
public List<AdminTicketVO> exportSearch(AdminTicketSearchRequest request) {
if (request.getType() == 2) {
return baseMapper.searchAllFromAdminAndFollow(request, AdminUserUtil.getUserId());
} else {
} else if (request.getType() == 4) {
return baseMapper.searchAllFromAdmin(request);
}
return Collections.emptyList();
}
@Override

View File

@ -2,10 +2,10 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.mobilebroken.repository.mapper.AdminMessageMapper">
<select id="search">
SELECT t.id AS 'ticketId',t.`no` AS 'ticketNo',t.title AS 'ticketTitle',m.content,m.create_time AS 'createTime',
u.`name` AS 'ticketCreateBy',t.create_time AS 'ticketCreateTime',t.handle AS 'ticketHandleBy',
m.is_read AS 'isRead',m.type
<select id="search" resultType="com.nflg.mobilebroken.common.pojo.vo.AdminMessageVO">
SELECT t.id AS 'ticketId',t.`no` AS 'ticketNo',m.content,m.type,m.create_time AS 'createTime',
u.`name` AS 'createUserName',t.create_time AS 'ticketCreateTime',t.handle AS 'ticketHandleByIds',
m.is_read AS 'isRead'
FROM admin_message m
INNER JOIN ticket t ON m.ticket_id=t.id
INNER JOIN admin_user u ON t.user_id=u.id

View File

@ -19,4 +19,19 @@
LEFT JOIN dictionary_item_translate dit ON di.id=dit.dictionary_item_id
WHERE d.`code`=#{Constant.DICTIONARY_TYPE_TITLE} AND dit.language_code=#{language}
</select>
<select id="getErrorMsg" resultType="java.lang.String">
SELECT IFNULL(dit.`value`,di.`name`) message
FROM dictionary_item di
LEFT JOIN dictionary_item_translate dit ON dit.dictionary_item_id=di.id AND dit.language_code=#{language}
WHERE di.`code`=#{errorCode}
</select>
<select id="getListByDictionaryCode" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketEvaluateItemVO">
SELECT di.`code`,IFNULL(dit.`value`,di.`name`) AS 'desc'
FROM dictionary d
INNER JOIN dictionary_item di ON d.id=di.dictionary_id
LEFT JOIN dictionary_item_translate dit ON di.id=dit.dictionary_item_id AND dit.language_code=#{language}
WHERE d.`code`=#{dictionaryCode}
</select>
</mapper>

View File

@ -95,12 +95,16 @@
<include refid="searchWhereCondition"/>
</select>
<select id="searchFromAdmin">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,a.`name` AS 'areaName',c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime',t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime'
<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,a.`name` AS 'areaName'
,c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime',di.name AS 'warrantyStatusDesc'
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 app_area a ON u.area_id=a.id
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
LEFT JOIN dictionary_item di ON d.warranty_state=di.id
<include refid="adminSearchWhereCondition"/>
</select>
@ -123,31 +127,43 @@
</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,a.`name` AS 'areaName',c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime',t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,a.`name` AS 'areaName'
,c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime',di.name AS 'warrantyStatusDesc'
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 app_area a ON u.area_id=a.id
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
LEFT JOIN dictionary_item di ON d.warranty_state=di.id
<include refid="adminSearchWhereCondition"/>
</select>
<select id="searchFromAdminAndFollow">
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,a.`name` AS 'areaName',c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime',t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime'
<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,a.`name` AS 'areaName'
,c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime',di.name AS 'warrantyStatusDesc'
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 app_area a ON u.area_id=a.id
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId}
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
LEFT JOIN dictionary_item di ON d.warranty_state=di.id
<include refid="adminSearchWhereCondition"/>
</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,a.`name` AS 'areaName',c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime',t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime'
SELECT t.id,t.`no`,t.title,t.state,t.urgency,t.component,t.question,t.solution,a.`name` AS 'areaName'
,c.agency_company_name AS 'companyName',u.`name` AS 'createUserName',t.device_no AS 'deviceNo',t.use_time AS 'useTime'
,t.create_time AS 'createTime',t.handle,t.solve_time AS 'solveTime',di.name AS 'warrantyStatusDesc'
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 app_area a ON u.area_id=a.id
INNER JOIN ticket_follow tf ON t.id=tf.ticket_id AND tf.user_id=#{userId}
LEFT JOIN device d ON t.device_no=d.device_no AND d.data_valid_state=1
LEFT JOIN dictionary_item di ON d.warranty_state=di.id
<include refid="adminSearchWhereCondition"/>
</select>
</mapper>

View File

@ -5,11 +5,15 @@ import com.nflg.mobilebroken.common.constant.STATE;
import com.nflg.mobilebroken.common.exception.NflgException;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestControllerAdvice
@ -33,4 +37,16 @@ public class GlobalRestControllerAdvice {
log.error("数据校验失败: ", ex);
return ApiResult.error(STATE.ParamErr, "数据校验失败: " + StrUtil.join(",", ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.toList())));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResult<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
log.error("数据校验失败: ", ex);
List<String> errors = new ArrayList<>();
ex.getBindingResult().getAllErrors().forEach(error -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.add(fieldName + ":" + errorMessage);
});
return ApiResult.error(STATE.ParamErr, "数据校验失败: " + StrUtil.join(",", errors));
}
}

View File

@ -73,6 +73,7 @@ public class LoggingAspect {
StackTraceElement[] stackTraceElements = ex.getStackTrace();
logRecord.setRequestResult(false);
logDetail.setRequestErrMsg(stackTraceElements.length > 0 ? ex.getMessage() + ":" + stackTraceElements[0].toString() : "");
// logger.error("未捕获的异常",ex);
return ApiResult.error(STATE.Error,"操作出现错误"+ex.getMessage());
}
finally {

View File

@ -1,5 +1,6 @@
package com.nflg.mobilebroken.starter.handler;
import com.nflg.mobilebroken.common.util.MultilingualUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
@ -31,7 +32,7 @@ public class UTCLocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime>
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
LocalDateTime utcTime = rs.getObject(columnName, LocalDateTime.class);
// UTC 时间转换为本地时间
return utcTime != null ? utcTime.atZone(ZoneId.of("UTC"))
return utcTime != null ? utcTime.atZone(ZoneId.of(MultilingualUtil.getZone()))
.withZoneSameInstant(ZoneId.systemDefault())
.toLocalDateTime() : null;
}
@ -40,7 +41,7 @@ public class UTCLocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime>
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
LocalDateTime utcTime = rs.getObject(columnIndex, LocalDateTime.class);
// UTC 时间转换为本地时间
return utcTime != null ? utcTime.atZone(ZoneId.of("UTC"))
return utcTime != null ? utcTime.atZone(ZoneId.of(MultilingualUtil.getZone()))
.withZoneSameInstant(ZoneId.systemDefault())
.toLocalDateTime() : null;
}
@ -49,7 +50,7 @@ public class UTCLocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime>
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
LocalDateTime utcTime = cs.getObject(columnIndex, LocalDateTime.class);
// UTC 时间转换为本地时间
return utcTime != null ? utcTime.atZone(ZoneId.of("UTC"))
return utcTime != null ? utcTime.atZone(ZoneId.of(MultilingualUtil.getZone()))
.withZoneSameInstant(ZoneId.systemDefault())
.toLocalDateTime() : null;
}