perf: 添加功能

This commit is contained in:
曹鹏飞 2025-02-05 17:24:07 +08:00
parent b3ec09148f
commit 5f9543d097
21 changed files with 185 additions and 31 deletions

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

@ -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.LanguageUtil;
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 = LanguageUtil.getLanguage();
return ApiResult.success(dictionaryItemTranslateService.getTicketEvaluateSelect(language));
}
/**
* 添加工单评价
*

View File

@ -2,6 +2,14 @@ package com.nflg.mobilebroken.common.constant;
public class Constant {
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";

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

@ -10,7 +10,7 @@ import java.time.LocalDateTime;
@Data
public class TicketSearchRequest extends PageRequest {
//搜索类型1: 我的工单,2: 我的关注,3: 区域工单
//搜索类型1: 我的工单,2: 我的关注,3: 区域工单,4: 全部工单
@NotNull(message = "搜索类型不能为空")
private Integer type;

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

@ -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;
@ -22,4 +23,6 @@ public interface DictionaryItemTranslateMapper extends BaseMapper<DictionaryItem
List<TitleVO> getTitles(String language);
String getErrorMsg(String language, String errorCode);
List<TicketEvaluateItemVO> getListByDictionaryCode(String dictionaryCode, String language);
}

View File

@ -23,4 +23,6 @@ public interface IAdminMessageService extends IService<AdminMessage> {
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>
* 后台-用户 服务类
@ -29,5 +31,5 @@ public interface IAdminUserService extends IService<AdminUser> {
PageData<AdminUserVO> search(SearchAccountRequest request);
AdminUser getCQM();
List<AdminUser> getCQM();
}

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;
@ -27,4 +28,6 @@ public interface IDictionaryItemTranslateService extends IService<DictionaryItem
List<TitleVO> getTitles(String language);
String getErrorMsg(String language, String errorCode);
TicketEvaluateVO getTicketEvaluateSelect(String language);
}

View File

@ -23,7 +23,7 @@ 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);

View File

@ -1,16 +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>
@ -23,6 +31,9 @@ import java.util.List;
@Service
public class AdminMessageServiceImpl extends ServiceImpl<AdminMessageMapper, AdminMessage> implements IAdminMessageService {
@Resource
private IAdminUserService adminUserService;
@Override
public IPage<AdminMessageVO> search(Integer userId, AdminMessageSearchRequest request) {
return baseMapper.search(userId, request, new Page<>(request.getPage(), request.getPageSize()));
@ -43,4 +54,22 @@ public class AdminMessageServiceImpl extends ServiceImpl<AdminMessageMapper, Adm
.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

@ -24,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;
@ -132,14 +133,14 @@ public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser
}
@Override
public AdminUser getCQM() {
public List<AdminUser> getCQM() {
DictionaryItem cqm = dictionaryItemService
.lambdaQuery()
.eq(DictionaryItem::getCode, Constant.DICTIONARY_TYPE_TITLE_CQM)
.one();
return lambdaQuery()
.eq(AdminUser::getTitleId, cqm.getId())
.one();
.list();
}
private String getDepartmentName(Integer departmentId) {

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;
@ -91,4 +93,14 @@ public class DictionaryItemTranslateServiceImpl extends ServiceImpl<DictionaryIt
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,10 +1,10 @@
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;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.constant.TicketState;
import com.nflg.mobilebroken.common.constant.TicketUrgency;
import com.nflg.mobilebroken.common.pojo.dto.UserDTO;
@ -15,21 +15,20 @@ import com.nflg.mobilebroken.common.pojo.request.TicketSearchRequest;
import com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO;
import com.nflg.mobilebroken.common.pojo.vo.TicketVO;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.LanguageUtil;
import com.nflg.mobilebroken.common.util.TicketUtl;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.AdminUser;
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.IDictionaryItemTranslateService;
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>
@ -45,14 +44,8 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
@Resource
private IAdminUserService adminUserService;
@Resource
private IDictionaryItemTranslateService dictionaryItemTranslateService;
@Override
public void add(TicketAddRequest request,Integer userId) {
AdminUser cqmUser = adminUserService.getCQM();
VUtils.trueThrowBusinessError(Objects.isNull(cqmUser))
.throwMessage(dictionaryItemTranslateService.getErrorMsg(LanguageUtil.getLanguage(), Constant.DICTIONARY_TYPE_SYSTEMERROR_CQMNOTCONFIG));
public Integer add(TicketAddRequest request, Integer userId) {
Ticket lastTicket=lambdaQuery()
.ge(Ticket::getCreateTime, LocalDateTime.now().toLocalDate())
.orderByDesc(Ticket::getId)
@ -69,9 +62,9 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
.setAttachments(StrUtil.join(",", request.getAttachments()))
.setState(TicketState.PendingProcessing.getState())
.setUserId(userId)
.setCreateTime(LocalDateTime.now())
.setCqm(cqmUser.getId());
.setCreateTime(LocalDateTime.now());
save(ticket);
return ticket.getId();
}
@Override
@ -90,9 +83,10 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
public IPage<AdminTicketVO> searchPage(AdminTicketSearchRequest request) {
if (request.getType() == 2) {
return baseMapper.searchFromAdminAndFollow(request, AdminUserUtil.getUserId(), new Page<>(request.getPage(), request.getPageSize()));
} else {
} else if (request.getType() == 4) {
return baseMapper.searchFromAdmin(request, new Page<>(request.getPage(), request.getPageSize()));
}
return new Page<>(request.getPage(), request.getPageSize(), 0);
}
@Override
@ -100,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);
}
@ -115,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> 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

@ -26,4 +26,12 @@
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

@ -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));
}
}