fix(dispatch): 修正完成派工单的状态判断和附件保存逻辑

- 修正完成派工单时状态判断逻辑,禁止状态为0的派工单完成
- 优化附件保存逻辑,过滤已存在附件避免重复保存
- 完成派工单时仅在状态为1时更新完成时间和状态

feat(ticket): 新增获取工单案例图片接口

- 新增根据工单ID获取案例照片接口,支持标签过滤
- 支持案例图片选中状态返回,基于工单关联图片列表
- 异常情况返回空列表或错误提示

feat(solution): 支持解决措施上传案例照片标签管理

- 在解决措施保存请求中新增案例照片字段
- 保存时更新附件标签为“案例照片”
- 新建SolutionImageVO用于案例图片展示

refactor(entity): 添加FileUploadRecord标签字段支持

- FileUploadRecord实体新增标签字段,用于附件分类管理
This commit is contained in:
曹鹏飞 2025-12-08 18:07:16 +08:00
parent 5eab5d338e
commit 91c8edd53e
6 changed files with 116 additions and 14 deletions

View File

@ -33,6 +33,11 @@ public class SolutionMeasuresSaveRequest {
@NotBlank
private String reason;
/**
* 案例照片
*/
private List<Integer> imageIds;
/**
* 解决措施
*/

View File

@ -9,6 +9,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.DispatchVO;
import com.nflg.mobilebroken.common.pojo.vo.FileUploadVO;
import com.nflg.mobilebroken.common.pojo.vo.GongfuFileVO;
import com.nflg.mobilebroken.common.util.AdminUserUtil;
import com.nflg.mobilebroken.common.util.DateTimeUtil;
@ -151,7 +152,7 @@ public class DispatchController extends ControllerBase {
public ApiResult<Void> complete(@Valid @RequestBody DispatchCompleteRequest request) {
GongfuDispatch dispatch = dispatchService.getById(request.getTicketId());
VUtils.trueThrowBusinessError(Objects.isNull(dispatch)).throwMessage("派工单不存在");
VUtils.trueThrowBusinessError(!Objects.equals(dispatch.getState(), 1)).throwMessage("当前派工单状态不允许完成");
VUtils.trueThrowBusinessError(Objects.equals(dispatch.getState(), 0)).throwMessage("当前派工单状态不允许完成");
VUtils.trueThrowBusinessError(!Objects.equals(dispatch.getHandlerUserId(), AdminUserUtil.getUserId())
&& !Objects.equals(dispatch.getCreateById(), AdminUserUtil.getUserId()))
.throwMessage("无权限完成派工单");
@ -161,23 +162,37 @@ public class DispatchController extends ControllerBase {
.exists()
).throwMessage("延期申请审核中,不能完成派工单");
if (CollectionUtil.isNotEmpty(request.getAttachments())) {
fileService.saveBatch(request.getAttachments().stream().map(it -> new GongfuFile()
.setType(0)
.setSourceId(dispatch.getId())
.setNo(dispatch.getNo())
.setFileName(it.getFileName())
.setFileUrl(it.getUrl())
.setFileSuffix(FilenameUtils.getExtension(it.getFileName()))
.setFileSize(it.getFileSize())
.setCreateBy(AdminUserUtil.getUserName())
.setCreateTime(LocalDateTime.now())
).collect(Collectors.toList()));
List<Long> fids = fileService.lambdaQuery()
.eq(GongfuFile::getSourceId, request.getTicketId())
.list()
.stream()
.map(GongfuFile::getId)
.collect(Collectors.toList());
List<FileUploadVO> ups = request.getAttachments().stream()
.filter(it -> !fids.contains(it.getId().longValue()))
.collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(ups)) {
fileService.saveBatch(ups.stream()
.map(it -> new GongfuFile()
.setType(0)
.setSourceId(dispatch.getId())
.setNo(dispatch.getNo())
.setFileName(it.getFileName())
.setFileUrl(it.getUrl())
.setFileSuffix(FilenameUtils.getExtension(it.getFileName()))
.setFileSize(it.getFileSize())
.setCreateBy(AdminUserUtil.getUserName())
.setCreateTime(LocalDateTime.now())
).collect(Collectors.toList()));
}
}
dispatch.setSolution(request.getSolution());
dispatch.setSuggestion(request.getSuggestion());
dispatch.setActualEndDate(DateTimeUtil.format(request.getActualEndDate(), "yyyy-MM-dd"));
dispatch.setCompleteDate(LocalDateTime.now());
dispatch.setState(2);
if (dispatch.getState() == 1) {
dispatch.setCompleteDate(LocalDateTime.now());
dispatch.setState(2);
}
dispatchService.updateById(dispatch);
dispatchEventPublisher.publishDispatchComplate(dispatch);
return ApiResult.success();

View File

@ -16,6 +16,7 @@ import com.nflg.mobilebroken.common.pojo.request.*;
import com.nflg.mobilebroken.common.pojo.vo.*;
import com.nflg.mobilebroken.common.util.*;
import com.nflg.mobilebroken.gongfu.annotation.ApiMark;
import com.nflg.mobilebroken.gongfu.pojo.vo.SolutionImageVO;
import com.nflg.mobilebroken.gongfu.publisher.TicketEventPublisher;
import com.nflg.mobilebroken.gongfu.service.ShengWangService;
import com.nflg.mobilebroken.gongfu.service.SsePushService;
@ -1448,4 +1449,41 @@ public class TicketController extends ControllerBase {
public ApiResult<List<AdminUser>> getHandlerForSelect() {
return ApiResult.success(adminUserService.lambdaQuery().eq(AdminUser::isGongFuHandler, true).list());
}
/**
* 获取工单案例图片
* @param id 工单ID
* @return 工单案例图片
*/
@GetMapping("getSolutionImages")
public ApiResult<List<SolutionImageVO>> getSolutionImages(@RequestParam Long id) {
List<FileUploadRecord> images = fileUploadRecordService.lambdaQuery()
.eq(FileUploadRecord::getSource, (byte) 0)
.eq(FileUploadRecord::getSourceId, id)
.eq(FileUploadRecord::getTag, "案例照片")
.list();
if (CollectionUtil.isNotEmpty(images)) {
return ApiResult.success(images.stream()
.map(image -> Convert.convert(SolutionImageVO.class, image))
.collect(Collectors.toList())
);
}
GongfuTicket ticket = ticketService.getById(id);
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在");
images = fileUploadRecordService.lambdaQuery()
.eq(FileUploadRecord::getSource, (byte) 0)
.eq(FileUploadRecord::getSourceId, id)
.list();
if (CollectionUtil.isEmpty(images)) {
return ApiResult.success(Collections.emptyList());
}
int[] mids = StrUtil.splitToInt(ticket.getImages(), ",");
return ApiResult.success(
images.stream().map(image -> {
SolutionImageVO vo = Convert.convert(SolutionImageVO.class, image);
vo.setSelected(Arrays.stream(mids).anyMatch(mid -> mid == image.getId()));
return vo;
}).collect(Collectors.toList())
);
}
}

View File

@ -0,0 +1,29 @@
package com.nflg.mobilebroken.gongfu.pojo.vo;
import lombok.Data;
@Data
public class SolutionImageVO {
private Integer id;
/**
* 文件名称
*/
private String fileName;
/**
* 文件类型
*/
private String fileType;
/**
* 访问地址
*/
private String url;
/**
* 是否选中
*/
private boolean selected = true;
}

View File

@ -61,6 +61,11 @@ public class FileUploadRecord implements Serializable {
@TableField("`from`")
private String from;
/**
* 标签
*/
private String tag;
/**
* 上传人
*/

View File

@ -53,6 +53,9 @@ public class TicketSolutionServiceImpl extends ServiceImpl<TicketSolutionMapper,
@Resource
private IGongfuDeviceTypeService deviceTypeService;
@Resource
private IFileUploadRecordService fileUploadRecordService;
@Override
public SolutionMeasuresVO getSolutionMeasures(Long ticketId) {
TicketDTO ticket = ticketService.getDto(ticketId);
@ -268,6 +271,13 @@ public class TicketSolutionServiceImpl extends ServiceImpl<TicketSolutionMapper,
ticketSolutionAuditService.lambdaUpdate()
.eq(TicketSolutionAudit::getTicketId, request.getTicketId())
.remove();
if (CollectionUtil.isNotEmpty(request.getImageIds())) {
fileUploadRecordService.lambdaUpdate()
.set(FileUploadRecord::getTag, "案例照片")
.eq(FileUploadRecord::getSource, (byte) 0)
.eq(FileUploadRecord::getSourceId, request.getTicketId())
.update();
}
return ticket;
}
}