diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index e3b20dde..8ff11c96 100644 --- a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -238,8 +238,8 @@ public class OssClient { /** * 下载文件从 Amazon S3 到 输出流 * - * @param key 文件在 Amazon S3 中的对象键 - * @param out 输出流 + * @param key 文件在 Amazon S3 中的对象键 + * @param out 输出流 * @param consumer 自定义处理逻辑 * @return 输出流中写入的字节数(长度) * @throws OssException 如果下载失败,抛出自定义异常 @@ -317,6 +317,18 @@ public class OssClient { return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), contentType); } + /** + * 上传 byte[] 数据到 Amazon S3,使用指定的文件路径构造对象键。 + * + * @param data 要上传的 byte[] 数据 + * @param filePath 对象键的文件路径 + * @return UploadResult 包含上传后的文件信息 + * @throws OssException 如果上传失败,抛出自定义异常 + */ + public UploadResult uploadFilePath(byte[] data, String filePath, String contentType) { + return upload(new ByteArrayInputStream(data), filePath, Long.valueOf(data.length), contentType); + } + /** * 上传 InputStream 到 Amazon S3,使用指定的后缀构造对象键。 * diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ForemanVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ForemanVo.java new file mode 100644 index 00000000..5d8664cc --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ForemanVo.java @@ -0,0 +1,26 @@ +package org.dromara.project.domain.resp.projectteam; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author lcj + * @date 2025/4/11 16:37 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ForemanVo { + + /** + * 班组长id + */ + private Long foremanId; + + /** + * 班组长名字 + */ + private String foremanName; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ProjectTeamForemanResp.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ProjectTeamForemanResp.java index 623dc5a8..6378f89e 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ProjectTeamForemanResp.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/resp/projectteam/ProjectTeamForemanResp.java @@ -4,6 +4,7 @@ import lombok.Data; import java.io.Serial; import java.io.Serializable; +import java.util.List; /** * @author lcj @@ -31,13 +32,8 @@ public class ProjectTeamForemanResp implements Serializable { private Long projectId; /** - * 班组长id + * 班组长列表 */ - private Long foremanId; - - /** - * 班组长名字 - */ - private String foremanName; + private List foremanList; } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectTeamServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectTeamServiceImpl.java index c3b7113e..aa30e7fc 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectTeamServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectTeamServiceImpl.java @@ -21,6 +21,7 @@ import org.dromara.project.domain.enums.ProjectTeamMemberPostEnum; import org.dromara.project.domain.req.projectteam.ProjectTeamCreateReq; import org.dromara.project.domain.req.projectteam.ProjectTeamQueryReq; import org.dromara.project.domain.req.projectteam.ProjectTeamUpdateReq; +import org.dromara.project.domain.resp.projectteam.ForemanVo; import org.dromara.project.domain.resp.projectteam.ProjectTeamForemanResp; import org.dromara.project.domain.vo.BusProjectTeamVo; import org.dromara.project.mapper.BusProjectTeamMapper; @@ -231,9 +232,11 @@ public class BusProjectTeamServiceImpl extends ServiceImpl constructionUserList = foremanMap.get(projectTeam.getId()); + List foremanVoList = constructionUserList.stream() + .map(constructionUser -> new ForemanVo(constructionUser.getId(), constructionUser.getUserName())) + .toList(); + projectTeamForemanResp.setForemanList(foremanVoList); } return projectTeamForemanResp; }).toList(); diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/constant/DocumentSafetyMeetingConstant.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/constant/DocumentSafetyMeetingConstant.java new file mode 100644 index 00000000..0bdab13f --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/constant/DocumentSafetyMeetingConstant.java @@ -0,0 +1,22 @@ +package org.dromara.safety.constant; + +import java.util.List; + +/** + * @author lcj + * @date 2025/4/14 10:50 + */ +public interface DocumentSafetyMeetingConstant { + + /** + * 顶级目录前缀 + */ + String TOP_FOLDER_PREFIX = "/doc/safety/meeting/"; + + static String getTopFolderPrefix(Long projectId) { + return String.format("%s%s/", TOP_FOLDER_PREFIX, projectId); + } + + List PICTURE_SUFFIX_LIST = List.of("jpeg", "jpg", "png", "webp"); + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/controller/BusDocumentSafetyMeetingController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/controller/BusDocumentSafetyMeetingController.java new file mode 100644 index 00000000..63aeff23 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/controller/BusDocumentSafetyMeetingController.java @@ -0,0 +1,132 @@ +package org.dromara.safety.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingCreateFileReq; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingCreateFolderReq; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingQueryReq; +import org.dromara.safety.domain.resp.documentsafetymeeting.DocumentSafetyMeetingRecycleBinResp; +import org.dromara.safety.domain.vo.BusDocumentSafetyMeetingVo; +import org.dromara.safety.service.IBusDocumentSafetyMeetingService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * 安全会议纪要 + * + * @author lcj + * @date 2025-04-14 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/safety/documentSafetyMeeting") +public class BusDocumentSafetyMeetingController extends BaseController { + + private final IBusDocumentSafetyMeetingService busDocumentSafetyMeetingService; + + /** + * 查询安全会议纪要列表 + */ + @SaCheckPermission("safety:documentSafetyMeeting:list") + @GetMapping("/list") + public R> list(DocumentSafetyMeetingQueryReq req) { + return R.ok(busDocumentSafetyMeetingService.queryList(req)); + } + + /** + * 查询安全会议纪要回收站列表 + */ + @SaCheckPermission("safety:documentSafetyMeeting:list") + @GetMapping("/recycleBin/list") + public TableDataInfo list(DocumentSafetyMeetingQueryReq req, PageQuery pageQuery) { + return busDocumentSafetyMeetingService.queryRecycleBinPageList(req, pageQuery); + } + + /** + * 获取安全会议纪要详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("safety:documentSafetyMeeting:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(busDocumentSafetyMeetingService.queryById(id)); + } + + /** + * 新增安全会议纪要文件夹 + */ + @SaCheckPermission("safety:documentSafetyMeeting:add") + @Log(title = "安全会议纪要", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/folder") + public R addFolder(@RequestBody DocumentSafetyMeetingCreateFolderReq req) { + return R.ok(busDocumentSafetyMeetingService.insertByFolder(req)); + } + + /** + * 新增安全会议纪要文件 + */ + @SaCheckPermission("safety:documentSafetyMeeting:add") + @Log(title = "安全会议纪要", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/file") + public R addFile(@RequestPart("file") MultipartFile file, @RequestBody DocumentSafetyMeetingCreateFileReq req) { + return R.ok(busDocumentSafetyMeetingService.insertByFile(file, req)); + } + + /** + * 批量恢复安全会议纪要文件 + * + * @param ids 主键串 + */ + @SaCheckPermission("safety:documentSafetyMeeting:edit") + @Log(title = "安全会议纪要", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping("/recovery/{ids}") + public R recovery(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(busDocumentSafetyMeetingService.recoveryBatchById(List.of(ids))); + } + + /** + * 删除安全会议纪要 + * + * @param ids 主键串 + */ + @SaCheckPermission("safety:documentSafetyMeeting:remove") + @Log(title = "安全会议纪要", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(busDocumentSafetyMeetingService.deleteWithRecycleBin(List.of(ids))); + } + + /** + * 彻底删除安全会议纪要 + * + * @param ids 主键串 + */ + @SaCheckPermission("safety:documentSafetyMeeting:remove") + @Log(title = "安全会议纪要", businessType = BusinessType.DELETE) + @DeleteMapping("/completelyDelete/{ids}") + public R completelyDelete(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(busDocumentSafetyMeetingService.completelyDelete(List.of(ids))); + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/BusDocumentSafetyMeeting.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/BusDocumentSafetyMeeting.java new file mode 100644 index 00000000..7fa69ed8 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/BusDocumentSafetyMeeting.java @@ -0,0 +1,88 @@ +package org.dromara.safety.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.common.mybatis.core.domain.BaseEntity; + +import java.io.Serial; +import java.util.Date; + +/** + * 安全会议纪要对象 bus_document_safety_meeting + * + * @author lcj + * @date 2025-04-14 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("bus_document_safety_meeting") +public class BusDocumentSafetyMeeting extends BaseEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id") + private Long id; + + /** + * 项目id + */ + private Long projectId; + + /** + * 父级(0代表顶级) + */ + private Long pid; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 文件url + */ + private String fileUrl; + + /** + * 文件类型(1文件-2文件夹-3图片) + */ + private String fileType; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 状态(0正常 1删除) + */ + private String fileStatus; + + /** + * 原文件名 + */ + private String originalName; + + /** + * 备注 + */ + private String remark; + + /** + * 删除时间 + */ + private Date deletedAt; + + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/enums/DocumentStatusEnum.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/enums/DocumentStatusEnum.java new file mode 100644 index 00000000..789f5e90 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/enums/DocumentStatusEnum.java @@ -0,0 +1,24 @@ +package org.dromara.safety.domain.enums; + +import lombok.Getter; + +/** + * @author lcj + * @date 2025/4/14 14:03 + */ +@Getter +public enum DocumentStatusEnum { + + NORMAL("正常", "0"), + DELETE("删除", "1"); + + private final String text; + + private final String value; + + DocumentStatusEnum(String text, String value) { + this.text = text; + this.value = value; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/enums/DocumentTypeEnum.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/enums/DocumentTypeEnum.java new file mode 100644 index 00000000..36bd3a26 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/enums/DocumentTypeEnum.java @@ -0,0 +1,25 @@ +package org.dromara.safety.domain.enums; + +import lombok.Getter; + +/** + * @author lcj + * @date 2025/4/14 10:42 + */ +@Getter +public enum DocumentTypeEnum { + + FILE("文件", "1"), + FOLDER("文件夹", "2"), + PICTURE("图片", "3"); + + private final String text; + + private final String value; + + DocumentTypeEnum(String text, String value) { + this.text = text; + this.value = value; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingCreateFileReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingCreateFileReq.java new file mode 100644 index 00000000..aded134c --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingCreateFileReq.java @@ -0,0 +1,30 @@ +package org.dromara.safety.domain.req.documentsafetymeeting; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/14 10:06 + */ +@Data +public class DocumentSafetyMeetingCreateFileReq implements Serializable { + + @Serial + private static final long serialVersionUID = -4889729533450017719L; + + /** + * 项目id + */ + @NotNull(message = "项目id不能为空") + private Long projectId; + + /** + * 父级(0代表顶级) + */ + private Long pid; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingCreateFolderReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingCreateFolderReq.java new file mode 100644 index 00000000..f63bfe6d --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingCreateFolderReq.java @@ -0,0 +1,41 @@ +package org.dromara.safety.domain.req.documentsafetymeeting; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/14 10:06 + */ +@Data +public class DocumentSafetyMeetingCreateFolderReq implements Serializable { + + @Serial + private static final long serialVersionUID = 486922166637112952L; + + /** + * 项目id + */ + @NotNull(message = "项目id不能为空") + private Long projectId; + + /** + * 父级(0代表顶级) + */ + private Long pid; + + /** + * 文件名称 + */ + @NotNull(message = "文件名称不能为空") + private String fileName; + + /** + * 备注 + */ + private String remark; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingQueryReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingQueryReq.java new file mode 100644 index 00000000..1c1f1b63 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/req/documentsafetymeeting/DocumentSafetyMeetingQueryReq.java @@ -0,0 +1,38 @@ +package org.dromara.safety.domain.req.documentsafetymeeting; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/14 10:04 + */ +@Data +public class DocumentSafetyMeetingQueryReq implements Serializable { + + @Serial + private static final long serialVersionUID = -5290567924829663119L; + + /** + * 项目id + */ + private Long projectId; + + /** + * 父级(0代表顶级) + */ + private Long pid; + + /** + * 文件类型(1文件-2文件夹-3图片) + */ + private String fileType; + + /** + * 不是文件类型(1文件-2文件夹-3图片) + */ + private String notFileType; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/resp/documentsafetymeeting/DocumentSafetyMeetingRecycleBinResp.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/resp/documentsafetymeeting/DocumentSafetyMeetingRecycleBinResp.java new file mode 100644 index 00000000..e7f10c88 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/resp/documentsafetymeeting/DocumentSafetyMeetingRecycleBinResp.java @@ -0,0 +1,74 @@ +package org.dromara.safety.domain.resp.documentsafetymeeting; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * @author lcj + * @date 2025/4/14 17:44 + */ +@Data +public class DocumentSafetyMeetingRecycleBinResp implements Serializable { + + @Serial + private static final long serialVersionUID = 1302984678621164410L; + + /** + * 主键id + */ + private Long id; + + /** + * 项目id + */ + private Long projectId; + + /** + * 父级(0代表顶级) + */ + private Long pid; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 文件url + */ + private String fileUrl; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 文件类型(1文件-2文件夹-3图片) + */ + private String fileType; + + /** + * 原文件名 + */ + private String originalName; + + /** + * 备注 + */ + private String remark; + + /** + * 删除时间 + */ + private Date deletedAt; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusDocumentSafetyMeetingVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusDocumentSafetyMeetingVo.java new file mode 100644 index 00000000..2d9d8ee3 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusDocumentSafetyMeetingVo.java @@ -0,0 +1,74 @@ +package org.dromara.safety.domain.vo; + +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.safety.domain.BusDocumentSafetyMeeting; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 安全会议纪要视图对象 bus_document_safety_meeting + * + * @author lcj + * @date 2025-04-14 + */ +@Data +@AutoMapper(target = BusDocumentSafetyMeeting.class) +public class BusDocumentSafetyMeetingVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 项目id + */ + private Long projectId; + + /** + * 父级(0代表顶级) + */ + private Long pid; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 文件url + */ + private String fileUrl; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 文件类型(1文件-2文件夹-3图片) + */ + private String fileType; + + /** + * 原文件名 + */ + private String originalName; + + /** + * 备注 + */ + private String remark; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusTeamMeetingVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusTeamMeetingVo.java index 57cbfd6a..eda6bde9 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusTeamMeetingVo.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/vo/BusTeamMeetingVo.java @@ -50,7 +50,7 @@ public class BusTeamMeetingVo implements Serializable { /** * 班组名称 */ - private IdAndNameVO team; + private String teamName; /** * 分包公司id @@ -61,7 +61,7 @@ public class BusTeamMeetingVo implements Serializable { /** * 分包公司 */ - private IdAndNameVO contractor; + private String contractorName; /** * 开会时间 @@ -78,7 +78,7 @@ public class BusTeamMeetingVo implements Serializable { /** * 宣讲人 */ - private IdAndNameVO compere; + private String compereName; /** * 参与人id(多个用,号隔开) @@ -101,10 +101,14 @@ public class BusTeamMeetingVo implements Serializable { /** * 班会图片(多个用,号隔开) */ - @ExcelProperty(value = "班会图片", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "多=个用,号隔开") + @ExcelProperty(value = "班会图片") private String picture; + /** + * 班会图片列表 + */ + private List pictureUrlList; + /** * 备注 */ diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/mapper/BusDocumentSafetyMeetingMapper.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/mapper/BusDocumentSafetyMeetingMapper.java new file mode 100644 index 00000000..7353a4ea --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/mapper/BusDocumentSafetyMeetingMapper.java @@ -0,0 +1,15 @@ +package org.dromara.safety.mapper; + +import org.dromara.safety.domain.BusDocumentSafetyMeeting; +import org.dromara.safety.domain.vo.BusDocumentSafetyMeetingVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 安全会议纪要Mapper接口 + * + * @author lcj + * @date 2025-04-14 + */ +public interface BusDocumentSafetyMeetingMapper extends BaseMapperPlus { + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IBusDocumentSafetyMeetingService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IBusDocumentSafetyMeetingService.java new file mode 100644 index 00000000..491eceef --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IBusDocumentSafetyMeetingService.java @@ -0,0 +1,125 @@ +package org.dromara.safety.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.safety.domain.BusDocumentSafetyMeeting; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingCreateFileReq; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingCreateFolderReq; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingQueryReq; +import org.dromara.safety.domain.resp.documentsafetymeeting.DocumentSafetyMeetingRecycleBinResp; +import org.dromara.safety.domain.vo.BusDocumentSafetyMeetingVo; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Collection; +import java.util.List; + +/** + * 安全会议纪要Service接口 + * + * @author lcj + * @date 2025-04-14 + */ +public interface IBusDocumentSafetyMeetingService extends IService { + + /** + * 查询安全会议纪要 + * + * @param id 主键 + * @return 安全会议纪要 + */ + BusDocumentSafetyMeetingVo queryById(Long id); + + /** + * 分页查询安全会议纪要列表 + * + * @param req 查询条件 + * @return 安全会议纪要分页列表 + */ + List queryList(DocumentSafetyMeetingQueryReq req); + + /** + * 分页查询安全会议纪要回收站列表 + * + * @param req 查询条件 + * @param pageQuery 分页参数 + * @return 安全会议纪要分页列表 + */ + TableDataInfo queryRecycleBinPageList(DocumentSafetyMeetingQueryReq req, PageQuery pageQuery); + + /** + * 新增安全会议纪要文件夹 + * + * @param req 文件夹创建请求 + * @return 是否新增成功 + */ + Long insertByFolder(DocumentSafetyMeetingCreateFolderReq req); + + /** + * 新增安全会议纪要文件 + * + * @param file 文件 + * @param req 文件上传请求 + * @return 是否新增成功 + */ + Long insertByFile(MultipartFile file, DocumentSafetyMeetingCreateFileReq req); + + /** + * 批量恢复安全会议纪要信息 + * + * @param ids 待删除的主键集合 + * @return 是否删除成功 + */ + Boolean recoveryBatchById(Collection ids); + + /** + * 批量删除安全会议纪要信息 + * + * @param ids 待删除的主键集合 + * @return 是否删除成功 + */ + Boolean deleteWithRecycleBin(Collection ids); + + /** + * 彻底批量删除安全会议纪要 + * + * @param ids 待删除的主键集合 + * @return 是否删除成功 + */ + Boolean completelyDelete(Collection ids); + + /** + * 获取安全会议纪要视图对象 + * + * @param documentSafetyMeeting 安全会议纪要对象 + * @return 安全会议纪要视图对象 + */ + BusDocumentSafetyMeetingVo getVo(BusDocumentSafetyMeeting documentSafetyMeeting); + + /** + * 获取安全会议纪要查询条件封装 + * + * @param req 安全会议纪要查询条件 + * @return 安全会议纪要查询条件封装 + */ + LambdaQueryWrapper buildQueryWrapper(DocumentSafetyMeetingQueryReq req); + + /** + * 获取安全会议纪要分页对象视图 + * + * @param documentSafetyMeetingPage 安全会议纪要分页对象 + * @return 安全会议纪要分页对象视图 + */ + Page getVoPage(Page documentSafetyMeetingPage); + + /** + * 递归查询所有的文件和文件夹以及文件夹下的子文件夹的id + * + * @param ids 主键集合 + * @return 整合所有的id集合 + */ + List getAllChildIdList(Collection ids); + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusDocumentSafetyMeetingServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusDocumentSafetyMeetingServiceImpl.java new file mode 100644 index 00000000..9220627b --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusDocumentSafetyMeetingServiceImpl.java @@ -0,0 +1,454 @@ +package org.dromara.safety.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.HttpStatus; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.ObjectUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.project.service.IBusProjectService; +import org.dromara.safety.constant.DocumentSafetyMeetingConstant; +import org.dromara.safety.domain.BusDocumentSafetyMeeting; +import org.dromara.safety.domain.enums.DocumentStatusEnum; +import org.dromara.safety.domain.enums.DocumentTypeEnum; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingCreateFileReq; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingCreateFolderReq; +import org.dromara.safety.domain.req.documentsafetymeeting.DocumentSafetyMeetingQueryReq; +import org.dromara.safety.domain.resp.documentsafetymeeting.DocumentSafetyMeetingRecycleBinResp; +import org.dromara.safety.domain.vo.BusDocumentSafetyMeetingVo; +import org.dromara.safety.mapper.BusDocumentSafetyMeetingMapper; +import org.dromara.safety.service.IBusDocumentSafetyMeetingService; +import org.dromara.system.domain.vo.SysOssUploadVo; +import org.dromara.system.service.ISysOssService; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 安全会议纪要Service业务层处理 + * + * @author lcj + * @date 2025-04-14 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class BusDocumentSafetyMeetingServiceImpl extends ServiceImpl + implements IBusDocumentSafetyMeetingService { + + @Resource + private IBusProjectService projectService; + + @Resource + private ISysOssService ossService; + + /** + * 查询安全会议纪要 + * + * @param id 主键 + * @return 安全会议纪要 + */ + @Override + public BusDocumentSafetyMeetingVo queryById(Long id) { + BusDocumentSafetyMeeting documentSafetyMeeting = this.getById(id); + if (documentSafetyMeeting == null) { + throw new ServiceException("安全会议纪要信息不存在", HttpStatus.NOT_FOUND); + } + return this.getVo(documentSafetyMeeting); + } + + /** + * 分页查询安全会议纪要列表 + * + * @param req 查询条件 + * @return 安全会议纪要分页列表 + */ + @Override + public List queryList(DocumentSafetyMeetingQueryReq req) { + LambdaQueryWrapper lqw = buildQueryWrapper(req); + // 排除已经删除的文件 + lqw.eq(BusDocumentSafetyMeeting::getFileStatus, DocumentStatusEnum.NORMAL.getValue()); + List result = this.list(lqw); + return result.stream().map(this::getVo).toList(); + } + + /** + * 分页查询安全会议纪要回收站列表 + * + * @param req 查询条件 + * @param pageQuery 分页参数 + * @return 安全会议纪要分页列表 + */ + @Override + public TableDataInfo queryRecycleBinPageList(DocumentSafetyMeetingQueryReq req, PageQuery pageQuery) { + LambdaQueryWrapper lqw = this.buildQueryWrapper(req); + lqw.eq(BusDocumentSafetyMeeting::getFileStatus, DocumentStatusEnum.DELETE.getValue()); + Page result = this.page(pageQuery.build(), lqw); + List documentSafetyMeetingList = result.getRecords(); + // 添加分页信息 + Page documentSafetyMeetingVoPage = new Page<>( + result.getCurrent(), + result.getSize(), + result.getTotal()); + if (CollUtil.isEmpty(documentSafetyMeetingList)) { + return TableDataInfo.build(documentSafetyMeetingVoPage); + } + // 对象列表 => 封装对象列表 + List list = documentSafetyMeetingList.stream().map(documentSafetyMeeting -> { + DocumentSafetyMeetingRecycleBinResp resp = new DocumentSafetyMeetingRecycleBinResp(); + BeanUtils.copyProperties(documentSafetyMeeting, resp); + return resp; + }).toList(); + documentSafetyMeetingVoPage.setRecords(list); + return TableDataInfo.build(documentSafetyMeetingVoPage); + } + + /** + * 新增安全会议纪要文件夹 + * + * @param req 文件夹创建请求 + * @return 是否新增成功 + */ + @Override + public Long insertByFolder(DocumentSafetyMeetingCreateFolderReq req) { + if (req == null) { + throw new ServiceException("文件夹创建请求不能为空", HttpStatus.BAD_REQUEST); + } + if (StringUtils.isEmpty(req.getFileName())) { + throw new ServiceException("文件夹名称不能为空", HttpStatus.BAD_REQUEST); + } + BusDocumentSafetyMeeting documentSafetyMeeting = new BusDocumentSafetyMeeting(); + BeanUtils.copyProperties(req, documentSafetyMeeting); + Long pid = req.getPid(); + String filePath; + if (pid != null && pid != 0) { + BusDocumentSafetyMeeting pDocumentSafetyMeeting = this.getById(pid); + // 判断父级目录是否存在 + validParentFolder(pDocumentSafetyMeeting, req.getProjectId()); + filePath = pDocumentSafetyMeeting.getFilePath() + "/" + req.getFileName(); + } else { + filePath = DocumentSafetyMeetingConstant.getTopFolderPrefix(req.getProjectId()) + req.getFileName(); + } + // 填充默认值 + documentSafetyMeeting.setFilePath(filePath); + documentSafetyMeeting.setFileType(DocumentTypeEnum.FOLDER.getValue()); + boolean save = this.save(documentSafetyMeeting); + if (!save) { + throw new ServiceException("新增目录失败,数据库异常", HttpStatus.ERROR); + } + return documentSafetyMeeting.getId(); + } + + /** + * 新增安全会议纪要文件 + * + * @param req 文件上传请求 + * @return 是否新增成功 + */ + @Override + public Long insertByFile(MultipartFile file, DocumentSafetyMeetingCreateFileReq req) { + // 数据校验 + if (ObjectUtils.isEmpty(file)) { + throw new ServiceException("文件不能为空", HttpStatus.BAD_REQUEST); + } + Long projectId = req.getProjectId(); + if (projectService.getById(projectId) == null) { + throw new ServiceException("项目不存在", HttpStatus.BAD_REQUEST); + } + // 拼接文件名 + String originalFilename = file.getOriginalFilename(); + String suffix = FileUtil.getSuffix(originalFilename); + String uuid = IdUtil.fastSimpleUUID(); + String date = DateUtils.getDate(); + String fileName = String.format("%s_%s.%s", date, uuid, suffix); + // 拼接文件路径 + Long pid = req.getPid(); + String filePath; + if (pid != null && pid != 0) { + BusDocumentSafetyMeeting pDocumentSafetyMeeting = this.getById(pid); + // 判断父级目录是否存在 + validParentFolder(pDocumentSafetyMeeting, projectId); + filePath = pDocumentSafetyMeeting.getFilePath() + "/" + fileName; + } else { + filePath = DocumentSafetyMeetingConstant.getTopFolderPrefix(projectId) + fileName; + } + // 上传文件 + SysOssUploadVo ossUploadVo = ossService.uploadWithNoSave(file, filePath); + // 保存文件信息 + BusDocumentSafetyMeeting documentSafetyMeeting = new BusDocumentSafetyMeeting(); + documentSafetyMeeting.setFilePath(filePath); + documentSafetyMeeting.setFileUrl(ossUploadVo.getOssId()); + documentSafetyMeeting.setFileSuffix(suffix); + // 判断文件类型 + if (DocumentSafetyMeetingConstant.PICTURE_SUFFIX_LIST.contains(suffix)) { + documentSafetyMeeting.setFileType(DocumentTypeEnum.PICTURE.getValue()); + } else { + documentSafetyMeeting.setFileType(DocumentTypeEnum.FILE.getValue()); + } + documentSafetyMeeting.setFileName(ossUploadVo.getFileName()); + documentSafetyMeeting.setOriginalName(originalFilename); + documentSafetyMeeting.setProjectId(projectId); + documentSafetyMeeting.setPid(pid); + boolean save = this.save(documentSafetyMeeting); + if (!save) { + throw new ServiceException("新增文件失败,数据库异常", HttpStatus.ERROR); + } + // 返回主键 + return documentSafetyMeeting.getId(); + } + + /** + * 批量恢复安全会议纪要信息 + * + * @param ids 待删除的主键集合 + * @return 是否删除成功 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean recoveryBatchById(Collection ids) { + List allParentIdsRecursively = getAllParentIdsRecursively(ids); + // 需要更新状态的文件集合 + allParentIdsRecursively.addAll(ids); + List updateList = allParentIdsRecursively.stream().map(id -> { + BusDocumentSafetyMeeting documentSafetyMeeting = new BusDocumentSafetyMeeting(); + documentSafetyMeeting.setId(id); + documentSafetyMeeting.setFileStatus(DocumentStatusEnum.NORMAL.getValue()); + return documentSafetyMeeting; + }).toList(); + boolean result = this.updateBatchById(updateList); + if (!result) { + throw new ServiceException("恢复文件失败,数据库异常", HttpStatus.ERROR); + } + return true; + } + + private List getAllParentIdsRecursively(Collection ids) { + // 使用 list() 方法批量查询当前 id 列表对应的实体数据 + List fileList = this.lambdaQuery() + .in(BusDocumentSafetyMeeting::getId, ids) + .eq(BusDocumentSafetyMeeting::getFileStatus, DocumentStatusEnum.DELETE.getValue()) + .list(); + // 通过 stream 流过滤出非 0 的父 id,并去重 + List parentIdList = fileList.stream() + .map(BusDocumentSafetyMeeting::getPid) + .filter(pid -> pid != 0) + .distinct() + .collect(Collectors.toList()); + // 如果父 id 列表为空,说明递归终止,返回空列表 + if (parentIdList.isEmpty()) { + return new ArrayList<>(); + } + // 递归查询父 id 列表对应的上级父 id + List higherParentIds = getAllParentIdsRecursively(parentIdList); + // 将当前层的父 id 和上级递归得到的父 id 合并 + List allParentIds = new ArrayList<>(); + allParentIds.addAll(parentIdList); + allParentIds.addAll(higherParentIds); + // 返回合并后去重的结果 + return allParentIds.stream().distinct().collect(Collectors.toList()); + } + + + /** + * 校验父级目录是否存在 + * + * @param pDocumentSafetyMeeting 父级目录 + * @param projectId 当前项目id + */ + private void validParentFolder(BusDocumentSafetyMeeting pDocumentSafetyMeeting, Long projectId) { + // 判断父级目录是否存在 + if (pDocumentSafetyMeeting == null) { + throw new ServiceException("父级目录不存在", HttpStatus.NOT_FOUND); + } + // 判断父级目录是否是文件夹 + if (DocumentTypeEnum.FILE.getValue().equals(pDocumentSafetyMeeting.getFileType())) { + throw new ServiceException("父级目录不是文件夹", HttpStatus.BAD_REQUEST); + } + // 判断是否为同一个项目 + if (!pDocumentSafetyMeeting.getProjectId().equals(projectId)) { + throw new ServiceException("父级目录不属于当前项目", HttpStatus.BAD_REQUEST); + } + } + + /** + * 批量删除安全会议纪要信息 + * + * @param ids 待删除的主键集合 + * @return 是否删除成功 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteWithRecycleBin(Collection ids) { + // 获取所有需要删除的元素 + List allChildIdList = this.getAllChildIdList(ids); + if (CollUtil.isEmpty(allChildIdList)) { + return true; + } + // 批量修改状态为已删除 + List documentSafetyMeetingList = allChildIdList.stream().map(id -> { + BusDocumentSafetyMeeting documentSafetyMeeting = new BusDocumentSafetyMeeting(); + documentSafetyMeeting.setId(id); + documentSafetyMeeting.setDeletedAt(new Date()); + documentSafetyMeeting.setFileStatus(DocumentStatusEnum.DELETE.getValue()); + return documentSafetyMeeting; + }).toList(); + // 批量修改 + boolean result = this.updateBatchById(documentSafetyMeetingList); + if (!result) { + throw new ServiceException("数据库操作失败", HttpStatus.ERROR); + } + return true; + } + + /** + * 彻底批量删除安全会议纪要 + * + * @param ids 待删除的主键集合 + * @return 是否删除成功 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean completelyDelete(Collection ids) { + // 获取所有需要删除的元素 + List allChildIdList = this.getAllChildIdList(ids); + if (CollUtil.isEmpty(allChildIdList)) { + return true; + } + boolean result = this.removeBatchByIds(allChildIdList); + if (!result) { + throw new ServiceException("数据库操作失败", HttpStatus.ERROR); + } + // todo 删除oss文件 + + return true; + } + + /** + * 获取安全会议纪要视图对象 + * + * @param documentSafetyMeeting 安全会议纪要对象 + * @return 安全会议纪要视图对象 + */ + @Override + public BusDocumentSafetyMeetingVo getVo(BusDocumentSafetyMeeting documentSafetyMeeting) { + // 对象转封装类 + BusDocumentSafetyMeetingVo documentSafetyMeetingVo = new BusDocumentSafetyMeetingVo(); + if (documentSafetyMeeting == null) { + return documentSafetyMeetingVo; + } + BeanUtils.copyProperties(documentSafetyMeeting, documentSafetyMeetingVo); + return documentSafetyMeetingVo; + } + + /** + * 获取安全会议纪要查询条件封装 + * + * @param req 安全会议纪要查询条件 + * @return 安全会议纪要查询条件封装 + */ + @Override + public LambdaQueryWrapper buildQueryWrapper(DocumentSafetyMeetingQueryReq req) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + if (req == null) { + return lqw; + } + Long projectId = req.getProjectId(); + Long pid = req.getPid(); + String fileType = req.getFileType(); + String notFileType = req.getNotFileType(); + // 精确查询 + lqw.eq(ObjectUtils.isNotEmpty(projectId), BusDocumentSafetyMeeting::getProjectId, projectId); + lqw.eq(ObjectUtils.isNotEmpty(pid), BusDocumentSafetyMeeting::getPid, pid); + lqw.eq(StringUtils.isNotBlank(fileType), BusDocumentSafetyMeeting::getFileType, fileType); + // 不等于 + lqw.ne(StringUtils.isNotBlank(notFileType), BusDocumentSafetyMeeting::getFileType, notFileType); + return lqw; + } + + /** + * 获取安全会议纪要分页对象视图 + * + * @param documentSafetyMeetingPage 安全会议纪要分页对象 + * @return 安全会议纪要分页对象视图 + */ + @Override + public Page getVoPage(Page documentSafetyMeetingPage) { + // 获取安全会议纪要列表 + List documentSafetyMeetingList = documentSafetyMeetingPage.getRecords(); + // 添加分页信息 + Page documentSafetyMeetingVoPage = new Page<>( + documentSafetyMeetingPage.getCurrent(), + documentSafetyMeetingPage.getSize(), + documentSafetyMeetingPage.getTotal()); + if (CollUtil.isEmpty(documentSafetyMeetingList)) { + return documentSafetyMeetingVoPage; + } + // 对象列表 => 封装对象列表 + List documentSafetyMeetingVoList = documentSafetyMeetingList + .stream().map(this::getVo).toList(); + documentSafetyMeetingVoPage.setRecords(documentSafetyMeetingVoList); + return documentSafetyMeetingVoPage; + } + + /** + * 递归查询所有的文件和文件夹以及文件夹下的子文件夹的id + * + * @param ids 主键集合 + * @return 整合所有的id集合 + */ + @Override + public List getAllChildIdList(Collection ids) { + List idList = new ArrayList<>(); + for (Long id : ids) { + // 将当前id加入集合 + idList.add(id); + // 查询当前记录(判断是否为文件夹) + BusDocumentSafetyMeeting record = this.getById(id); + if (record != null && DocumentTypeEnum.FOLDER.getValue().equals(record.getFileType())) { + // 如果是文件夹,递归查询子节点 + getChildIds(id, idList); + } + } + return idList; + } + + /** + * 递归查询给定父级id下所有子文件和子文件夹的id + * + * @param parentId 父级文件夹id + * @param ids 存放id的集合(递归过程中不断添加) + */ + private void getChildIds(Long parentId, List ids) { + // 条件查询,查询pid为parentId的记录 + List childList = this.lambdaQuery() + .eq(BusDocumentSafetyMeeting::getPid, parentId) + .eq(BusDocumentSafetyMeeting::getFileStatus, DocumentStatusEnum.NORMAL.getValue()) + .list(); + // 遍历所有子记录 + for (BusDocumentSafetyMeeting child : childList) { + ids.add(child.getId()); + // 如果子节点是文件夹,继续递归 + if (DocumentTypeEnum.FOLDER.getValue().equals(child.getFileType())) { + getChildIds(child.getId(), ids); + } + } + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusTeamMeetingServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusTeamMeetingServiceImpl.java index d9fb07af..3c71560b 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusTeamMeetingServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusTeamMeetingServiceImpl.java @@ -14,6 +14,7 @@ import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.project.domain.BusConstructionUser; import org.dromara.project.domain.BusContractor; import org.dromara.project.domain.BusProjectTeam; @@ -28,14 +29,14 @@ import org.dromara.safety.domain.req.teammeeting.TeamMeetingUpdateReq; import org.dromara.safety.domain.vo.BusTeamMeetingVo; import org.dromara.safety.mapper.BusTeamMeetingMapper; import org.dromara.safety.service.IBusTeamMeetingService; +import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.service.ISysOssService; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.Date; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; /** * 站班会Service业务层处理 @@ -181,8 +182,12 @@ public class BusTeamMeetingServiceImpl extends ServiceImpl ids, Boolean isValid) { + Long userId = LoginHelper.getUserId(); + List teamMeetingList = this.listByIds(ids); if (isValid) { // TODO 做一些业务上的校验,判断是否需要校验 + List projectId = teamMeetingList.stream().map(BusTeamMeeting::getProjectId).toList(); + projectService.validAuth(projectId, userId); } return this.removeBatchByIds(ids); } @@ -209,7 +214,7 @@ public class BusTeamMeetingServiceImpl extends ServiceImpl ossIdList = Arrays.stream(picture.split(",")).map(Long::parseLong).toList(); + List sysOssVoList = ossService.listByIds(ossIdList); + List pictureUrlList = sysOssVoList.stream().map(SysOssVo::getUrl).toList(); + teamMeetingVo.setPictureUrlList(pictureUrlList); } return teamMeetingVo; } @@ -300,8 +313,77 @@ public class BusTeamMeetingServiceImpl extends ServiceImpl teamIdList = teamMeetingList.stream().map(BusTeamMeeting::getTeamId).collect(Collectors.toSet()); + Map> teamMap = projectTeamService.listByIds(teamIdList) + .stream().collect(Collectors.groupingBy(BusProjectTeam::getId)); + // 获取对应分包公司 + Set contractorIdList = teamMeetingList.stream().map(BusTeamMeeting::getContractorId).collect(Collectors.toSet()); + Map> contractorMap = contractorService.listByIds(contractorIdList) + .stream().collect(Collectors.groupingBy(BusContractor::getId)); + // 获取对应参会人 + Set userIdList = new HashSet<>(); + for (BusTeamMeeting teamMeeting : teamMeetingList) { + String participantId = teamMeeting.getParticipantId(); + userIdList.addAll(JSONUtil.toList(participantId, Long.class)); + } + // 获取对应宣讲人 + Set compereIdList = teamMeetingList.stream().map(BusTeamMeeting::getCompereId).collect(Collectors.toSet()); + userIdList.addAll(compereIdList); + Map> userMap = constructionUserService.listByIds(userIdList) + .stream().collect(Collectors.groupingBy(BusConstructionUser::getId)); + // 获取对应文件信息 + Set ossIdList = teamMeetingList.stream().map(BusTeamMeeting::getPicture).filter(StringUtils::isNotBlank) + .flatMap(ossId -> Arrays.stream(ossId.split(",")).map(Long::parseLong)).collect(Collectors.toSet()); + Map> ossMap = ossService.listByIds(ossIdList) + .stream().collect(Collectors.groupingBy(SysOssVo::getOssId)); // 对象列表 => 封装对象列表 - List teamMeetingVoList = teamMeetingList.stream().map(this::getVo).toList(); + List teamMeetingVoList = teamMeetingList.stream().map(teamMeeting -> { + BusTeamMeetingVo teamMeetingVo = new BusTeamMeetingVo(); + BeanUtils.copyProperties(teamMeeting, teamMeetingVo); + // 关联班组信息 + String teamName = null; + if (teamMap.containsKey(teamMeeting.getTeamId())) { + teamName = teamMap.get(teamMeeting.getTeamId()).get(0).getTeamName(); + } + teamMeetingVo.setTeamName(teamName); + // 关联分包公司信息 + String contractorName = null; + if (contractorMap.containsKey(teamMeeting.getContractorId())) { + contractorName = contractorMap.get(teamMeeting.getContractorId()).get(0).getName(); + } + teamMeetingVo.setContractorName(contractorName); + // 关联宣讲人信息 + String compereName = null; + if (userMap.containsKey(teamMeeting.getCompereId())) { + compereName = userMap.get(teamMeeting.getCompereId()).get(0).getUserName(); + } + teamMeetingVo.setCompereName(compereName); + // 关联参会人信息 + List participantList = new ArrayList<>(); + String participantId = teamMeeting.getParticipantId(); + List idList = JSONUtil.toList(participantId, Long.class); + if (CollUtil.isNotEmpty(idList)) { + for (Long userId : idList) { + if (userMap.containsKey(userId)) { + BusConstructionUser constructionUser = userMap.get(userId).get(0); + participantList.add(IdAndNameVO.build(constructionUser.getId(), constructionUser.getUserName())); + } + } + } + teamMeetingVo.setParticipantList(participantList); + // 关联文件信息 + List pictureUrlList = new ArrayList<>(); + List pictureIdList = Arrays.stream(teamMeeting.getPicture().split(",")).map(Long::parseLong).toList(); + for (Long pictureId : pictureIdList) { + if (ossMap.containsKey(pictureId)) { + SysOssVo sysOssVo = ossMap.get(pictureId).get(0); + pictureUrlList.add(sysOssVo.getUrl()); + } + } + teamMeetingVo.setPictureUrlList(pictureUrlList); + return teamMeetingVo; + }).toList(); teamMeetingVoPage.setRecords(teamMeetingVoList); return teamMeetingVoPage; } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java index 9d18f6d4..e789799e 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java @@ -61,6 +61,15 @@ public interface ISysOssService { */ SysOssUploadVo uploadWithNoSave(MultipartFile file); + /** + * 上传 MultipartFile 到对象存储服务,不保存文件信息到数据库 + * + * @param file 要上传的 MultipartFile 对象 + * @param filePath 文件路径 + * @return 上传成功后的 SysOssVo 对象,包含文件信息 + */ + SysOssUploadVo uploadWithNoSave(MultipartFile file, String filePath); + /** * 上传文件到对象存储服务,并保存文件信息到数据库 * diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index e1650448..bd054508 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -227,6 +227,29 @@ public class SysOssServiceImpl implements ISysOssService, OssService { return uploadVo; } + /** + * 上传 MultipartFile 到对象存储服务,不保存文件信息到数据库 + * + * @param file 要上传的 MultipartFile 对象 + * @param filePath 文件路径 + * @return 上传成功后的 SysOssVo 对象,包含文件信息 + */ + @Override + public SysOssUploadVo uploadWithNoSave(MultipartFile file, String filePath) { + String originalFilename = file.getOriginalFilename(); + OssClient storage = OssFactory.instance(); + UploadResult uploadResult; + try { + uploadResult = storage.uploadFilePath(file.getBytes(), filePath, file.getContentType()); + } catch (IOException e) { + throw new ServiceException(e.getMessage()); + } + SysOssUploadVo uploadVo = new SysOssUploadVo(); + uploadVo.setUrl(uploadResult.getUrl()); + uploadVo.setFileName(originalFilename); + return uploadVo; + } + /** * 上传文件到对象存储服务,并保存文件信息到数据库 * diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/safety/BusDocumentSafetyMeetingMapper.xml b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/safety/BusDocumentSafetyMeetingMapper.xml new file mode 100644 index 00000000..11fe780a --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/safety/BusDocumentSafetyMeetingMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql b/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql index 1b5d39f9..b3e0b0a5 100644 --- a/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql +++ b/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql @@ -655,3 +655,26 @@ CREATE TABLE `bus_daily_piece_item` PRIMARY KEY (`id`) USING BTREE, INDEX `idx_report_id` (`report_id` ASC) USING BTREE comment '日报id' ) comment = '施工人员日报计件信息' collate = utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `bus_document_safety_meeting`; +CREATE TABLE `bus_document_safety_meeting` +( + `id` bigint not null auto_increment comment '主键id', + `project_id` bigint null comment '项目id', + `pid` bigint default 0 null comment '父级(0代表顶级)', + `file_name` varchar(255) null comment '文件名称', + `file_path` varchar(512) null comment '文件路径', + `file_type` char(1) not null comment '文件类型(1文件-2文件夹-3图片)', + `file_suffix` varchar(20) null comment '文件后缀', + `file_status` char(1) default '0' null comment '状态(0正常 1删除)', + `original_name` varchar(255) null comment '原文件名', + `remark` varchar(512) null comment '备注', + `create_by` varchar(64) null comment '创建者', + `update_by` varchar(64) null comment '更新者', + `create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间', + `update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间', + `deleted_at` datetime null comment '删除时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_pid` (`pid` ASC) USING BTREE, + INDEX `idx_project_id` (`project_id` ASC) USING BTREE +) comment = '安全会议纪要' COLLATE = utf8mb4_unicode_ci;