From 69e9ea6b9f3cb07496ba7d400f675b8682fa1378 Mon Sep 17 00:00:00 2001 From: dk <1260500659@qq.com> Date: Thu, 25 Jun 2026 21:17:57 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=97=A5=E5=BF=97=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A5=E5=BF=97=E7=AE=A1=E7=90=86=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98=E3=80=82=20fix(=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=BB=BB=E5=8A=A1):=20=E4=BB=BB=E5=8A=A1=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=90=8E=E9=9C=80=E8=A6=81=E4=BE=9D=E7=84=B6=E8=83=BD?= =?UTF-8?q?=E5=A4=9F=E4=BF=AE=E6=94=B9=E5=B7=A5=E4=BD=9C=E6=97=A5=E5=BF=97?= =?UTF-8?q?=EF=BC=8C=E4=BD=86=E6=98=AF=E5=8F=AA=E8=83=BD=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E5=86=85=E5=AE=B9=E5=92=8C=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E9=99=84=E4=BB=B6=EF=BC=9B=E4=BB=BB=E5=8A=A1=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=90=8E=EF=BC=8C=E5=8D=8F=E5=8A=9E=E4=BA=BA=E7=9A=84=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E5=BF=97=E4=B8=8D=E5=BA=94=E8=AF=A5=E8=83=BD?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E3=80=81=E6=89=80=E6=9C=89=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E9=87=8C=E7=9A=84=E6=88=90=E5=91=98=E4=B8=8D=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=B7=A5=E4=BD=9C=E6=97=A5=E5=BF=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project/enums/ErrorCodeConstants.java | 2 + .../task/worklog/TaskWorklogServiceImpl.java | 28 ++++++++----- .../admin/logger/OperateLogController.java | 42 ++++++++++++++----- .../vo/operatelog/OperateLogPageReqVO.java | 11 +++-- .../vo/operatelog/OperateLogRespVO.java | 17 ++++---- .../dal/mysql/logger/OperateLogMapper.java | 1 + 6 files changed, 67 insertions(+), 34 deletions(-) diff --git a/rdms-project/rdms-project-api/src/main/java/com/njcn/rdms/module/project/enums/ErrorCodeConstants.java b/rdms-project/rdms-project-api/src/main/java/com/njcn/rdms/module/project/enums/ErrorCodeConstants.java index 6fa4fd8..99ba0ed 100644 --- a/rdms-project/rdms-project-api/src/main/java/com/njcn/rdms/module/project/enums/ErrorCodeConstants.java +++ b/rdms-project/rdms-project-api/src/main/java/com/njcn/rdms/module/project/enums/ErrorCodeConstants.java @@ -184,8 +184,10 @@ public interface ErrorCodeConstants { ErrorCode PROJECT_TASK_WORKLOG_DELETE_FORBIDDEN = new ErrorCode(1_008_006_006, "仅记录填报人或任务负责人可删除该工时记录"); ErrorCode PROJECT_TASK_WORKLOG_DATE_RANGE_INVALID = new ErrorCode(1_008_006_007, "段起始日期不能晚于段结束日期"); ErrorCode PROJECT_TASK_WORKLOG_DATE_OVERLAP = new ErrorCode(1_008_006_008, "日期范围与该任务下您已有的工时记录重叠"); + ErrorCode PROJECT_TASK_WORKLOG_DELETE_NOT_ALLOWED_BY_TASK_STATUS = new ErrorCode(1_008_006_009, "当前任务状态不允许删除工作日志"); ErrorCode PROJECT_TASK_WORKLOG_PROGRESS_NOT_MONOTONIC = new ErrorCode(1_008_006_010, "工时进度与日期顺序不一致:早段进度不得高于晚段、晚段进度不得低于早段"); ErrorCode PROJECT_TASK_WORKLOG_DIFFICULTY_INVALID = new ErrorCode(1_008_006_011, "完成难度不在字典范围内"); + ErrorCode PROJECT_TASK_WORKLOG_CREATE_NOT_ALLOWED_BY_TASK_STATUS = new ErrorCode(1_008_006_012, "当前任务状态不允许新增工作日志"); // ========== 任务 / 工时附件 1_008_010_xxx(原 1_008_007 与下方项目需求段撞号,迁至独立号段;新增错误码域请从 1_008_011 起) ========== ErrorCode PROJECT_TASK_ATTACHMENT_TOO_MANY = new ErrorCode(1_008_010_001, "附件数量不能超过 {} 个"); diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/project/task/worklog/TaskWorklogServiceImpl.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/project/task/worklog/TaskWorklogServiceImpl.java index 108ccbe..ed120f7 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/project/task/worklog/TaskWorklogServiceImpl.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/project/task/worklog/TaskWorklogServiceImpl.java @@ -105,6 +105,7 @@ public class TaskWorklogServiceImpl implements TaskWorklogService { permission = ProjectTaskConstants.PERMISSION_WORKLOG) public Long createWorklog(Long projectId, Long executionId, Long taskId, TaskWorklogSaveReqVO reqVO) { ProjectTaskDO task = validateEditableContext(projectId, executionId, taskId); + validateCreateAllowed(task); validateLeafTask(taskId); Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); validateFileWorklogPermission(taskId, task.getOwnerId(), loginUserId); @@ -177,6 +178,7 @@ public class TaskWorklogServiceImpl implements TaskWorklogService { permission = ProjectTaskConstants.PERMISSION_WORKLOG) public void deleteWorklog(Long projectId, Long executionId, Long taskId, Long worklogId) { ProjectTaskDO task = validateEditableContext(projectId, executionId, taskId); + validateDeleteAllowed(task); TaskWorklogDO worklog = loadWorklog(worklogId, taskId); Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); boolean isFiler = Objects.equals(worklog.getUserId(), loginUserId); @@ -240,24 +242,30 @@ public class TaskWorklogServiceImpl implements TaskWorklogService { ProjectExecutionDO execution = validateExecutionExists(projectId, executionId); validateAllowEdit(ProjectExecutionConstants.OBJECT_TYPE, execution.getStatusCode()); ProjectTaskDO task = validateTaskExists(projectId, executionId, taskId); - // 任务层放宽:completed 状态下非 owner(即协办人)允许继续维护自己的工时(§4.2.4 矩阵)。 - // 其他状态(pending / active / paused / cancelled)仍按 allow_edit 判定,owner 在 completed 下被拦截, - // 避免与"完成时硬置进度 100%"冲突。 - if (!isCompletedAssigneeWorklogContext(task)) { + // 工作日志维护在任务 completed 状态下统一放行;新增/删除是否允许由各自接口单独判定。 + if (!isCompletedWorklogContext(task)) { validateAllowEdit(ProjectTaskConstants.OBJECT_TYPE, task.getStatusCode()); } return task; } /** - * 是否处于"任务已完成、协办人维护工时"的放行场景。 + * 是否处于“任务已完成”的工作日志维护场景。 */ - private boolean isCompletedAssigneeWorklogContext(ProjectTaskDO task) { - if (!"completed".equals(task.getStatusCode())) { - return false; + private boolean isCompletedWorklogContext(ProjectTaskDO task) { + return "completed".equals(task.getStatusCode()); + } + + private void validateCreateAllowed(ProjectTaskDO task) { + if (isCompletedWorklogContext(task)) { + throw exception(ErrorCodeConstants.PROJECT_TASK_WORKLOG_CREATE_NOT_ALLOWED_BY_TASK_STATUS); + } + } + + private void validateDeleteAllowed(ProjectTaskDO task) { + if (isCompletedWorklogContext(task)) { + throw exception(ErrorCodeConstants.PROJECT_TASK_WORKLOG_DELETE_NOT_ALLOWED_BY_TASK_STATUS); } - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - return loginUserId != null && !Objects.equals(loginUserId, task.getOwnerId()); } private void validateExecutionAndTaskExists(Long projectId, Long executionId, Long taskId) { diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/OperateLogController.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/OperateLogController.java index e54fb5b..071bdc3 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/OperateLogController.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/OperateLogController.java @@ -4,14 +4,15 @@ import com.njcn.rdms.framework.apilog.core.annotation.ApiAccessLog; import com.njcn.rdms.framework.common.pojo.CommonResult; import com.njcn.rdms.framework.common.pojo.PageParam; import com.njcn.rdms.framework.common.pojo.PageResult; +import com.njcn.rdms.framework.common.util.collection.CollectionUtils; import com.njcn.rdms.framework.common.util.object.BeanUtils; import com.njcn.rdms.framework.excel.core.util.ExcelUtils; -import com.njcn.rdms.framework.translate.core.TranslateUtils; import com.njcn.rdms.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import com.njcn.rdms.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import com.njcn.rdms.module.system.dal.dataobject.logger.OperateLogDO; +import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO; import com.njcn.rdms.module.system.service.logger.OperateLogService; -import com.fhs.core.trans.anno.TransMethodResult; +import com.njcn.rdms.module.system.service.user.AdminUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -26,7 +27,9 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; +import java.util.Collections; import java.util.List; +import java.util.Map; import static com.njcn.rdms.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static com.njcn.rdms.framework.common.pojo.CommonResult.success; @@ -40,34 +43,53 @@ public class OperateLogController { @Resource private OperateLogService operateLogService; + @Resource + private AdminUserService adminUserService; + @GetMapping("/get") @Operation(summary = "查看操作日志") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:operate-log:query')") public CommonResult getOperateLog(@RequestParam("id") Long id) { - OperateLogDO operateLog = operateLogService.getOperateLog(id); - return success(BeanUtils.toBean(operateLog, OperateLogRespVO.class)); + OperateLogRespVO respVO = BeanUtils.toBean(operateLogService.getOperateLog(id), OperateLogRespVO.class); + fillUserNames(Collections.singletonList(respVO)); + return success(respVO); } @GetMapping("/page") @Operation(summary = "查看操作日志分页列表") @PreAuthorize("@ss.hasPermission('system:operate-log:query')") - @TransMethodResult public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) { PageResult pageResult = operateLogService.getOperateLogPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, OperateLogRespVO.class)); + PageResult respPageResult = BeanUtils.toBean(pageResult, OperateLogRespVO.class); + fillUserNames(respPageResult.getList()); + return success(respPageResult); } @Operation(summary = "导出操作日志") @GetMapping("/export-excel") @PreAuthorize("@ss.hasPermission('system:operate-log:export')") - @TransMethodResult @ApiAccessLog(operateType = EXPORT) public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException { exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = operateLogService.getOperateLogPage(exportReqVO).getList(); - ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class, - TranslateUtils.translate(BeanUtils.toBean(list, OperateLogRespVO.class))); + List respVOList = BeanUtils.toBean( + operateLogService.getOperateLogPage(exportReqVO).getList(), OperateLogRespVO.class); + fillUserNames(respVOList); + ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class, respVOList); + } + + private void fillUserNames(List respVOList) { + if (respVOList == null || respVOList.isEmpty()) { + return; + } + Map userMap = adminUserService.getUserMap( + CollectionUtils.convertSet(respVOList, OperateLogRespVO::getUserId)); + respVOList.forEach(respVO -> { + AdminUserDO user = userMap.get(respVO.getUserId()); + if (user != null) { + respVO.setUserName(user.getNickname()); + } + }); } } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java index 2063680..8d92d3d 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java @@ -13,21 +13,24 @@ import static com.njcn.rdms.framework.common.util.date.DateUtils.FORMAT_YEAR_MON @Data public class OperateLogPageReqVO extends PageParam { - @Schema(description = "用户编号", example = "灿能") + @Schema(description = "用户编号", example = "1") private Long userId; @Schema(description = "操作模块业务编号", example = "1") private Long bizId; - @Schema(description = "操作模块,模拟匹配", example = "订单") + @Schema(description = "操作模块,模糊匹配", example = "订单") private String type; - @Schema(description = "操作名,模拟匹配", example = "创建订单") + @Schema(description = "操作名称,模糊匹配", example = "创建订单") private String subType; - @Schema(description = "操作明细,模拟匹配", example = "修改编号为 1 的用户信息") + @Schema(description = "操作明细,模糊匹配", example = "修改编号为 1 的用户信息") private String action; + @Schema(description = "请求方式", example = "GET") + private String requestMethod; + @Schema(description = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java index 8cb6f0c..6d03c92 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java @@ -1,13 +1,10 @@ package com.njcn.rdms.module.system.controller.admin.logger.vo.operatelog; -import com.njcn.rdms.framework.excel.core.annotations.DictFormat; -import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO; import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; -import com.njcn.rdms.module.system.enums.DictTypeConstants; -import com.fhs.core.trans.anno.Trans; -import com.fhs.core.trans.constant.TransType; import com.fhs.core.trans.vo.VO; +import com.njcn.rdms.framework.excel.core.annotations.DictFormat; +import com.njcn.rdms.module.system.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.Data; @@ -27,8 +24,8 @@ public class OperateLogRespVO implements VO { private String traceId; @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userName") private Long userId; + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "awen") @ExcelProperty("操作人") private String userName; @@ -42,18 +39,18 @@ public class OperateLogRespVO implements VO { @ExcelProperty("操作模块类型") private String type; - @Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单") - @ExcelProperty("操作名") + @Schema(description = "操作名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单") + @ExcelProperty("操作名称") private String subType; @Schema(description = "操作模块业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("操作模块业务编号") private Long bizId; - @Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从灿能改成源码。") + @Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋艿改成源码。") private String action; - @Schema(description = "拓展字段", example = "{'orderId': 1}") + @Schema(description = "扩展字段", example = "{'orderId': 1}") private String extra; @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/logger/OperateLogMapper.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/logger/OperateLogMapper.java index 9b8db50..fee23e3 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/logger/OperateLogMapper.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/logger/OperateLogMapper.java @@ -18,6 +18,7 @@ public interface OperateLogMapper extends BaseMapperX { .likeIfPresent(OperateLogDO::getType, pageReqDTO.getType()) .likeIfPresent(OperateLogDO::getSubType, pageReqDTO.getSubType()) .likeIfPresent(OperateLogDO::getAction, pageReqDTO.getAction()) + .eqIfPresent(OperateLogDO::getRequestMethod, pageReqDTO.getRequestMethod()) .betweenIfPresent(OperateLogDO::getCreateTime, pageReqDTO.getCreateTime()) .orderByDesc(OperateLogDO::getId)); }