From d882806df6f31dfe67aaf932bb058b024e1eab86 Mon Sep 17 00:00:00 2001 From: aikai Date: Tue, 24 Jun 2025 17:58:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(bpm):=20=E6=96=B0=E5=A2=9E=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E5=88=86=E9=85=8D=E8=A7=84=E5=88=99=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E5=B7=A5=E5=8D=95=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增工单分配规则相关实体、控制器、服务和映射 - 实现工单分配规则的创建、更新、删除和查询功能 - 优化工单分页查询接口,支持按责任人和部门筛选 - 新增工单跟踪记录分页查询功能 --- .../definition/BpmTaskRuleScriptEnum.java | 3 +- .../BpmOAWorkOrderAssignRuleController.java | 112 +++++++++++ .../admin/oa/BpmOAWorkOrderController.java | 10 +- .../vo/workorder/BpmOAWorkOrderPageReqVO.java | 5 +- .../workorder/BpmOAWorkOrderTrackReqDTO.java | 21 +++ .../BpmOAWorkOrderAssignRulePageReqVO.java | 33 ++++ .../BpmOAWorkOrderAssignRuleRespVO.java | 42 +++++ .../BpmOAWorkOrderAssignRuleSaveReqVO.java | 31 +++ .../oa/BpmOAWorkOrderAssignRuleDO.java | 14 +- .../oa/BpmOAWorkOrderAssignRuleMapper.java | 26 ++- .../dal/mysql/oa/BpmOAWorkOrderMapper.java | 17 +- .../mysql/oa/BpmOAWorkOrderTrackMapper.java | 8 +- .../impl/BpmOaWorkOrderLeaderScript.java | 61 ++++++ .../oa/BpmOAWorkOrderAssignRuleService.java | 82 ++++++++ .../BpmOAWorkOrderAssignRuleServiceImpl.java | 176 ++++++++++++++++++ .../bpm/service/oa/BpmOAWorkOrderService.java | 23 ++- .../service/oa/BpmOAWorkOrderServiceImpl.java | 70 +++++-- .../mapper/oa/BpmOAWorkOrderMapper.xml | 43 ++--- .../mapper/oa/BpmOAWorkOrderTrackMapper.xml | 7 + .../infra/config/MinioConfigProperties.java | 37 ++++ .../app/file/AppFileController.java | 45 +++++ .../app/file/vo/MinioMultiUploadReqVO.java | 22 +++ .../app/file/vo/MinioUploadReqVO.java | 25 +++ .../app/file/vo/MinioUploadRespVO.java | 41 ++++ .../infra/service/minio/MinioService.java | 158 ++++++++++++++++ .../src/main/resources/application-local.yaml | 15 ++ 26 files changed, 1043 insertions(+), 84 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderAssignRuleController.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderTrackReqDTO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRulePageReqVO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleRespVO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleSaveReqVO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmOaWorkOrderLeaderScript.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleService.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleServiceImpl.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderTrackMapper.xml create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/config/MinioConfigProperties.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioMultiUploadReqVO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadReqVO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadRespVO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/minio/MinioService.java diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java index 5d20d11a..da3c9c20 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java @@ -25,7 +25,8 @@ public enum BpmTaskRuleScriptEnum { LEADER_X8(27L, "调薪部门领导"), LEADER_X9(28L, "调薪人上级领导"), LEADER_X10(29L, "所选工厂的领导"), - LEADER_X11(30L, "审批人的上级领导"); + LEADER_X11(30L, "审批人的上级领导"), + LEADER_X31(31L, "工单负责人"); /** * 脚本编号 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderAssignRuleController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderAssignRuleController.java new file mode 100644 index 00000000..b62f50e5 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderAssignRuleController.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRulePageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleSaveReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderAssignRuleDO; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAWorkOrderAssignRuleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +/** + * 管理后台 - BPM OA 工单分配规则 + * + * @author 系统 + */ +@Tag(name = "管理后台 - BPM OA 工单分配规则") +@RestController +@RequestMapping("/bpm/work-order-assign-rule") +@Validated +public class BpmOAWorkOrderAssignRuleController { + + @Resource + private BpmOAWorkOrderAssignRuleService workOrderAssignRuleService; + + @PostMapping("/create") + @Operation(summary = "创建工单分配规则") + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:create')") + @OperateLog(type = CREATE) + public CommonResult createWorkOrderAssignRule(@Valid @RequestBody BpmOAWorkOrderAssignRuleSaveReqVO createReqVO) { + return success(workOrderAssignRuleService.createWorkOrderAssignRule(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工单分配规则") + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:update')") + @OperateLog(type = UPDATE) + public CommonResult updateWorkOrderAssignRule(@Valid @RequestBody BpmOAWorkOrderAssignRuleSaveReqVO updateReqVO) { + workOrderAssignRuleService.updateWorkOrderAssignRule(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工单分配规则") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:delete')") + @OperateLog(type = DELETE) + public CommonResult deleteWorkOrderAssignRule(@RequestParam("id") Long id) { + workOrderAssignRuleService.deleteWorkOrderAssignRule(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工单分配规则") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:query')") + public CommonResult getWorkOrderAssignRule(@RequestParam("id") Long id) { + BpmOAWorkOrderAssignRuleDO workOrderAssignRule = workOrderAssignRuleService.getWorkOrderAssignRule(id); + return success(workOrderAssignRule); + } + + @GetMapping("/page") + @Operation(summary = "获得工单分配规则分页") + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:query')") + public CommonResult> getWorkOrderAssignRulePage(@Valid BpmOAWorkOrderAssignRulePageReqVO pageReqVO) { + PageResult pageResult = workOrderAssignRuleService.getWorkOrderAssignRulePage(pageReqVO); + return success(pageResult); + } + + @GetMapping("/list") + @Operation(summary = "获得工单分配规则列表") + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:query')") + public CommonResult> getWorkOrderAssignRuleList(@Valid BpmOAWorkOrderAssignRulePageReqVO exportReqVO) { + List list = workOrderAssignRuleService.getWorkOrderAssignRuleList(exportReqVO); + return success(list); + } + + @GetMapping("/list-by-type") + @Operation(summary = "根据工单类型获取有效的分配规则") + @Parameter(name = "workOrderType", description = "工单类型", required = true) + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:query')") + public CommonResult> getEnabledRulesByType(@RequestParam("workOrderType") String workOrderType) { + List list = workOrderAssignRuleService.getEnabledRulesByType(workOrderType); + return success(list); + } + + @PutMapping("/update-status") + @Operation(summary = "批量更新规则状态") + @PreAuthorize("@ss.hasPermission('bpm:work-order-assign-rule:update')") + @OperateLog(type = UPDATE) + public CommonResult updateRuleStatus(@RequestParam("ids") Collection ids, + @RequestParam("status") Integer status) { + workOrderAssignRuleService.updateRuleStatus(ids, status); + return success(true); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderController.java index 6c5ef61f..3f4dc19c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAWorkOrderController.java @@ -28,7 +28,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti */ @Tag(name = "管理后台 - BPM OA 工单") @RestController -@RequestMapping("/admin-api/bpm/oa/work-order") +@RequestMapping("/bpm/oa/work-order") @Validated @Slf4j public class BpmOAWorkOrderController { @@ -80,6 +80,12 @@ public class BpmOAWorkOrderController { return success(true); } + @GetMapping("/track-page") + @Operation(summary = "获得工单跟踪记录分页") + public CommonResult> getTrackPage(@Valid BpmOAWorkOrderTrackReqDTO dto) { + return success(workOrderService.getTrackPage(dto)); + } + @PutMapping("/update") @Operation(summary = "修改工单") @PreAuthorize("@ss.hasPermission('bpm:oa-work-order:update')") @@ -95,4 +101,4 @@ public class BpmOAWorkOrderController { return success(workOrderService.getMyAssignedWorkOrderCount(getLoginUserId())); } -} \ No newline at end of file +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderPageReqVO.java index 5d0246e5..b699fc3f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderPageReqVO.java @@ -32,8 +32,11 @@ public class BpmOAWorkOrderPageReqVO extends PageParam { @Schema(description = "发起人ID", example = "1") private Long fromUserId; + @Schema(description = "当前用户id", example = "1") + private Long loginUserId; + @Schema(description = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderTrackReqDTO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderTrackReqDTO.java new file mode 100644 index 00000000..d379d06e --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorder/BpmOAWorkOrderTrackReqDTO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorder; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Data +public class BpmOAWorkOrderTrackReqDTO extends PageParam { + + @Schema(description = "工单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工单ID不能为空") + private Long workOrderId; + + @Schema(description = "操作类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "PROCESS") + @NotEmpty(message = "操作类型不能为空") + private String operationType; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRulePageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRulePageReqVO.java new file mode 100644 index 00000000..63e4321d --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRulePageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - BPM OA 工单分配规则分页查询 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BpmOAWorkOrderAssignRulePageReqVO extends PageParam { + + @Schema(description = "工单类型", example = "it_support") + private String workOrderType; + + @Schema(description = "责任部门ID", example = "100") + private Long deptId; + + @Schema(description = "责任人ID", example = "1") + private Long assigneeUserId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleRespVO.java new file mode 100644 index 00000000..9845dd63 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - BPM OA 工单分配规则 Response VO") +@Data +public class BpmOAWorkOrderAssignRuleRespVO { + + @Schema(description = "规则ID,主键", example = "1") + private Long id; + + @Schema(description = "工单类型", example = "it_support") + private String workOrderType; + + @Schema(description = "工单类型名称", example = "IT支持") + private String workOrderTypeName; + + @Schema(description = "责任部门ID", example = "100") + private Long deptId; + + @Schema(description = "责任部门名称", example = "运维部") + private String deptName; + + @Schema(description = "责任人ID", example = "1") + private Long assigneeUserId; + + @Schema(description = "责任人姓名", example = "张三") + private String assigneeUserName; + + @Schema(description = "规则描述", example = "IT支持类工单自动分配给运维部门张三处理") + private String description; + + @Schema(description = "创建时间", example = "2024-01-01 10:00:00") + private LocalDateTime createTime; + + @Schema(description = "更新时间", example = "2024-01-01 10:00:00") + private LocalDateTime updateTime; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleSaveReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleSaveReqVO.java new file mode 100644 index 00000000..3de42538 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/workorderassignrule/BpmOAWorkOrderAssignRuleSaveReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - BPM OA 工单分配规则新增/修改 Request VO") +@Data +public class BpmOAWorkOrderAssignRuleSaveReqVO { + + @Schema(description = "规则ID,主键", example = "1") + private Long id; + + @Schema(description = "工单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "it_support") + @NotEmpty(message = "工单类型不能为空") + private String workOrderType; + + @Schema(description = "责任部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "责任部门ID不能为空") + private Long deptId; + + @Schema(description = "责任人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "责任人ID不能为空") + private Long assigneeUserId; + + @Schema(description = "规则描述", example = "IT支持类工单自动分配给运维部门张三处理") + private String description; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAWorkOrderAssignRuleDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAWorkOrderAssignRuleDO.java index 031648e5..da1bc142 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAWorkOrderAssignRuleDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAWorkOrderAssignRuleDO.java @@ -41,21 +41,9 @@ public class BpmOAWorkOrderAssignRuleDO extends BaseDO { */ private Long assigneeUserId; - /** - * 规则优先级 - * 数值越小优先级越高 - */ - private Integer priority; - - /** - * 规则状态 - * 1-启用,0-禁用 - */ - private Integer status; - /** * 规则描述 */ private String description; -} \ No newline at end of file +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderAssignRuleMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderAssignRuleMapper.java index 9714fe9e..5cb3dca1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderAssignRuleMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderAssignRuleMapper.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.dal.mysql.oa; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRulePageReqVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderAssignRuleDO; import org.apache.ibatis.annotations.Mapper; @@ -21,9 +22,7 @@ public interface BpmOAWorkOrderAssignRuleMapper extends BaseMapperX selectRulesByType(String workOrderType) { return selectList(new LambdaQueryWrapperX() - .eq(BpmOAWorkOrderAssignRuleDO::getWorkOrderType, workOrderType) - .eq(BpmOAWorkOrderAssignRuleDO::getStatus, 1) - .orderByAsc(BpmOAWorkOrderAssignRuleDO::getPriority)); + .eq(BpmOAWorkOrderAssignRuleDO::getWorkOrderType, workOrderType)); } /** @@ -31,9 +30,7 @@ public interface BpmOAWorkOrderAssignRuleMapper extends BaseMapperX selectRulesByDept(Long deptId) { return selectList(new LambdaQueryWrapperX() - .eq(BpmOAWorkOrderAssignRuleDO::getDeptId, deptId) - .eq(BpmOAWorkOrderAssignRuleDO::getStatus, 1) - .orderByAsc(BpmOAWorkOrderAssignRuleDO::getPriority)); + .eq(BpmOAWorkOrderAssignRuleDO::getDeptId, deptId)); } /** @@ -41,9 +38,18 @@ public interface BpmOAWorkOrderAssignRuleMapper extends BaseMapperX selectRulesByAssignee(Long assigneeUserId) { return selectList(new LambdaQueryWrapperX() - .eq(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId, assigneeUserId) - .eq(BpmOAWorkOrderAssignRuleDO::getStatus, 1) - .orderByAsc(BpmOAWorkOrderAssignRuleDO::getPriority)); + .eq(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId, assigneeUserId)); } -} \ No newline at end of file + /** + * 分页查询工单分配规则 + */ + default PageResult selectPage(BpmOAWorkOrderAssignRulePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(BpmOAWorkOrderAssignRuleDO::getWorkOrderType, reqVO.getWorkOrderType()) + .eqIfPresent(BpmOAWorkOrderAssignRuleDO::getDeptId, reqVO.getDeptId()) + .eqIfPresent(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId, reqVO.getAssigneeUserId()) + .betweenIfPresent(BpmOAWorkOrderAssignRuleDO::getCreateTime, reqVO.getCreateTime())); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderMapper.java index f7fcb229..8fcddc1d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderMapper.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorder.BpmOAWorkOrderPageReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorder.BpmOAWorkOrderRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderDO; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -69,19 +71,20 @@ public interface BpmOAWorkOrderMapper extends BaseMapperX { /** * 工单分页查询(带关联信息)- XML实现 */ - PageResult selectWorkOrderPage(@Param("loginUserId") Long loginUserId, - @Param("req") BpmOAWorkOrderPageReqVO req); + IPage selectWorkOrderPage(@Param("page") Page page, + @Param("req") BpmOAWorkOrderPageReqVO req); /** * 我发起的工单分页查询(带关联信息)- XML实现 */ - PageResult selectMyWorkOrderPage(@Param("loginUserId") Long loginUserId, - @Param("req") BpmOAWorkOrderPageReqVO req); + PageResult selectMyWorkOrderPage(@Param("page") Page page, + @Param("req") BpmOAWorkOrderPageReqVO req); /** * 分配给我的工单分页查询(带关联信息)- XML实现 */ - PageResult selectAssignedWorkOrderPage(@Param("loginUserId") Long loginUserId, - @Param("req") BpmOAWorkOrderPageReqVO req); + IPage selectAssignedWorkOrderPage(@Param("page") Page page, + @Param("req") BpmOAWorkOrderPageReqVO req); -} \ No newline at end of file + BpmOAWorkOrderDO selectByProcessInstanceId(@Param("processInstanceId") String processInstanceId); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderTrackMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderTrackMapper.java index d5dfc98e..759116be 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderTrackMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAWorkOrderTrackMapper.java @@ -2,8 +2,14 @@ package cn.iocoder.yudao.module.bpm.dal.mysql.oa; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorder.BpmOAWorkOrderTrackInfo; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorder.BpmOAWorkOrderTrackReqDTO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderTrackDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -24,4 +30,4 @@ public interface BpmOAWorkOrderTrackMapper extends BaseMapperX calculateTaskCandidateUsers(DelegateExecution execution) { + // 获得发起人 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); + List bpmTaskRespVOs = bpmTaskService.getTaskListByProcessInstanceId(processInstance.getProcessInstanceId()); + if (CollUtil.isEmpty(bpmTaskRespVOs)) { + return emptySet(); + } + //根据流程实例ID 取到调岗流程表单 + BpmOAWorkOrderDO bpmOAWorkOrderDO = bpmOAWorkOrderMapper.selectByProcessInstanceId(processInstance.getProcessInstanceId()); + //获取调岗部门ID + return bpmOAWorkOrderDO.getAssigneeUserId() != null ? asSet(bpmOAWorkOrderDO.getAssigneeUserId()) : emptySet(); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.LEADER_X31; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleService.java new file mode 100644 index 00000000..a138fa6b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleService.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.bpm.service.oa; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRulePageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleSaveReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderAssignRuleDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * BPM OA 工单分配规则 Service 接口 + * + * @author 系统 + */ +public interface BpmOAWorkOrderAssignRuleService { + + /** + * 创建工单分配规则 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkOrderAssignRule(@Valid BpmOAWorkOrderAssignRuleSaveReqVO createReqVO); + + /** + * 更新工单分配规则 + * + * @param updateReqVO 更新信息 + */ + void updateWorkOrderAssignRule(@Valid BpmOAWorkOrderAssignRuleSaveReqVO updateReqVO); + + /** + * 删除工单分配规则 + * + * @param id 编号 + */ + void deleteWorkOrderAssignRule(Long id); + + /** + * 获得工单分配规则 + * + * @param id 编号 + * @return 工单分配规则 + */ + BpmOAWorkOrderAssignRuleDO getWorkOrderAssignRule(Long id); + + /** + * 获得工单分配规则分页 + * + * @param pageReqVO 分页查询 + * @return 工单分配规则分页 + */ + PageResult getWorkOrderAssignRulePage(BpmOAWorkOrderAssignRulePageReqVO pageReqVO); + + /** + * 获得工单分配规则列表(用于导出) + * + * @param exportReqVO 查询条件 + * @return 工单分配规则列表 + */ + List getWorkOrderAssignRuleList(BpmOAWorkOrderAssignRulePageReqVO exportReqVO); + + /** + * 根据工单类型获取有效的分配规则 + * + * @param workOrderType 工单类型 + * @return 分配规则列表 + */ + List getEnabledRulesByType(String workOrderType); + + /** + * 批量更新规则状态 + * + * @param ids 规则ID列表 + * @param status 状态(1-启用,0-禁用) + */ + void updateRuleStatus(Collection ids, Integer status); + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleServiceImpl.java new file mode 100644 index 00000000..2bdf5e20 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderAssignRuleServiceImpl.java @@ -0,0 +1,176 @@ +package cn.iocoder.yudao.module.bpm.service.oa; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRulePageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleSaveReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderAssignRuleDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAWorkOrderAssignRuleMapper; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; +import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_WORK_TASK_NOT_EXISTS; + +/** + * BPM OA 工单分配规则 Service 实现类 + * + * @author 系统 + */ +@Service +@Validated +public class BpmOAWorkOrderAssignRuleServiceImpl implements BpmOAWorkOrderAssignRuleService { + + @Resource + private BpmOAWorkOrderAssignRuleMapper workOrderAssignRuleMapper; + + @Resource + private AdminUserApi userApi; + + @Resource + private DeptApi deptApi; + + @Resource + private DictDataApi dictDataApi; + + private static final String WORK_ORDER_TYPE = "work_order_type"; + private static final String WORK_ORDER_ASSIGN_RULE_STATUS = "work_order_assign_rule_status"; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createWorkOrderAssignRule(BpmOAWorkOrderAssignRuleSaveReqVO createReqVO) { + // 插入 + BpmOAWorkOrderAssignRuleDO workOrderAssignRule = BeanUtils.toBean(createReqVO, BpmOAWorkOrderAssignRuleDO.class); + workOrderAssignRuleMapper.insert(workOrderAssignRule); + + // 返回 + return workOrderAssignRule.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateWorkOrderAssignRule(BpmOAWorkOrderAssignRuleSaveReqVO updateReqVO) { + // 校验存在 + validateWorkOrderAssignRuleExists(updateReqVO.getId()); + // 更新 + BpmOAWorkOrderAssignRuleDO updateObj = BeanUtils.toBean(updateReqVO, BpmOAWorkOrderAssignRuleDO.class); + workOrderAssignRuleMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteWorkOrderAssignRule(Long id) { + // 校验存在 + validateWorkOrderAssignRuleExists(id); + + // 删除 + workOrderAssignRuleMapper.deleteById(id); + } + + private BpmOAWorkOrderAssignRuleDO validateWorkOrderAssignRuleExists(Long id) { + BpmOAWorkOrderAssignRuleDO workOrderAssignRule = workOrderAssignRuleMapper.selectById(id); + if (workOrderAssignRule == null) { + throw exception(OA_WORK_TASK_NOT_EXISTS); + } + return workOrderAssignRule; + } + + @Override + public BpmOAWorkOrderAssignRuleDO getWorkOrderAssignRule(Long id) { + return workOrderAssignRuleMapper.selectById(id); + } + + @Override + public PageResult getWorkOrderAssignRulePage(BpmOAWorkOrderAssignRulePageReqVO pageReqVO) { + PageResult pageResult = workOrderAssignRuleMapper.selectPage(pageReqVO); + return new PageResult<>(convertList(pageResult.getList()), pageResult.getTotal()); + } + + @Override + public List getWorkOrderAssignRuleList(BpmOAWorkOrderAssignRulePageReqVO exportReqVO) { + List list = workOrderAssignRuleMapper.selectList(new LambdaQueryWrapperX() + .likeIfPresent(BpmOAWorkOrderAssignRuleDO::getWorkOrderType, exportReqVO.getWorkOrderType()) + .eqIfPresent(BpmOAWorkOrderAssignRuleDO::getDeptId, exportReqVO.getDeptId()) + .eqIfPresent(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId, exportReqVO.getAssigneeUserId()) + .betweenIfPresent(BpmOAWorkOrderAssignRuleDO::getCreateTime, exportReqVO.getCreateTime())); + return convertList(list); + } + + @Override + public List getEnabledRulesByType(String workOrderType) { + return workOrderAssignRuleMapper.selectRulesByType(workOrderType); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateRuleStatus(Collection ids, Integer status) { + // 批量更新状态 + ids.forEach(id -> { + BpmOAWorkOrderAssignRuleDO updateObj = new BpmOAWorkOrderAssignRuleDO(); + updateObj.setId(id); + workOrderAssignRuleMapper.updateById(updateObj); + }); + } + + private List convertList(List list) { + if (list.isEmpty()) { + return java.util.Collections.emptyList(); + } + + // 获取用户信息 + Map userMap = convertMap( + userApi.getUserList(list.stream().map(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId).collect(Collectors.toSet())).getCheckedData(), + AdminUserRespDTO::getId); + + // 获取部门信息 + Map deptMap = convertMap( + deptApi.getDeptList(list.stream().map(BpmOAWorkOrderAssignRuleDO::getDeptId).collect(Collectors.toSet())).getCheckedData(), + DeptRespDTO::getId); + + // 获取字典信息 + Map workOrderTypeMap = convertMap( + dictDataApi.getDictDataList(WORK_ORDER_TYPE).getCheckedData(), + DictDataRespDTO::getValue); + + Map statusMap = convertMap( + dictDataApi.getDictDataList(WORK_ORDER_ASSIGN_RULE_STATUS).getCheckedData(), + DictDataRespDTO::getValue); + + return list.stream().map(rule -> { + BpmOAWorkOrderAssignRuleRespVO respVO = BeanUtils.toBean(rule, BpmOAWorkOrderAssignRuleRespVO.class); + + // 填充用户名称 + if (userMap.containsKey(rule.getAssigneeUserId())) { + respVO.setAssigneeUserName(userMap.get(rule.getAssigneeUserId()).getNickname()); + } + + // 填充部门名称 + if (deptMap.containsKey(rule.getDeptId())) { + respVO.setDeptName(deptMap.get(rule.getDeptId()).getName()); + } + + // 填充工单类型名称 + if (workOrderTypeMap.containsKey(rule.getWorkOrderType())) { + respVO.setWorkOrderTypeName(workOrderTypeMap.get(rule.getWorkOrderType()).getLabel()); + } + return respVO; + }).collect(Collectors.toList()); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderService.java index c0ce4353..0635dff8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderService.java @@ -16,7 +16,7 @@ public interface BpmOAWorkOrderService { /** * 创建工单 * - * @param userId 发起人ID + * @param userId 发起人ID * @param createReqVO 创建请求 * @return 工单ID */ @@ -25,7 +25,7 @@ public interface BpmOAWorkOrderService { /** * 更新工单状态结果 * - * @param id 工单ID + * @param id 工单ID * @param result BPM流程结果 */ void updateWorkOrderResult(Long id, Integer result); @@ -33,7 +33,7 @@ public interface BpmOAWorkOrderService { /** * 分配工单 * - * @param id 工单ID + * @param id 工单ID * @param assigneeUserId 责任人ID * @param assigneeDeptId 责任部门ID */ @@ -42,7 +42,7 @@ public interface BpmOAWorkOrderService { /** * 添加工单跟踪信息 * - * @param userId 操作人ID + * @param userId 操作人ID * @param trackReqVO 跟踪信息 */ void addTrackInfo(Long userId, @Valid BpmOAWorkOrderTrackReqVO trackReqVO); @@ -82,7 +82,7 @@ public interface BpmOAWorkOrderService { * 获取工单分页 * * @param loginUserId 登录用户ID - * @param pageVO 分页请求 + * @param pageVO 分页请求 * @return 分页结果 */ PageResult getWorkOrderPage(Long loginUserId, BpmOAWorkOrderPageReqVO pageVO); @@ -91,7 +91,7 @@ public interface BpmOAWorkOrderService { * 获取我发起的工单分页 * * @param loginUserId 登录用户ID - * @param pageVO 分页请求 + * @param pageVO 分页请求 * @return 分页结果 */ PageResult getMyWorkOrderPage(Long loginUserId, BpmOAWorkOrderPageReqVO pageVO); @@ -100,7 +100,7 @@ public interface BpmOAWorkOrderService { * 获取分配给我的工单分页 * * @param loginUserId 登录用户ID - * @param pageVO 分页请求 + * @param pageVO 分页请求 * @return 分页结果 */ PageResult getAssignedWorkOrderPage(Long loginUserId, BpmOAWorkOrderPageReqVO pageVO); @@ -113,4 +113,11 @@ public interface BpmOAWorkOrderService { */ Long getMyAssignedWorkOrderCount(Long userId); -} \ No newline at end of file + /** + * 工单操作记录跟踪分页列表 + * + * @param dto + * @return + */ + PageResult getTrackPage(@Valid BpmOAWorkOrderTrackReqDTO dto); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderServiceImpl.java index 353c3045..67f5fc80 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAWorkOrderServiceImpl.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.module.bpm.service.oa; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorder.*; @@ -14,10 +17,12 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAWorkOrderTrackMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -31,7 +36,6 @@ import java.util.Map; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_WORK_TASK_NOT_EXISTS; /** @@ -69,6 +73,10 @@ public class BpmOAWorkOrderServiceImpl extends BpmOABaseService implements BpmOA @Resource private DictDataApi dictDataApi; + private static final String WORK_ORDER_TYPE = "work_order_type"; + private static final String WORK_ORDER_LEVEL = "work_order_level"; + private static final String WORK_ORDER_STATUS = "work_order_status"; + @Override @Transactional(rollbackFor = Exception.class) public Long createWorkOrder(Long userId, BpmOAWorkOrderCreateReqVO createReqVO) { @@ -87,11 +95,9 @@ public class BpmOAWorkOrderServiceImpl extends BpmOABaseService implements BpmOA .status(1) // 默认状态:待分配 .result(BpmProcessInstanceResultEnum.PROCESS.getResult()) .build(); - - workOrderMapper.insert(workOrder); - // 自动分配责任人(根据规则) autoAssignWorkOrder(workOrder); + workOrderMapper.insert(workOrder); // 发起 BPM 流程 Map processInstanceVariables = new HashMap<>(); @@ -170,17 +176,17 @@ public class BpmOAWorkOrderServiceImpl extends BpmOABaseService implements BpmOA @Override public BpmOAWorkOrderRespVO getWorkOrderDetail(Long id) { BpmOAWorkOrderDO workOrder = validateWorkOrderExists(id); - + // 转换为VO BpmOAWorkOrderRespVO respVO = convertToRespVO(workOrder); - + // 获取跟踪记录 List trackList = trackMapper.selectByWorkOrderId(id); List trackInfoList = trackList.stream() .map(this::convertToTrackInfo) .collect(Collectors.toList()); respVO.setTrackInfo(trackInfoList); - + return respVO; } @@ -191,20 +197,47 @@ public class BpmOAWorkOrderServiceImpl extends BpmOABaseService implements BpmOA @Override public PageResult getWorkOrderPage(Long loginUserId, BpmOAWorkOrderPageReqVO pageVO) { + IPage pageResult = workOrderMapper.selectWorkOrderPage(MyBatisUtils.buildPage(pageVO), pageVO.setLoginUserId(loginUserId)); // 使用XML查询,直接返回带关联信息的VO数据 - return workOrderMapper.selectWorkOrderPage(loginUserId, pageVO); + return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); } @Override public PageResult getMyWorkOrderPage(Long loginUserId, BpmOAWorkOrderPageReqVO pageVO) { + List workOrderTypeDictList = dictDataApi.getDictDataList(WORK_ORDER_TYPE).getCheckedData(); + Map workOrderTypeDictMap = workOrderTypeDictList.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + List workOrderLevelDictList = dictDataApi.getDictDataList(WORK_ORDER_LEVEL).getCheckedData(); + Map workOrderLevelDictMap = workOrderLevelDictList.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + List workOrderStatusDictList = dictDataApi.getDictDataList(WORK_ORDER_STATUS).getCheckedData(); + Map workOrderStatusDictMap = workOrderStatusDictList.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + PageResult bpmOAWorkOrderRespVOPageResult = workOrderMapper.selectMyWorkOrderPage(MyBatisUtils.buildPage(pageVO), pageVO.setLoginUserId(loginUserId)); + for (BpmOAWorkOrderRespVO bpmOAWorkOrderRespVO : bpmOAWorkOrderRespVOPageResult.getList()) { + bpmOAWorkOrderRespVO.setTypeName(workOrderTypeDictMap.get(bpmOAWorkOrderRespVO.getType())); + bpmOAWorkOrderRespVO.setLevelName(workOrderLevelDictMap.get(String.valueOf(bpmOAWorkOrderRespVO.getLevel()))); + bpmOAWorkOrderRespVO.setStatusName(workOrderStatusDictMap.get(String.valueOf(bpmOAWorkOrderRespVO.getStatus()))); + } // 使用XML查询,直接返回带关联信息的VO数据 - return workOrderMapper.selectMyWorkOrderPage(loginUserId, pageVO); + return bpmOAWorkOrderRespVOPageResult; } @Override public PageResult getAssignedWorkOrderPage(Long loginUserId, BpmOAWorkOrderPageReqVO pageVO) { + List workOrderTypeDictList = dictDataApi.getDictDataList(WORK_ORDER_TYPE).getCheckedData(); + Map workOrderTypeDictMap = workOrderTypeDictList.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + List workOrderLevelDictList = dictDataApi.getDictDataList(WORK_ORDER_LEVEL).getCheckedData(); + Map workOrderLevelDictMap = workOrderLevelDictList.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + List workOrderStatusDictList = dictDataApi.getDictDataList(WORK_ORDER_STATUS).getCheckedData(); + Map workOrderStatusDictMap = workOrderStatusDictList.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + IPage pageResult = workOrderMapper.selectAssignedWorkOrderPage(MyBatisUtils.buildPage(pageVO), pageVO.setLoginUserId(loginUserId)); + PageResult bpmOAWorkOrderRespVOPageResult = + pageResult != null ? new PageResult<>(pageResult.getRecords(), pageResult.getTotal()) : new PageResult<>(); + for (BpmOAWorkOrderRespVO bpmOAWorkOrderRespVO : bpmOAWorkOrderRespVOPageResult.getList()) { + bpmOAWorkOrderRespVO.setTypeName(workOrderTypeDictMap.get(bpmOAWorkOrderRespVO.getType())); + bpmOAWorkOrderRespVO.setLevelName(workOrderLevelDictMap.get(String.valueOf(bpmOAWorkOrderRespVO.getLevel()))); + bpmOAWorkOrderRespVO.setStatusName(workOrderStatusDictMap.get(String.valueOf(bpmOAWorkOrderRespVO.getStatus()))); + } // 使用XML查询,直接返回带关联信息的VO数据 - return workOrderMapper.selectAssignedWorkOrderPage(loginUserId, pageVO); + return bpmOAWorkOrderRespVOPageResult; } @Override @@ -212,6 +245,15 @@ public class BpmOAWorkOrderServiceImpl extends BpmOABaseService implements BpmOA return workOrderMapper.selectMyAssignedCount(userId); } + @Override + public PageResult getTrackPage(BpmOAWorkOrderTrackReqDTO dto) { + PageResult pageResult = trackMapper.selectPage(new PageParam().setPageSize(dto.getPageSize()).setPageNo(dto.getPageNo()), + new LambdaQueryWrapper() + .eq(dto.getWorkOrderId() != null, BpmOAWorkOrderTrackDO::getWorkOrderId, dto.getWorkOrderId()) + .eq(StrUtil.isNotEmpty(dto.getOperationType()), BpmOAWorkOrderTrackDO::getOperationType, dto.getOperationType())); + return new PageResult<>(pageResult.getList().stream().map(this::convertToTrackInfo).collect(Collectors.toList()), pageResult.getTotal()); + } + /** * 创建跟踪记录 */ @@ -293,10 +335,10 @@ public class BpmOAWorkOrderServiceImpl extends BpmOABaseService implements BpmOA // 设置类型名称 respVO.setTypeName(getWorkOrderTypeName(workOrder.getType())); - + // 设置优先级名称 respVO.setLevelName(getWorkOrderLevelName(workOrder.getLevel())); - + // 设置状态名称 respVO.setStatusName(getWorkOrderStatusName(workOrder.getStatus())); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderMapper.xml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderMapper.xml index d06abbb0..47f42ebd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderMapper.xml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderMapper.xml @@ -34,7 +34,7 @@ - SELECT + SELECT w.id, w.title, w.type, @@ -114,20 +108,14 @@ fu.nickname AS from_user_name, fd.name AS from_dept_name, au.nickname AS assignee_user_name, - ad.name AS assignee_dept_name, - wt.label AS type_name, - wl.label AS level_name, - ws.label AS status_name + ad.name AS assignee_dept_name FROM bpm_oa_work_order w LEFT JOIN system_users fu ON w.from_user_id = fu.id LEFT JOIN system_dept fd ON w.from_dept_id = fd.id LEFT JOIN system_users au ON w.assignee_user_id = au.id LEFT JOIN system_dept ad ON w.assignee_dept_id = ad.id - LEFT JOIN system_dict_data wt ON wt.dict_type = 'work_order_type' AND wt.value = w.type - LEFT JOIN system_dict_data wl ON wl.dict_type = 'work_order_level' AND wl.value = CAST(w.level AS CHAR) - LEFT JOIN system_dict_data ws ON ws.dict_type = 'work_order_status' AND ws.value = CAST(w.status AS CHAR) - w.deleted = 0 AND w.from_user_id = #{loginUserId} + w.deleted = 0 AND w.from_user_id = #{req.loginUserId} AND w.title LIKE CONCAT('%', #{req.title}, '%') @@ -146,7 +134,7 @@ + - \ No newline at end of file + diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderTrackMapper.xml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderTrackMapper.xml new file mode 100644 index 00000000..90b09a23 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAWorkOrderTrackMapper.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/config/MinioConfigProperties.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/config/MinioConfigProperties.java new file mode 100644 index 00000000..16b70985 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/config/MinioConfigProperties.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.infra.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * MinIO 配置属性类 + * + * @author AI Assistant + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "minio") +public class MinioConfigProperties { + + /** + * MinIO 服务地址 + */ + private String endpoint; + + /** + * 访问密钥 + */ + private String accessKey; + + /** + * 密钥 + */ + private String secretKey; + + /** + * 默认存储桶名称 + */ + private String bucketName; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java index 62755fc6..3eafa353 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java @@ -3,17 +3,23 @@ package cn.iocoder.yudao.module.infra.controller.app.file; import cn.hutool.core.io.IoUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.infra.controller.app.file.vo.AppFileUploadReqVO; +import cn.iocoder.yudao.module.infra.controller.app.file.vo.MinioMultiUploadReqVO; +import cn.iocoder.yudao.module.infra.controller.app.file.vo.MinioUploadReqVO; +import cn.iocoder.yudao.module.infra.controller.app.file.vo.MinioUploadRespVO; import cn.iocoder.yudao.module.infra.service.file.FileService; +import cn.iocoder.yudao.module.infra.service.minio.MinioService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; 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.multipart.MultipartFile; import javax.annotation.Resource; +import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -27,6 +33,9 @@ public class AppFileController { @Resource private FileService fileService; + @Resource + private MinioService minioService; + @PostMapping("/upload") @Operation(summary = "上传文件") public CommonResult uploadFile(AppFileUploadReqVO uploadReqVO) throws Exception { @@ -35,4 +44,40 @@ public class AppFileController { return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); } + @PostMapping("/minio/upload") + @Operation(summary = "MinIO单文件上传") + public CommonResult minioUpload(MinioUploadReqVO uploadReqVO) { + try { + String fileUrl = minioService.uploadFile(uploadReqVO.getFile(), uploadReqVO.getPath()); + return success(MinioUploadRespVO.single(fileUrl)); + } catch (Exception e) { + log.error("MinIO文件上传失败", e); + return CommonResult.error(500, "文件上传失败: " + e.getMessage()); + } + } + + @PostMapping("/minio/upload/multiple") + @Operation(summary = "MinIO多文件上传") + public CommonResult minioUploadMultiple(@RequestParam("files") MultipartFile[] files) { + try { + List fileUrls = minioService.uploadFiles(files); + return success(MinioUploadRespVO.multiple(fileUrls)); + } catch (Exception e) { + log.error("MinIO多文件上传失败", e); + return CommonResult.error(500, "文件上传失败: " + e.getMessage()); + } + } + + @PostMapping("/minio/upload/batch") + @Operation(summary = "MinIO批量文件上传(表单方式)") + public CommonResult minioUploadBatch(MinioMultiUploadReqVO uploadReqVO) { + try { + List fileUrls = minioService.uploadFiles(uploadReqVO.getFiles()); + return success(MinioUploadRespVO.multiple(fileUrls)); + } catch (Exception e) { + log.error("MinIO批量文件上传失败", e); + return CommonResult.error(500, "文件上传失败: " + e.getMessage()); + } + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioMultiUploadReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioMultiUploadReqVO.java new file mode 100644 index 00000000..d395dc53 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioMultiUploadReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.infra.controller.app.file.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotEmpty; + +/** + * MinIO 多文件上传请求 VO + * + * @author AI Assistant + */ +@Schema(description = "用户 App - MinIO 多文件上传请求") +@Data +public class MinioMultiUploadReqVO { + + @Schema(description = "文件数组", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "文件不能为空") + private MultipartFile[] files; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadReqVO.java new file mode 100644 index 00000000..7cb424c7 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.infra.controller.app.file.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotNull; + +/** + * MinIO 文件上传请求 VO + * + * @author AI Assistant + */ +@Schema(description = "用户 App - MinIO 文件上传请求") +@Data +public class MinioUploadReqVO { + + @Schema(description = "文件", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "文件不能为空") + private MultipartFile file; + + @Schema(description = "文件路径", example = "avatar/user.jpg") + private String path; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadRespVO.java new file mode 100644 index 00000000..7729db63 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/MinioUploadRespVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.infra.controller.app.file.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * MinIO 文件上传响应 VO + * + * @author AI Assistant + */ +@Schema(description = "用户 App - MinIO 文件上传响应") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MinioUploadRespVO { + + @Schema(description = "文件访问URL", example = "http://113.105.111.100:9000/yudao-bucket/abc123.jpg") + private String url; + + @Schema(description = "文件访问URL列表", example = "[\"http://113.105.111.100:9000/yudao-bucket/abc123.jpg\"]") + private List urls; + + /** + * 创建单文件上传响应 + */ + public static MinioUploadRespVO single(String url) { + return new MinioUploadRespVO(url, null); + } + + /** + * 创建多文件上传响应 + */ + public static MinioUploadRespVO multiple(List urls) { + return new MinioUploadRespVO(null, urls); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/minio/MinioService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/minio/MinioService.java new file mode 100644 index 00000000..2c6948ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/minio/MinioService.java @@ -0,0 +1,158 @@ +package cn.iocoder.yudao.module.infra.service.minio; + +import cn.iocoder.yudao.module.infra.config.MinioConfigProperties; +import io.minio.BucketExistsArgs; +import io.minio.MakeBucketArgs; +import io.minio.MinioClient; +import io.minio.PutObjectArgs; +import io.minio.RemoveObjectArgs; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * MinIO 文件服务类 + * + * @author AI Assistant + */ +@Slf4j +@Service +public class MinioService { + + @Resource + private MinioConfigProperties minioConfigProperties; + + private MinioClient minioClient; + + /** + * 初始化 MinIO 客户端 + */ + @PostConstruct + public void init() { + try { + this.minioClient = MinioClient.builder() + .endpoint(minioConfigProperties.getEndpoint()) + .credentials(minioConfigProperties.getAccessKey(), minioConfigProperties.getSecretKey()) + .build(); + + // 检查桶是否存在,不存在则创建 + boolean bucketExists = minioClient.bucketExists( + BucketExistsArgs.builder() + .bucket(minioConfigProperties.getBucketName()) + .build() + ); + + if (!bucketExists) { + minioClient.makeBucket( + MakeBucketArgs.builder() + .bucket(minioConfigProperties.getBucketName()) + .build() + ); + log.info("创建存储桶: {}", minioConfigProperties.getBucketName()); + } + + log.info("MinIO 客户端初始化成功. Endpoint: {}, Bucket: {}", + minioConfigProperties.getEndpoint(), minioConfigProperties.getBucketName()); + } catch (Exception e) { + log.error("MinIO 客户端初始化失败", e); + throw new RuntimeException("MinIO 客户端初始化失败", e); + } + } + + /** + * 上传单个文件 + * + * @param file 上传的文件 + * @param path 文件存储路径,如果为空则自动生成 + * @return 文件访问URL + */ + public String uploadFile(MultipartFile file, String path) throws Exception { + if (file.isEmpty()) { + throw new IllegalArgumentException("上传文件不能为空"); + } + + // 如果路径为空,则生成随机路径 + if (path == null || path.trim().isEmpty()) { + String originalFilename = file.getOriginalFilename(); + String extension = ""; + if (originalFilename != null && originalFilename.contains(".")) { + extension = originalFilename.substring(originalFilename.lastIndexOf(".")); + } + path = UUID.randomUUID().toString() + extension; + } + + try (InputStream inputStream = file.getInputStream()) { + // 上传文件到 MinIO + minioClient.putObject( + PutObjectArgs.builder() + .bucket(minioConfigProperties.getBucketName()) + .object(path) + .stream(inputStream, file.getSize(), -1) + .contentType(file.getContentType()) + .build() + ); + + // 生成文件访问URL + String fileUrl = minioConfigProperties.getEndpoint() + "/" + + minioConfigProperties.getBucketName() + "/" + path; + + log.info("文件上传成功: {}", fileUrl); + return fileUrl; + } catch (Exception e) { + log.error("文件上传失败: {}", path, e); + throw new Exception("文件上传失败: " + e.getMessage(), e); + } + } + + /** + * 上传多个文件 + * + * @param files 上传的文件数组 + * @return 文件访问URL列表 + */ + public List uploadFiles(MultipartFile[] files) throws Exception { + if (files == null || files.length == 0) { + throw new IllegalArgumentException("上传文件不能为空"); + } + + List fileUrls = new ArrayList<>(); + + for (MultipartFile file : files) { + if (!file.isEmpty()) { + String fileUrl = uploadFile(file, null); + fileUrls.add(fileUrl); + } + } + + log.info("批量文件上传完成,共上传 {} 个文件", fileUrls.size()); + return fileUrls; + } + + /** + * 删除文件 + * + * @param path 文件路径 + */ + public void deleteFile(String path) throws Exception { + try { + minioClient.removeObject( + RemoveObjectArgs.builder() + .bucket(minioConfigProperties.getBucketName()) + .object(path) + .build() + ); + log.info("文件删除成功: {}", path); + } catch (Exception e) { + log.error("文件删除失败: {}", path, e); + throw new Exception("文件删除失败: " + e.getMessage(), e); + } + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml index 649d1bfe..4075c4d1 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml @@ -1,5 +1,11 @@ --- #################### 数据库相关配置 #################### spring: + # Servlet 配置 + servlet: + # 文件上传相关配置项 + multipart: + max-file-size: 5GB # 单个文件大小 + max-request-size: 10GB # 设置总上传的文件大小 # 数据源配置项 autoconfigure: @@ -122,6 +128,15 @@ logging: cn.iocoder.yudao.module.infra.dal.mysql: debug cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info +--- #################### MinIO 文件服务配置 #################### + +# MinIO 配置项 +minio: + endpoint: http://10.10.2.3:9000 # MinIO 服务地址 + access-key: fKpfyQYqJn7jSId2WDhn # 访问密钥 + secret-key: XkTbVLD1pgvxXphFIjgpIYKks166o9zGrDFqTz3t # 密钥 + bucket-name: test-bucket # 默认存储桶名称 + --- #################### 芋道相关配置 #################### # 芋道配置项,设置当前项目所有自定义的配置